[Midnightbsd-cvs] src: pf/pfctl: Deal with merge conflicts
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Tue Nov 11 15:28:59 EST 2008
Log Message:
-----------
Deal with merge conflicts
Modified Files:
--------------
src/contrib/pf/authpf:
authpf.8 (r1.2 -> r1.3)
src/contrib/pf/pfctl:
pfctl.c (r1.3 -> r1.4)
-------------- next part --------------
Index: authpf.8
===================================================================
RCS file: /home/cvs/src/contrib/pf/authpf/authpf.8,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/pf/authpf/authpf.8 -L contrib/pf/authpf/authpf.8 -u -r1.2 -r1.3
--- contrib/pf/authpf/authpf.8
+++ contrib/pf/authpf/authpf.8
@@ -1,29 +1,19 @@
-.\" $FreeBSD: src/contrib/pf/authpf/authpf.8,v 1.1.1.3.2.1 2006/03/30 08:14:55 mlaier Exp $
-.\" $OpenBSD: authpf.8,v 1.38 2005/01/04 09:57:04 jmc Exp $
+.\" $FreeBSD: src/contrib/pf/authpf/authpf.8,v 1.3 2007/07/03 12:30:00 mlaier Exp $
+.\" $OpenBSD: authpf.8,v 1.43 2007/02/24 17:21:04 beck Exp $
.\"
-.\" Copyright (c) 2002 Bob Beck (beck at openbsd.org>. All rights reserved.
+.\" Copyright (c) 1998-2007 Bob Beck (beck at openbsd.org>. All rights reserved.
.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd March 28, 2006
.Dt AUTHPF 8
@@ -230,8 +220,11 @@
hijack the session.
Note that TCP keepalives are not sufficient for
this, since they are not secure.
-Also note that
+Also note that the various SSH tunnelling mechanisms,
+such as
.Ar AllowTcpForwarding
+and
+.Ar PermitTunnel ,
should be disabled for
.Nm
users to prevent them from circumventing restrictions imposed by the
@@ -429,8 +422,7 @@
external_if = "xl0"
internal_if = "fxp0"
-pass in log quick on $internal_if proto tcp from $user_ip to any \e
- keep state
+pass in log quick on $internal_if proto tcp from $user_ip to any
pass in quick on $internal_if from $user_ip to any
.Ed
.Pp
@@ -445,16 +437,15 @@
# rdr ftp for proxying by ftp-proxy(8)
rdr on $internal_if proto tcp from $user_ip to any port 21 \e
- -> 127.0.0.1 port 8081
+ -> 127.0.0.1 port 8021
# allow out ftp, ssh, www and https only, and allow user to negotiate
# ipsec with the ipsec server.
pass in log quick on $internal_if proto tcp from $user_ip to any \e
- port { 21, 22, 80, 443 } flags S/SA
+ port { 21, 22, 80, 443 }
pass in quick on $internal_if proto tcp from $user_ip to any \e
port { 21, 22, 80, 443 }
-pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp \e
- keep state
+pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp
pass in quick proto esp from $user_ip to $ipsec_gw
.Ed
.Pp
@@ -469,7 +460,7 @@
# nat and tag connections...
nat on $ext_if from $user_ip to any tag $user_ip -> $ext_addr
pass in quick on $int_if from $user_ip to any
-pass out log quick on $ext_if tagged $user_ip keep state
+pass out log quick on $ext_if tagged $user_ip
.Ed
.Pp
With the above rules added by
@@ -495,7 +486,7 @@
.Bd -literal
table <authpf_users> persist
pass in on $ext_if proto tcp from <authpf_users> \e
- to port { smtp imap } keep state
+ to port { smtp imap }
.Ed
.Pp
It is also possible to use the "authpf_users"
@@ -522,6 +513,7 @@
.Xr pf 4 ,
.Xr pf.conf 5 ,
.Xr fdescfs 5 ,
+.Xr securelevel 7 ,
.Xr ftp-proxy 8
.Sh HISTORY
The
Index: pfctl.c
===================================================================
RCS file: /home/cvs/src/contrib/pf/pfctl/pfctl.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L contrib/pf/pfctl/pfctl.c -L contrib/pf/pfctl/pfctl.c -u -r1.3 -r1.4
--- contrib/pf/pfctl/pfctl.c
+++ contrib/pf/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.234 2005/03/07 13:52:50 henning Exp $ */
+/* $OpenBSD: pfctl.c,v 1.262 2007/03/01 17:20:53 deraadt Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/contrib/pf/pfctl/pfctl.c,v 1.6 2005/05/03 16:55:20 mlaier Exp $");
+__FBSDID("$FreeBSD: src/contrib/pf/pfctl/pfctl.c,v 1.7 2007/07/03 12:30:02 mlaier Exp $");
#include <sys/types.h>
#include <sys/ioctl.h>
@@ -44,6 +44,7 @@
#include <net/pfvar.h>
#include <arpa/inet.h>
#include <altq/altq.h>
+#include <sys/sysctl.h>
#include <err.h>
#include <errno.h>
@@ -60,10 +61,6 @@
#ifdef __FreeBSD__
#define HTONL(x) (x) = htonl((__uint32_t)(x))
-#endif
-
-#ifdef __MidnightBSD__
-#define HTONL(x) (x) = htonl((__uint32_t)(x))
#endif
void usage(void);
@@ -76,6 +73,8 @@
int pfctl_clear_altq(int, int);
int pfctl_clear_src_nodes(int, int);
int pfctl_clear_states(int, const char *, int);
+void pfctl_addrprefix(char *, struct pf_addr *);
+int pfctl_kill_src_nodes(int, const char *, int);
int pfctl_kill_states(int, const char *, int);
void pfctl_init_options(struct pfctl *);
int pfctl_load_options(struct pfctl *);
@@ -87,7 +86,7 @@
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);
-int pfctl_show_rules(int, int, int, char *);
+int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int);
int pfctl_show_nat(int, int, char *);
int pfctl_show_src_nodes(int, int);
int pfctl_show_states(int, const char *, int);
@@ -95,20 +94,29 @@
int pfctl_show_timeouts(int, int);
int pfctl_show_limits(int, 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 *);
+int pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *);
+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 **);
+struct pf_anchor_global pf_anchors;
+struct pf_anchor pf_main_anchor;
+
const char *clearopt;
char *rulesopt;
const char *showopt;
const char *debugopt;
char *anchoropt;
+const char *optiopt = NULL;
char *pf_device = "/dev/pf";
char *ifaceopt;
char *tableopt;
const char *tblcmdopt;
+int src_node_killers;
+char *src_node_kill[2];
int state_killers;
char *state_kill[2];
int loadopt;
@@ -120,14 +128,25 @@
const char *infile;
+#define INDENT(d, o) do { \
+ if (o) { \
+ int i; \
+ for (i=0; i < d; i++) \
+ printf(" "); \
+ } \
+ } while (0); \
+
+
static const struct {
const char *name;
int index;
} pf_limits[] = {
- { "states", PF_LIMIT_STATES },
- { "src-nodes", PF_LIMIT_SRC_NODES },
- { "frags", PF_LIMIT_FRAGS },
- { NULL, 0 }
+ { "states", PF_LIMIT_STATES },
+ { "src-nodes", PF_LIMIT_SRC_NODES },
+ { "frags", PF_LIMIT_FRAGS },
+ { "tables", PF_LIMIT_TABLES },
+ { "table-entries", PF_LIMIT_TABLE_ENTRIES },
+ { NULL, 0 }
};
struct pf_hint {
@@ -200,27 +219,28 @@
static const char *tblcmdopt_list[] = {
"kill", "flush", "add", "delete", "load", "replace", "show",
- "test", "zero", NULL
+ "test", "zero", "expire", NULL
};
static const char *debugopt_list[] = {
"none", "urgent", "misc", "loud", NULL
};
+static const char *optiopt_list[] = {
+ "o", "none", "basic", "profile", NULL
+};
void
usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s [-AdeghmNnOoqRrvz] ", __progname);
+ fprintf(stderr, "usage: %s [-AdeghmNnOqRrvz] ", __progname);
fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
- fprintf(stderr, " ");
- fprintf(stderr, "[-f file] [-i interface] [-k host] ");
- fprintf(stderr, "[-p device] [-s modifier]\n");
- fprintf(stderr, " ");
- fprintf(stderr, "[-t table -T command [address ...]] ");
- fprintf(stderr, "[-x level]\n");
+ fprintf(stderr, "\t[-f file] [-i interface] [-K host | network] ");
+ fprintf(stderr, "[-k host | network ]\n");
+ fprintf(stderr, "\t[-o [level]] [-p device] [-s modifier ]\n");
+ fprintf(stderr, "\t[-t table -T command [address ...]] [-x level]\n");
exit(1);
}
@@ -232,12 +252,7 @@
errx(1, "pf already enabled");
#ifdef __FreeBSD__
else if (errno == ESRCH)
-
- errx(1, "pfil registration failed");
-#endif
-#ifdef __MidnightBSD__
- else if (errno == ESRCH)
- errx(1, "pfil registration failed");
+ errx(1, "pfil registeration failed");
#endif
else
err(1, "DIOCSTART");
@@ -288,7 +303,7 @@
if ((opts & PF_OPT_NOACTION) == 0) {
bzero(&pi, sizeof(pi));
- pi.pfiio_flags = PFI_IFLAG_SETABLE_MASK;
+ pi.pfiio_flags = PFI_IFLAG_SKIP;
if (ioctl(dev, DIOCCLRIFFLAG, &pi))
err(1, "DIOCCLRIFFLAG");
@@ -378,6 +393,163 @@
return (0);
}
+void
+pfctl_addrprefix(char *addr, struct pf_addr *mask)
+{
+ char *p;
+ const char *errstr;
+ int prefix, ret_ga, q, r;
+ struct addrinfo hints, *res;
+
+ if ((p = strchr(addr, '/')) == NULL)
+ return;
+
+ *p++ = '\0';
+ prefix = strtonum(p, 0, 128, &errstr);
+ if (errstr)
+ errx(1, "prefix is %s: %s", errstr, p);
+
+ bzero(&hints, sizeof(hints));
+ /* prefix only with numeric addresses */
+ hints.ai_flags |= AI_NUMERICHOST;
+
+ if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) {
+ errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
+ /* NOTREACHED */
+ }
+
+ if (res->ai_family == AF_INET && prefix > 32)
+ errx(1, "prefix too long for AF_INET");
+ else if (res->ai_family == AF_INET6 && prefix > 128)
+ errx(1, "prefix too long for AF_INET6");
+
+ q = prefix >> 3;
+ r = prefix & 7;
+ switch (res->ai_family) {
+ case AF_INET:
+ bzero(&mask->v4, sizeof(mask->v4));
+ mask->v4.s_addr = htonl((u_int32_t)
+ (0xffffffffffULL << (32 - prefix)));
+ break;
+ case AF_INET6:
+ bzero(&mask->v6, sizeof(mask->v6));
+ if (q > 0)
+ memset((void *)&mask->v6, 0xff, q);
+ if (r > 0)
+ *((u_char *)&mask->v6 + q) =
+ (0xff00 >> r) & 0xff;
+ break;
+ }
+ freeaddrinfo(res);
+}
+
+int
+pfctl_kill_src_nodes(int dev, const char *iface, int opts)
+{
+ struct pfioc_src_node_kill psnk;
+ struct addrinfo *res[2], *resp[2];
+ struct sockaddr last_src, last_dst;
+ int killed, sources, dests;
+ int ret_ga;
+
+ killed = sources = dests = 0;
+
+ memset(&psnk, 0, sizeof(psnk));
+ memset(&psnk.psnk_src.addr.v.a.mask, 0xff,
+ sizeof(psnk.psnk_src.addr.v.a.mask));
+ memset(&last_src, 0xff, sizeof(last_src));
+ memset(&last_dst, 0xff, sizeof(last_dst));
+
+ pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask);
+
+ if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) {
+ errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
+ /* NOTREACHED */
+ }
+ for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
+ if (resp[0]->ai_addr == NULL)
+ continue;
+ /* We get lots of duplicates. Catch the easy ones */
+ if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
+ continue;
+ last_src = *(struct sockaddr *)resp[0]->ai_addr;
+
+ psnk.psnk_af = resp[0]->ai_family;
+ sources++;
+
+ if (psnk.psnk_af == AF_INET)
+ psnk.psnk_src.addr.v.a.addr.v4 =
+ ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
+ else if (psnk.psnk_af == AF_INET6)
+ psnk.psnk_src.addr.v.a.addr.v6 =
+ ((struct sockaddr_in6 *)resp[0]->ai_addr)->
+ sin6_addr;
+ else
+ errx(1, "Unknown address family %d", psnk.psnk_af);
+
+ if (src_node_killers > 1) {
+ dests = 0;
+ memset(&psnk.psnk_dst.addr.v.a.mask, 0xff,
+ sizeof(psnk.psnk_dst.addr.v.a.mask));
+ memset(&last_dst, 0xff, sizeof(last_dst));
+ pfctl_addrprefix(src_node_kill[1],
+ &psnk.psnk_dst.addr.v.a.mask);
+ if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL,
+ &res[1]))) {
+ errx(1, "getaddrinfo: %s",
+ gai_strerror(ret_ga));
+ /* NOTREACHED */
+ }
+ for (resp[1] = res[1]; resp[1];
+ resp[1] = resp[1]->ai_next) {
+ if (resp[1]->ai_addr == NULL)
+ continue;
+ if (psnk.psnk_af != resp[1]->ai_family)
+ continue;
+
+ if (memcmp(&last_dst, resp[1]->ai_addr,
+ sizeof(last_dst)) == 0)
+ continue;
+ last_dst = *(struct sockaddr *)resp[1]->ai_addr;
+
+ dests++;
+
+ if (psnk.psnk_af == AF_INET)
+ psnk.psnk_dst.addr.v.a.addr.v4 =
+ ((struct sockaddr_in *)resp[1]->
+ ai_addr)->sin_addr;
+ else if (psnk.psnk_af == AF_INET6)
+ psnk.psnk_dst.addr.v.a.addr.v6 =
+ ((struct sockaddr_in6 *)resp[1]->
+ ai_addr)->sin6_addr;
+ else
+ errx(1, "Unknown address family %d",
+ psnk.psnk_af);
+
+ if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
+ err(1, "DIOCKILLSRCNODES");
+ killed += psnk.psnk_af;
+ /* fixup psnk.psnk_af */
+ psnk.psnk_af = resp[1]->ai_family;
+ }
+ freeaddrinfo(res[1]);
+ } else {
+ if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
+ err(1, "DIOCKILLSRCNODES");
+ killed += psnk.psnk_af;
+ /* fixup psnk.psnk_af */
+ psnk.psnk_af = res[0]->ai_family;
+ }
+ }
+
+ freeaddrinfo(res[0]);
+
+ if ((opts & PF_OPT_QUIET) == 0)
+ fprintf(stderr, "killed %d src nodes from %d sources and %d "
+ "destinations\n", killed, sources, dests);
+ return (0);
+}
+
int
pfctl_kill_states(int dev, const char *iface, int opts)
{
@@ -398,6 +570,8 @@
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
errx(1, "invalid interface: %s", iface);
+ pfctl_addrprefix(state_kill[0], &psk.psk_src.addr.v.a.mask);
+
if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
/* NOTREACHED */
@@ -428,6 +602,8 @@
memset(&psk.psk_dst.addr.v.a.mask, 0xff,
sizeof(psk.psk_dst.addr.v.a.mask));
memset(&last_dst, 0xff, sizeof(last_dst));
+ pfctl_addrprefix(state_kill[1],
+ &psk.psk_dst.addr.v.a.mask);
if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
&res[1]))) {
errx(1, "getaddrinfo: %s",
@@ -520,6 +696,17 @@
}
void
+pfctl_move_pool(struct pf_pool *src, struct pf_pool *dst)
+{
+ struct pf_pooladdr *pa;
+
+ while ((pa = TAILQ_FIRST(&src->list)) != NULL) {
+ TAILQ_REMOVE(&src->list, pa, entries);
+ TAILQ_INSERT_TAIL(&dst->list, pa, entries);
+ }
+}
+
+void
pfctl_clear_pool(struct pf_pool *pool)
{
struct pf_pooladdr *pa;
@@ -553,12 +740,18 @@
printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
rule->qname, rule->qid, rule->pqname, rule->pqid);
}
- if (opts & PF_OPT_VERBOSE)
+ if (opts & PF_OPT_VERBOSE) {
printf(" [ Evaluations: %-8llu Packets: %-8llu "
"Bytes: %-10llu States: %-6u]\n",
(unsigned long long)rule->evaluations,
- (unsigned long long)rule->packets,
- (unsigned long long)rule->bytes, rule->states);
+ (unsigned long long)(rule->packets[0] +
+ rule->packets[1]),
+ (unsigned long long)(rule->bytes[0] +
+ rule->bytes[1]), rule->states);
+ if (!(opts & PF_OPT_DEBUG))
+ printf(" [ Inserted: uid %u pid %u ]\n",
+ (unsigned)rule->cuid, (unsigned)rule->cpid);
+ }
}
void
@@ -571,99 +764,160 @@
}
int
-pfctl_show_rules(int dev, int opts, int format, char *anchorname)
+pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
+ char *anchorname, int depth)
{
struct pfioc_rule pr;
u_int32_t nr, mnr, header = 0;
int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
+ int len = strlen(path);
+ int brace;
+ char *p;
+
+ if (path[0])
+ snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
+ else
+ snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
memset(&pr, 0, sizeof(pr));
- memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
+ memcpy(pr.anchor, path, sizeof(pr.anchor));
if (opts & PF_OPT_SHOWALL) {
pr.rule.action = PF_PASS;
if (ioctl(dev, DIOCGETRULES, &pr)) {
warn("DIOCGETRULES");
- return (-1);
+ goto error;
}
header++;
}
pr.rule.action = PF_SCRUB;
if (ioctl(dev, DIOCGETRULES, &pr)) {
warn("DIOCGETRULES");
- return (-1);
+ goto error;
}
if (opts & PF_OPT_SHOWALL) {
- if (format == 0 && (pr.nr > 0 || header))
+ if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header))
pfctl_print_title("FILTER RULES:");
- else if (format == 1 && labels)
+ else if (format == PFCTL_SHOW_LABELS && labels)
pfctl_print_title("LABEL COUNTERS:");
}
mnr = pr.nr;
+ if (opts & PF_OPT_CLRRULECTRS)
+ pr.action = PF_GET_CLR_CNTR;
+
for (nr = 0; nr < mnr; ++nr) {
pr.nr = nr;
if (ioctl(dev, DIOCGETRULE, &pr)) {
warn("DIOCGETRULE");
- return (-1);
+ goto error;
}
if (pfctl_get_pool(dev, &pr.rule.rpool,
- nr, pr.ticket, PF_SCRUB, anchorname) != 0)
- return (-1);
+ nr, pr.ticket, PF_SCRUB, path) != 0)
+ goto error;
switch (format) {
- case 1:
+ case PFCTL_SHOW_LABELS:
if (pr.rule.label[0]) {
printf("%s ", pr.rule.label);
- printf("%llu %llu %llu\n",
+ printf("%llu %llu %llu %llu %llu %llu %llu\n",
(unsigned long long)pr.rule.evaluations,
- (unsigned long long)pr.rule.packets,
- (unsigned long long)pr.rule.bytes);
+ (unsigned long long)(pr.rule.packets[0] +
+ pr.rule.packets[1]),
+ (unsigned long long)(pr.rule.bytes[0] +
+ pr.rule.bytes[1]),
+ (unsigned long long)pr.rule.packets[0],
+ (unsigned long long)pr.rule.bytes[0],
+ (unsigned long long)pr.rule.packets[1],
+ (unsigned long long)pr.rule.bytes[1]);
}
break;
- default:
+ case PFCTL_SHOW_RULES:
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
labels = 1;
print_rule(&pr.rule, pr.anchor_call, rule_numbers);
+ printf("\n");
pfctl_print_rule_counters(&pr.rule, opts);
+ break;
+ case PFCTL_SHOW_NOTHING:
+ break;
}
pfctl_clear_pool(&pr.rule.rpool);
}
pr.rule.action = PF_PASS;
if (ioctl(dev, DIOCGETRULES, &pr)) {
warn("DIOCGETRULES");
- return (-1);
+ goto error;
}
mnr = pr.nr;
for (nr = 0; nr < mnr; ++nr) {
pr.nr = nr;
if (ioctl(dev, DIOCGETRULE, &pr)) {
warn("DIOCGETRULE");
- return (-1);
+ goto error;
}
if (pfctl_get_pool(dev, &pr.rule.rpool,
- nr, pr.ticket, PF_PASS, anchorname) != 0)
- return (-1);
+ nr, pr.ticket, PF_PASS, path) != 0)
+ goto error;
switch (format) {
- case 1:
+ case PFCTL_SHOW_LABELS:
if (pr.rule.label[0]) {
printf("%s ", pr.rule.label);
- printf("%llu %llu %llu\n",
+ printf("%llu %llu %llu %llu %llu %llu %llu\n",
(unsigned long long)pr.rule.evaluations,
- (unsigned long long)pr.rule.packets,
- (unsigned long long)pr.rule.bytes);
+ (unsigned long long)(pr.rule.packets[0] +
+ pr.rule.packets[1]),
+ (unsigned long long)(pr.rule.bytes[0] +
+ pr.rule.bytes[1]),
+ (unsigned long long)pr.rule.packets[0],
+ (unsigned long long)pr.rule.bytes[0],
+ (unsigned long long)pr.rule.packets[1],
+ (unsigned long long)pr.rule.bytes[1]);
}
break;
- default:
+ case PFCTL_SHOW_RULES:
+ brace = 0;
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
labels = 1;
- print_rule(&pr.rule, pr.anchor_call, rule_numbers);
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ if (pr.anchor_call[0] &&
+ ((((p = strrchr(pr.anchor_call, '_')) != NULL) &&
+ ((void *)p == (void *)pr.anchor_call ||
+ *(--p) == '/')) || (opts & PF_OPT_RECURSE))) {
+ brace++;
+ if ((p = strrchr(pr.anchor_call, '/')) !=
+ NULL)
+ p++;
+ else
+ p = &pr.anchor_call[0];
+ } else
+ p = &pr.anchor_call[0];
+
+ print_rule(&pr.rule, p, rule_numbers);
+ if (brace)
+ printf(" {\n");
+ else
+ printf("\n");
pfctl_print_rule_counters(&pr.rule, opts);
+ if (brace) {
+ pfctl_show_rules(dev, path, opts, format,
+ p, depth + 1);
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ printf("}\n");
+ }
+ break;
+ case PFCTL_SHOW_NOTHING:
+ break;
}
pfctl_clear_pool(&pr.rule.rpool);
}
+ path[len] = '\0';
return (0);
+
+ error:
+ path[len] = '\0';
+ return (-1);
}
int
@@ -698,6 +952,7 @@
}
print_rule(&pr.rule, pr.anchor_call,
opts & PF_OPT_VERBOSE2);
+ printf("\n");
pfctl_print_rule_counters(&pr.rule, opts);
pfctl_clear_pool(&pr.rule.rpool);
}
@@ -725,16 +980,17 @@
}
if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) {
warn("DIOCGETSRCNODES");
+ free(inbuf);
return (-1);
}
if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len)
break;
if (len == 0 && psn.psn_len == 0)
- return (0);
+ goto done;
if (len == 0 && psn.psn_len != 0)
len = psn.psn_len;
if (psn.psn_len == 0)
- return (0); /* no src_nodes */
+ goto done; /* no src_nodes */
len *= 2;
}
p = psn.psn_src_nodes;
@@ -744,6 +1000,8 @@
print_src_node(p, opts);
p++;
}
+done:
+ free(inbuf);
return (0);
}
@@ -767,16 +1025,17 @@
}
if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
warn("DIOCGETSTATES");
+ free(inbuf);
return (-1);
}
if (ps.ps_len + sizeof(struct pfioc_states) < len)
break;
if (len == 0 && ps.ps_len == 0)
- return (0);
+ goto done;
if (len == 0 && ps.ps_len != 0)
len = ps.ps_len;
if (ps.ps_len == 0)
- return (0); /* no states */
+ goto done; /* no states */
len *= 2;
}
p = ps.ps_states;
@@ -789,6 +1048,8 @@
}
print_state(p, opts);
}
+done:
+ free(inbuf);
return (0);
}
@@ -845,11 +1106,11 @@
pl.index = pf_limits[i].index;
if (ioctl(dev, DIOCGETLIMIT, &pl))
err(1, "DIOCGETLIMIT");
- printf("%-10s ", pf_limits[i].name);
+ printf("%-13s ", pf_limits[i].name);
if (pl.limit == UINT_MAX)
printf("unlimited\n");
else
- printf("hard limit %6u\n", pl.limit);
+ printf("hard limit %8u\n", pl.limit);
}
return (0);
}
@@ -880,93 +1141,186 @@
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
{
u_int8_t rs_num;
- struct pfioc_rule pr;
+ struct pf_rule *rule;
+ struct pf_ruleset *rs;
+ char *p;
- switch (r->action) {
- case PF_SCRUB:
- case PF_NOSCRUB:
- if ((loadopt & PFCTL_FLAG_FILTER) == 0)
- return (0);
- rs_num = PF_RULESET_SCRUB;
- break;
- case PF_DROP:
- case PF_PASS:
- if ((loadopt & PFCTL_FLAG_FILTER) == 0)
- return (0);
- rs_num = PF_RULESET_FILTER;
- break;
- case PF_NAT:
- case PF_NONAT:
- if ((loadopt & PFCTL_FLAG_NAT) == 0)
- return (0);
- rs_num = PF_RULESET_NAT;
- break;
- case PF_RDR:
- case PF_NORDR:
- if ((loadopt & PFCTL_FLAG_NAT) == 0)
- return (0);
- rs_num = PF_RULESET_RDR;
- break;
- case PF_BINAT:
- case PF_NOBINAT:
- if ((loadopt & PFCTL_FLAG_NAT) == 0)
- return (0);
- rs_num = PF_RULESET_BINAT;
- break;
- default:
+ rs_num = pf_get_ruleset_number(r->action);
+ if (rs_num == PF_RULESET_MAX)
errx(1, "Invalid rule type %d", r->action);
- break;
- }
+ rs = &pf->anchor->ruleset;
- if ((pf->opts & PF_OPT_OPTIMIZE) && rs_num == PF_RULESET_FILTER) {
- /*
- * We'll do an optimization post-pass before finally adding the
- * rules. Then we'll disable the optimization flag and feed
- * the rules right back into this function.
+ if (anchor_call[0] && r->anchor == NULL) {
+ /*
+ * Don't make non-brace anchors part of the main anchor pool.
*/
- struct pf_opt_rule *pfr;
- struct pf_pooladdr *pa;
+ if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
+ err(1, "pfctl_add_rule: calloc");
+
+ pf_init_ruleset(&r->anchor->ruleset);
+ r->anchor->ruleset.anchor = r->anchor;
+ if (strlcpy(r->anchor->path, anchor_call,
+ sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
+ errx(1, "pfctl_add_rule: strlcpy");
+ if ((p = strrchr(anchor_call, '/')) != NULL) {
+ if (!strlen(p))
+ err(1, "pfctl_add_rule: bad anchor name %s",
+ anchor_call);
+ } else
+ p = (char *)anchor_call;
+ if (strlcpy(r->anchor->name, p,
+ sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
+ errx(1, "pfctl_add_rule: strlcpy");
+ }
- if ((pfr = calloc(1, sizeof(*pfr))) == NULL)
- err(1, "calloc");
- memcpy(&pfr->por_rule, r, sizeof(*r));
- if (strlcpy(pfr->por_anchor, anchor_call,
- sizeof(pfr->por_anchor)) >= sizeof(pfr->por_anchor))
- errx(1, "pfctl_add_rule: strlcpy");
- TAILQ_INSERT_TAIL(&pf->opt_queue, pfr, por_entry);
-
- if (TAILQ_FIRST(&r->rpool.list) != NULL) {
- TAILQ_INIT(&pfr->por_rule.rpool.list);
- while ((pa = TAILQ_FIRST(&r->rpool.list)) != NULL) {
- TAILQ_REMOVE(&r->rpool.list, pa, entries);
- TAILQ_INSERT_TAIL(&pfr->por_rule.rpool.list, pa,
- entries);
+ if ((rule = calloc(1, sizeof(*rule))) == NULL)
+ err(1, "calloc");
+ bcopy(r, rule, sizeof(*rule));
+ TAILQ_INIT(&rule->rpool.list);
+ pfctl_move_pool(&r->rpool, &rule->rpool);
+
+ TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries);
+ return (0);
+}
+
+int
+pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a)
+{
+ int osize = pf->trans->pfrb_size;
+
+ if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) {
+ if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) ||
+ pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) ||
+ pfctl_add_trans(pf->trans, PF_RULESET_RDR, path))
+ return (1);
+ }
+ if (a == pf->astack[0] && ((altqsupport &&
+ (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
+ if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path))
+ return (2);
+ }
+ if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) {
+ if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) ||
+ pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path))
+ return (3);
+ }
+ if (pf->loadopt & PFCTL_FLAG_TABLE)
+ if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path))
+ return (4);
+ if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize))
+ return (5);
+
+ return (0);
+}
+
+int
+pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs,
+ int rs_num, int depth)
+{
+ struct pf_rule *r;
+ int error, len = strlen(path);
+ int brace = 0;
+
+ pf->anchor = rs->anchor;
+
+ if (path[0])
+ snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name);
+ else
+ snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name);
+
+ if (depth) {
+ if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) {
+ brace++;
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf(" {\n");
+ if ((pf->opts & PF_OPT_NOACTION) == 0 &&
+ (error = pfctl_ruleset_trans(pf,
+ path, rs->anchor))) {
+ printf("pfctl_load_rulesets: "
+ "pfctl_ruleset_trans %d\n", error);
+ goto error;
}
- } else {
- memset(&pfr->por_rule.rpool, 0,
- sizeof(pfr->por_rule.rpool));
+ } else if (pf->opts & PF_OPT_VERBOSE)
+ printf("\n");
- }
- return (0);
}
+ if (pf->optimize && rs_num == PF_RULESET_FILTER)
+ pfctl_optimize_ruleset(pf, rs);
+
+ while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) {
+ TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries);
+ if ((error = pfctl_load_rule(pf, path, r, depth)))
+ goto error;
+ if (r->anchor) {
+ if ((error = pfctl_load_ruleset(pf, path,
+ &r->anchor->ruleset, rs_num, depth + 1)))
+ goto error;
+ } else if (pf->opts & PF_OPT_VERBOSE)
+ printf("\n");
+ free(r);
+ }
+ if (brace && pf->opts & PF_OPT_VERBOSE) {
+ INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE));
+ printf("}\n");
+ }
+ path[len] = '\0';
+ return (0);
+
+ error:
+ path[len] = '\0';
+ return (error);
+
+}
+
+int
+pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth)
+{
+ u_int8_t rs_num = pf_get_ruleset_number(r->action);
+ char *name;
+ struct pfioc_rule pr;
+ int len = strlen(path);
+
+ bzero(&pr, sizeof(pr));
+ /* set up anchor before adding to path for anchor_call */
+ if ((pf->opts & PF_OPT_NOACTION) == 0)
+ pr.ticket = pfctl_get_ticket(pf->trans, rs_num, path);
+ if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor))
+ errx(1, "pfctl_load_rule: strlcpy");
+
+ if (r->anchor) {
+ if (r->anchor->match) {
+ if (path[0])
+ snprintf(&path[len], MAXPATHLEN - len,
+ "/%s", r->anchor->name);
+ else
+ snprintf(&path[len], MAXPATHLEN - len,
+ "%s", r->anchor->name);
+ name = path;
+ } else
+ name = r->anchor->path;
+ } else
+ name = "";
+
if ((pf->opts & PF_OPT_NOACTION) == 0) {
- bzero(&pr, sizeof(pr));
- if (strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)) >=
- sizeof(pr.anchor))
- errx(1, "pfctl_add_rule: strlcpy");
if (pfctl_add_pool(pf, &r->rpool, r->af))
return (1);
- pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor);
pr.pool_ticket = pf->paddr.ticket;
memcpy(&pr.rule, r, sizeof(pr.rule));
- strlcpy(pr.anchor_call, anchor_call, sizeof(pr.anchor_call));
+ if (r->anchor && strlcpy(pr.anchor_call, name,
+ sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call))
+ errx(1, "pfctl_load_rule: strlcpy");
if (ioctl(pf->dev, DIOCADDRULE, &pr))
err(1, "DIOCADDRULE");
}
- if (pf->opts & PF_OPT_VERBOSE)
- print_rule(r, anchor_call, pf->opts & PF_OPT_VERBOSE2);
+
+ if (pf->opts & PF_OPT_VERBOSE) {
+ INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
+ print_rule(r, r->anchor ? r->anchor->name : "",
+ pf->opts & PF_OPT_VERBOSE2);
+ }
+ path[len] = '\0';
pfctl_clear_pool(&r->rpool);
return (0);
}
@@ -994,86 +1348,86 @@
}
int
-pfctl_rules(int dev, char *filename, int opts, char *anchorname,
- struct pfr_buffer *trans)
+pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
+ char *anchorname, struct pfr_buffer *trans)
{
#define ERR(x) do { warn(x); goto _error; } while(0)
#define ERRX(x) do { warnx(x); goto _error; } while(0)
- FILE *fin;
struct pfr_buffer *t, buf;
struct pfioc_altq pa;
struct pfctl pf;
+ struct pf_ruleset *rs;
struct pfr_table trs;
+ char *path;
int osize;
+ RB_INIT(&pf_anchors);
+ memset(&pf_main_anchor, 0, sizeof(pf_main_anchor));
+ pf_init_ruleset(&pf_main_anchor.ruleset);
+ pf_main_anchor.ruleset.anchor = &pf_main_anchor;
if (trans == NULL) {
- bzero(&buf, sizeof(buf));
- buf.pfrb_type = PFRB_TRANS;
- t = &buf;
- osize = 0;
+ bzero(&buf, sizeof(buf));
+ buf.pfrb_type = PFRB_TRANS;
+ t = &buf;
+ osize = 0;
} else {
- t = trans;
- osize = t->pfrb_size;
+ t = trans;
+ osize = t->pfrb_size;
}
memset(&pa, 0, sizeof(pa));
memset(&pf, 0, sizeof(pf));
memset(&trs, 0, sizeof(trs));
+ if ((path = calloc(1, MAXPATHLEN)) == NULL)
+ ERRX("pfctl_rules: calloc");
if (strlcpy(trs.pfrt_anchor, anchorname,
sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
ERRX("pfctl_rules: strlcpy");
- if (strcmp(filename, "-") == 0) {
- fin = stdin;
- infile = "stdin";
- } else {
- if ((fin = pfctl_fopen(filename, "r")) == NULL) {
- warn("%s", filename);
- return (1);
- }
- infile = filename;
- }
+ infile = filename;
pf.dev = dev;
pf.opts = opts;
+ pf.optimize = optimize;
pf.loadopt = loadopt;
+
+ /* non-brace anchor, create without resolving the path */
+ if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL)
+ ERRX("pfctl_rules: calloc");
+ rs = &pf.anchor->ruleset;
+ pf_init_ruleset(rs);
+ rs->anchor = pf.anchor;
+ if (strlcpy(pf.anchor->path, anchorname,
+ sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path))
+ errx(1, "pfctl_add_rule: strlcpy");
+ if (strlcpy(pf.anchor->name, anchorname,
+ sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name))
+ errx(1, "pfctl_add_rule: strlcpy");
+
+
+ pf.astack[0] = pf.anchor;
+ pf.asd = 0;
if (anchorname[0])
pf.loadopt &= ~PFCTL_FLAG_ALTQ;
pf.paltq = &pa;
pf.trans = t;
- 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) {
- if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname) ||
- pfctl_add_trans(t, PF_RULESET_BINAT, anchorname) ||
- pfctl_add_trans(t, PF_RULESET_RDR, anchorname))
- ERR("pfctl_rules");
- }
- if (((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))) {
- if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname))
- ERR("pfctl_rules");
- }
- if ((pf.loadopt & PFCTL_FLAG_FILTER) != 0) {
- if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname) ||
- pfctl_add_trans(t, PF_RULESET_FILTER, anchorname))
- ERR("pfctl_rules");
- }
- if (pf.loadopt & PFCTL_FLAG_TABLE) {
- if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname))
- ERR("pfctl_rules");
- }
- if (pfctl_trans(dev, t, DIOCXBEGIN, osize))
- ERR("DIOCXBEGIN");
+ /*
+ * XXX For the time being we need to open transactions for
+ * the main ruleset before parsing, because tables are still
+ * loaded at parse time.
+ */
+ if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor))
+ ERRX("pfctl_rules");
if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ))
- pa.ticket = pfctl_get_ticket(t, PF_RULESET_ALTQ,
- anchorname);
+ pa.ticket =
+ pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname);
if (pf.loadopt & PFCTL_FLAG_TABLE)
- pf.tticket = pfctl_get_ticket(t, PF_RULESET_TABLE,
- anchorname);
+ pf.astack[0]->ruleset.tticket =
+ pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname);
}
+
if (parse_rules(fin, &pf) < 0) {
if ((opts & PF_OPT_NOACTION) == 0)
ERRX("Syntax error in config file: "
@@ -1081,9 +1435,19 @@
else
goto _error;
}
- if (pf.opts & PF_OPT_OPTIMIZE) {
- if (pfctl_optimize_rules(&pf))
- ERRX("Failed to optimize ruleset: pf rules not loaded");
+
+ if ((pf.loadopt & PFCTL_FLAG_FILTER &&
+ (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) ||
+ (pf.loadopt & PFCTL_FLAG_NAT &&
+ (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) ||
+ pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) ||
+ pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) ||
+ (pf.loadopt & PFCTL_FLAG_FILTER &&
+ pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) {
+ if ((opts & PF_OPT_NOACTION) == 0)
+ ERRX("Unable to load rules into kernel");
+ else
+ goto _error;
}
if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))
@@ -1097,14 +1461,14 @@
/* process "load anchor" directives */
if (!anchorname[0])
- if (pfctl_load_anchors(dev, opts, t) == -1)
+ if (pfctl_load_anchors(dev, &pf, t) == -1)
ERRX("load anchors");
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))
+ if (pfctl_trans(dev, t, DIOCXCOMMIT, osize))
ERR("DIOCXCOMMIT");
}
return (0);
@@ -1112,7 +1476,7 @@
_error:
if (trans == NULL) { /* main ruleset */
if ((opts & PF_OPT_NOACTION) == 0)
- if (pfctl_trans(dev, t, DIOCXROLLBACK, 0))
+ if (pfctl_trans(dev, t, DIOCXROLLBACK, osize))
err(1, "DIOCXROLLBACK");
exit(1);
} else { /* sub ruleset */
@@ -1149,6 +1513,9 @@
void
pfctl_init_options(struct pfctl *pf)
{
+ int mib[2], mem;
+ size_t size;
+
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;
@@ -1167,10 +1534,21 @@
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->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
+ pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
- pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
- pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT;
- pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
+ pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
+ pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT;
+ pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
+ pf->limit[PF_LIMIT_TABLES] = PFR_KTABLE_HIWAT;
+ pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_PHYSMEM;
+ size = sizeof(mem);
+ (void) sysctl(mib, 2, &mem, &size, NULL, 0);
+ if (mem <= 100*1024*1024)
+ pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL;
pf->debug = PF_DEBUG_URGENT;
}
@@ -1191,6 +1569,21 @@
error = 1;
}
+ /*
+ * If we've set the limit, but havn't explicitly set adaptive
+ * timeouts, do it now with a start of 60% and end of 120%.
+ */
+ if (pf->limit_set[PF_LIMIT_STATES] &&
+ !pf->timeout_set[PFTM_ADAPTIVE_START] &&
+ !pf->timeout_set[PFTM_ADAPTIVE_END]) {
+ pf->timeout[PFTM_ADAPTIVE_START] =
+ (pf->limit[PF_LIMIT_STATES] / 10) * 6;
+ pf->timeout_set[PFTM_ADAPTIVE_START] = 1;
+ pf->timeout[PFTM_ADAPTIVE_END] =
+ (pf->limit[PF_LIMIT_STATES] / 10) * 12;
+ pf->timeout_set[PFTM_ADAPTIVE_END] = 1;
+ }
+
/* load timeouts */
for (i = 0; i < PFTM_MAX; i++) {
if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i])
@@ -1317,7 +1710,7 @@
hint = pf_hints[i].hint;
if (hint == NULL) {
- warnx("Bad hint name.");
+ warnx("invalid state timeouts optimization");
return (1);
}
@@ -1363,7 +1756,7 @@
memset(&pi, 0, sizeof(pi));
if (ifname && strlcpy(pi.ifname, ifname,
sizeof(pi.ifname)) >= sizeof(pi.ifname)) {
- warnx("pfctl_set_logif: strlcpy");
+ warnx("pfctl_load_logif: strlcpy");
return (1);
}
if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) {
@@ -1500,22 +1893,10 @@
}
int
-pfctl_clear_rule_counters(int dev, int opts)
-{
- if (ioctl(dev, DIOCCLRRULECTRS))
- err(1, "DIOCCLRRULECTRS");
- if ((opts & PF_OPT_QUIET) == 0)
- fprintf(stderr, "pf: rule counters cleared\n");
- return (0);
-}
-
-int
pfctl_test_altqsupport(int dev, int opts)
{
-#if defined(__MidnightBSD__) && !defined(ENABLE_ALTQ)
+#if defined(__FreeBSD__) && !defined(ENABLE_ALTQ)
return (0);
-#elseif defined(__FreeBSD__) && !defined(ENABLE_ALTQ)
- return (0);
#else
struct pfioc_altq pa;
@@ -1563,8 +1944,9 @@
strlcat(sub, "/", sizeof(sub));
}
strlcat(sub, pr.name, sizeof(sub));
- printf(" %s\n", sub);
- if (opts & PF_OPT_VERBOSE && pfctl_show_anchors(dev, opts, sub))
+ if (sub[0] != '_' || (opts & PF_OPT_VERBOSE))
+ printf(" %s\n", sub);
+ if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub))
return (-1);
}
return (0);
@@ -1583,17 +1965,20 @@
int
main(int argc, char *argv[])
{
- int error = 0;
- int ch;
- int mode = O_RDONLY;
- int opts = 0;
- char anchorname[MAXPATHLEN];
+ int error = 0;
+ int ch;
+ int mode = O_RDONLY;
+ int opts = 0;
+ int optimize = 0;
+ char anchorname[MAXPATHLEN];
+ char *path;
+ FILE *fin = NULL;
if (argc < 2)
usage();
while ((ch = getopt(argc, argv,
- "a:AdD:eqf:F:ghi:k:mnNOop:rRs:t:T:vx:z")) != -1) {
+ "a:AdD:eqf:F:ghi:k:K:mnNOo::p:rRs:t:T:vx:z")) != -1) {
switch (ch) {
case 'a':
anchoropt = optarg;
@@ -1634,6 +2019,15 @@
state_kill[state_killers++] = optarg;
mode = O_RDWR;
break;
+ case 'K':
+ if (src_node_killers >= 2) {
+ warnx("can only specify -K twice");
+ usage();
+ /* NOTREACHED */
+ }
+ src_node_kill[src_node_killers++] = optarg;
+ mode = O_RDWR;
+ break;
case 'm':
opts |= PF_OPT_MERGE;
break;
@@ -1660,10 +2054,25 @@
loadopt |= PFCTL_FLAG_FILTER;
break;
case 'o':
- if (opts & PF_OPT_OPTIMIZE)
- opts |= PF_OPT_OPTIMIZE_PROFILE;
- else
- opts |= PF_OPT_OPTIMIZE;
+ if (optarg) {
+ optiopt = pfctl_lookup_option(optarg,
+ optiopt_list);
+ if (optiopt == NULL) {
+ warnx("Unknown optimization '%s'",
+ optarg);
+ usage();
+ }
+ }
+ if (opts & PF_OPT_OPTIMIZE) {
+ if (optiopt != NULL) {
+ warnx("Cannot specify -o multiple times"
+ "with optimizer level");
+ usage();
+ }
+ optimize |= PF_OPTIMIZE_PROFILE;
+ }
+ optimize |= PF_OPTIMIZE_BASIC;
+ opts |= PF_OPT_OPTIMIZE;
break;
case 'O':
loadopt |= PFCTL_FLAG_OPTION;
@@ -1721,7 +2130,7 @@
loadopt |= PFCTL_FLAG_TABLE;
tblcmdopt = NULL;
} else
- mode = strchr("acdfkrz", ch) ? O_RDWR : O_RDONLY;
+ mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY;
} else if (argc != optind) {
warnx("unknown command line argument: %s ...", argv[optind]);
usage();
@@ -1730,8 +2139,19 @@
if (loadopt == 0)
loadopt = ~0;
+ if ((path = calloc(1, MAXPATHLEN)) == NULL)
+ errx(1, "pfctl: calloc");
memset(anchorname, 0, sizeof(anchorname));
if (anchoropt != NULL) {
+ int len = strlen(anchoropt);
+
+ if (anchoropt[len - 1] == '*') {
+ if (len >= 2 && anchoropt[len - 2] == '/')
+ anchoropt[len - 2] = '\0';
+ else
+ anchoropt[len - 1] = '\0';
+ opts |= PF_OPT_RECURSE;
+ }
if (strlcpy(anchorname, anchoropt,
sizeof(anchorname)) >= sizeof(anchorname))
errx(1, "anchor name '%s' too long",
@@ -1751,7 +2171,7 @@
/* turn off options */
opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
clearopt = showopt = debugopt = NULL;
-#if defined(__MidnightBSD__) && !defined(ENABLE_ALTQ)
+#if defined(__FreeBSD__) && !defined(ENABLE_ALTQ)
altqsupport = 0;
#else
altqsupport = 1;
@@ -1769,11 +2189,13 @@
break;
case 'r':
pfctl_load_fingerprints(dev, opts);
- pfctl_show_rules(dev, opts, 0, anchorname);
+ pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES,
+ anchorname, 0);
break;
case 'l':
pfctl_load_fingerprints(dev, opts);
- pfctl_show_rules(dev, opts, 1, anchorname);
+ pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS,
+ anchorname, 0);
break;
case 'n':
pfctl_load_fingerprints(dev, opts);
@@ -1803,12 +2225,12 @@
pfctl_load_fingerprints(dev, opts);
pfctl_show_nat(dev, opts, anchorname);
- pfctl_show_rules(dev, opts, 0, anchorname);
+ pfctl_show_rules(dev, path, opts, 0, anchorname, 0);
pfctl_show_altq(dev, ifaceopt, opts, 0);
pfctl_show_states(dev, ifaceopt, opts);
pfctl_show_src_nodes(dev, opts);
pfctl_show_status(dev, opts);
- pfctl_show_rules(dev, opts, 1, anchorname);
+ pfctl_show_rules(dev, path, opts, 1, anchorname, 0);
pfctl_show_timeouts(dev, opts);
pfctl_show_limits(dev, opts);
pfctl_show_tables(anchorname, opts);
@@ -1827,7 +2249,15 @@
}
}
+ if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL)
+ pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
+ anchorname, 0);
+
if (clearopt != NULL) {
+ if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
+ errx(1, "anchor names beginning with '_' cannot "
+ "be modified from the command line");
+
switch (*clearopt) {
case 'r':
pfctl_clear_rules(dev, opts, anchorname);
@@ -1871,13 +2301,40 @@
if (state_killers)
pfctl_kill_states(dev, ifaceopt, opts);
+ if (src_node_killers)
+ pfctl_kill_src_nodes(dev, ifaceopt, opts);
+
if (tblcmdopt != NULL) {
error = pfctl_command_tables(argc, argv, tableopt,
tblcmdopt, rulesopt, anchorname, opts);
rulesopt = NULL;
}
+ if (optiopt != NULL) {
+ switch (*optiopt) {
+ case 'n':
+ optimize = 0;
+ break;
+ case 'b':
+ optimize |= PF_OPTIMIZE_BASIC;
+ break;
+ case 'o':
+ case 'p':
+ optimize |= PF_OPTIMIZE_PROFILE;
+ break;
+ }
+ }
- if ((rulesopt != NULL) && (!*anchorname))
+ if (rulesopt != NULL) {
+ if (strcmp(rulesopt, "-") == 0) {
+ fin = stdin;
+ rulesopt = "stdin";
+ } else {
+ if ((fin = pfctl_fopen(rulesopt, "r")) == NULL)
+ err(1, "%s", rulesopt);
+ }
+ }
+ if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) &&
+ !anchorname[0])
if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET))
error = 1;
@@ -1887,7 +2344,11 @@
error = 1;
if (rulesopt != NULL) {
- if (pfctl_rules(dev, rulesopt, opts, anchorname, NULL))
+ if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
+ errx(1, "anchor names beginning with '_' cannot "
+ "be modified from the command line");
+ if (pfctl_rules(dev, rulesopt, fin, opts, optimize,
+ anchorname, NULL))
error = 1;
else if (!(opts & PF_OPT_NOACTION) &&
(loadopt & PFCTL_FLAG_TABLE))
@@ -1915,9 +2376,5 @@
}
}
- if (opts & PF_OPT_CLRRULECTRS) {
- if (pfctl_clear_rule_counters(dev, opts))
- error = 1;
- }
exit(error);
}
More information about the Midnightbsd-cvs
mailing list