summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpf <mpf@openbsd.org>2008-05-09 13:59:31 +0000
committermpf <mpf@openbsd.org>2008-05-09 13:59:31 +0000
commit316145087cf1ebb10b44bb943d11febb770d72e6 (patch)
tree07e17160753be905bc161786761c6d254ff1955d
parentAdd support for NTT DoCoMo A2502. (diff)
downloadwireguard-openbsd-316145087cf1ebb10b44bb943d11febb770d72e6.tar.xz
wireguard-openbsd-316145087cf1ebb10b44bb943d11febb770d72e6.zip
Add support to kill states by rule label or state id.
Fix printing of the state id in pfctl -ss -vv. Remove the psnk_af hack to return the number of killed states. OK markus, beck. "I like it" henning, deraadt. Manpage help from jmc.
-rw-r--r--sbin/pfctl/pf_print_state.c4
-rw-r--r--sbin/pfctl/pfctl.859
-rw-r--r--sbin/pfctl/pfctl.c98
-rw-r--r--sys/net/pf_ioctl.c31
-rw-r--r--sys/net/pfvar.h8
5 files changed, 158 insertions, 42 deletions
diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c
index 8489c38c73a..ea726184add 100644
--- a/sbin/pfctl/pf_print_state.c
+++ b/sbin/pfctl/pf_print_state.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_print_state.c,v 1.46 2007/08/30 09:28:49 dhartmei Exp $ */
+/* $OpenBSD: pf_print_state.c,v 1.47 2008/05/09 13:59:31 mpf Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -308,7 +308,7 @@ print_state(struct pfsync_state *s, int opts)
}
if (opts & PF_OPT_VERBOSE2) {
printf(" id: %016llx creatorid: %08x%s\n",
- pf_state_counter_from_pfsync(s->id), ntohl(s->creatorid),
+ betoh64(*(u_int64_t *)(s->id)), ntohl(s->creatorid),
((s->sync_flags & PFSTATE_NOSYNC) ? " (no-sync)" : ""));
}
}
diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8
index 1273538d142..d8e510212d4 100644
--- a/sbin/pfctl/pfctl.8
+++ b/sbin/pfctl/pfctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pfctl.8,v 1.134 2008/05/06 03:50:03 mpf Exp $
+.\" $OpenBSD: pfctl.8,v 1.135 2008/05/09 13:59:31 mpf 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: May 6 2008 $
+.Dd $Mdocdate: May 9 2008 $
.Dt PFCTL 8
.Os
.Sh NAME
@@ -41,7 +41,10 @@
.Op Fl f Ar file
.Op Fl i Ar interface
.Op Fl K Ar host | network
-.Op Fl k Ar host | network
+.Xo
+.Oo Fl k
+.Ar host | network | label | id
+.Oc Xc
.Op Fl o Ar level
.Op Fl p Ar device
.Op Fl s Ar modifier
@@ -249,22 +252,28 @@ or
.Fl K Ar network
option may be specified, which will kill all the source tracking
entries from the first host/network to the second.
-.It Fl k Ar host | network
-Kill all of the state entries originating from the specified
-.Ar host
+.It Xo
+.Fl k
+.Ar host | network | label | id
+.Xc
+Kill all of the state entries matching the specified
+.Ar host ,
+.Ar network ,
+.Ar label ,
or
-.Ar network .
+.Ar id .
+.Pp
+For example, to kill all of the state entries originating from
+.Dq host :
+.Pp
+.Dl # pfctl -k host
+.Pp
A second
.Fl k Ar host
or
.Fl k Ar network
option may be specified, which will kill all the state entries
from the first host/network to the second.
-For example, to kill all of the state entries originating from
-.Dq host :
-.Pp
-.Dl # pfctl -k host
-.Pp
To kill all of the state entries from
.Dq host1
to
@@ -281,6 +290,32 @@ To kill all states with the target
.Dq host2 :
.Pp
.Dl # pfctl -k 0.0.0.0/0 -k host2
+.Pp
+It is also possible to kill states by rule label or state ID.
+In this mode the first
+.Fl k
+argument is used to specify the type
+of the second argument.
+The following command would kill all states that have been created
+from rules carrying the label
+.Dq foobar :
+.Pp
+.Dl # pfctl -k label -k foobar
+.Pp
+To kill one specific state by its unique state ID
+(as shown by pfctl -s state -vv),
+use the
+.Ar id
+modifier and as a second argument the state ID and optional creator ID.
+To kill a state with ID 4823e84500000003 use:
+.Pp
+.Dl # pfctl -k id -k 4823e84500000003
+.Pp
+To kill a state with ID 4823e84500000018 created from a backup
+firewall with hostid 00000002 use:
+.Pp
+.Dl # pfctl -k id -k 4823e84500000018/2
+.Pp
.It Fl m
Merge in explicitly given options without resetting those
which are omitted.
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index a9ba4e76b64..ee6b40b6766 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.274 2008/05/06 03:45:21 mpf Exp $ */
+/* $OpenBSD: pfctl.c,v 1.275 2008/05/09 13:59:31 mpf Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -68,7 +68,9 @@ 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);
+int pfctl_net_kill_states(int, const char *, int);
+int pfctl_label_kill_states(int, const char *, int);
+int pfctl_id_kill_states(int, const char *, int);
void pfctl_init_options(struct pfctl *);
int pfctl_load_options(struct pfctl *);
int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
@@ -229,7 +231,7 @@ usage(void)
fprintf(stderr, "usage: %s [-AdeghmNnOqRrvz] ", __progname);
fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
fprintf(stderr, "\t[-f file] [-i interface] [-K host | network] ");
- fprintf(stderr, "[-k host | network]\n");
+ fprintf(stderr, "[-k host | network | label | id]\n");
fprintf(stderr, "\t[-o level] [-p device] [-s modifier]\n");
fprintf(stderr, "\t[-t table -T command [address ...]] [-x level]\n");
exit(1);
@@ -515,17 +517,13 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
err(1, "DIOCKILLSRCNODES");
- killed += psnk.psnk_af;
- /* fixup psnk.psnk_af */
- psnk.psnk_af = resp[1]->ai_family;
+ killed += psnk.psnk_killed;
}
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;
+ killed += psnk.psnk_killed;
}
}
@@ -538,7 +536,7 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
}
int
-pfctl_kill_states(int dev, const char *iface, int opts)
+pfctl_net_kill_states(int dev, const char *iface, int opts)
{
struct pfioc_state_kill psk;
struct addrinfo *res[2], *resp[2];
@@ -625,17 +623,13 @@ pfctl_kill_states(int dev, const char *iface, int opts)
if (ioctl(dev, DIOCKILLSTATES, &psk))
err(1, "DIOCKILLSTATES");
- killed += psk.psk_af;
- /* fixup psk.psk_af */
- psk.psk_af = resp[1]->ai_family;
+ killed += psk.psk_killed;
}
freeaddrinfo(res[1]);
} else {
if (ioctl(dev, DIOCKILLSTATES, &psk))
err(1, "DIOCKILLSTATES");
- killed += psk.psk_af;
- /* fixup psk.psk_af */
- psk.psk_af = res[0]->ai_family;
+ killed += psk.psk_killed;
}
}
@@ -648,6 +642,68 @@ pfctl_kill_states(int dev, const char *iface, int opts)
}
int
+pfctl_label_kill_states(int dev, const char *iface, int opts)
+{
+ struct pfioc_state_kill psk;
+
+ if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
+ warnx("no label specified");
+ usage();
+ }
+ memset(&psk, 0, sizeof(psk));
+ if (iface != NULL && strlcpy(psk.psk_ifname, iface,
+ sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
+ errx(1, "invalid interface: %s", iface);
+
+ if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >=
+ sizeof(psk.psk_label))
+ errx(1, "label too long: %s", state_kill[1]);
+
+ if (ioctl(dev, DIOCKILLSTATES, &psk))
+ err(1, "DIOCKILLSTATES");
+
+ if ((opts & PF_OPT_QUIET) == 0)
+ fprintf(stderr, "killed %d states\n", psk.psk_killed);
+
+ return (0);
+}
+
+int
+pfctl_id_kill_states(int dev, const char *iface, int opts)
+{
+ struct pfioc_state_kill psk;
+
+ if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
+ warnx("no id specified");
+ usage();
+ }
+
+ memset(&psk, 0, sizeof(psk));
+ if ((sscanf(state_kill[1], "%llx/%x",
+ &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2)
+ HTONL(psk.psk_pfcmp.creatorid);
+ else if ((sscanf(state_kill[1], "%llx", &psk.psk_pfcmp.id)) == 1) {
+ psk.psk_pfcmp.creatorid = 0;
+ } else {
+ warnx("wrong id format specified");
+ usage();
+ }
+ if (psk.psk_pfcmp.id == 0) {
+ warnx("cannot kill id 0");
+ usage();
+ }
+
+ psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id);
+ if (ioctl(dev, DIOCKILLSTATES, &psk))
+ err(1, "DIOCKILLSTATES");
+
+ if ((opts & PF_OPT_QUIET) == 0)
+ fprintf(stderr, "killed %d states\n", psk.psk_killed);
+
+ return (0);
+}
+
+int
pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr,
u_int32_t ticket, int r_action, char *anchorname)
{
@@ -2247,8 +2303,14 @@ main(int argc, char *argv[])
break;
}
}
- if (state_killers)
- pfctl_kill_states(dev, ifaceopt, opts);
+ if (state_killers) {
+ if (!strcmp(state_kill[0], "label"))
+ pfctl_label_kill_states(dev, ifaceopt, opts);
+ else if (!strcmp(state_kill[0], "id"))
+ pfctl_id_kill_states(dev, ifaceopt, opts);
+ else
+ pfctl_net_kill_states(dev, ifaceopt, opts);
+ }
if (src_node_killers)
pfctl_kill_src_nodes(dev, ifaceopt, opts);
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 50b319a9b9f..5243d3aea4e 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.195 2008/05/06 03:45:22 mpf Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.196 2008/05/09 13:59:31 mpf Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -1557,7 +1557,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCCLRSTATES: {
struct pf_state *s, *nexts;
struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
- int killed = 0;
+ u_int killed = 0;
for (s = RB_MIN(pf_state_tree_id, &tree_id); s; s = nexts) {
nexts = RB_NEXT(pf_state_tree_id, &tree_id, s);
@@ -1572,7 +1572,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
killed++;
}
}
- psk->psk_af = killed;
+ psk->psk_killed = killed;
#if NPFSYNC
pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
#endif
@@ -1584,7 +1584,22 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_state_key *sk;
struct pf_state_host *src, *dst;
struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
- int killed = 0;
+ u_int killed = 0;
+
+ if (psk->psk_pfcmp.id) {
+ if (psk->psk_pfcmp.creatorid == 0)
+ psk->psk_pfcmp.creatorid = pf_status.hostid;
+ if ((s = pf_find_state_byid(&psk->psk_pfcmp))) {
+#if NPFSYNC > 0
+ /* send immediate delete of state */
+ pfsync_delete_state(s);
+ s->sync_flags |= PFSTATE_NOSYNC;
+#endif
+ pf_unlink_state(s);
+ psk->psk_killed = 1;
+ }
+ break;
+ }
for (s = RB_MIN(pf_state_tree_id, &tree_id); s;
s = nexts) {
@@ -1617,6 +1632,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pf_match_port(psk->psk_dst.port_op,
psk->psk_dst.port[0], psk->psk_dst.port[1],
dst->port)) &&
+ (!psk->psk_label[0] || (s->rule.ptr->label[0] &&
+ !strcmp(psk->psk_label, s->rule.ptr->label))) &&
(!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
s->kif->pfik_name))) {
#if NPFSYNC > 0
@@ -1628,7 +1645,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
killed++;
}
}
- psk->psk_af = killed;
+ psk->psk_killed = killed;
break;
}
@@ -2852,7 +2869,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_state *s;
struct pfioc_src_node_kill *psnk = \
(struct pfioc_src_node_kill *) addr;
- int killed = 0;
+ u_int killed = 0;
RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) {
if (PF_MATCHA(psnk->psnk_src.neg, \
@@ -2882,7 +2899,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (killed > 0)
pf_purge_expired_src_nodes(1);
- psnk->psnk_af = killed;
+ psnk->psnk_killed = killed;
break;
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 340071c3577..d9e27c57787 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.265 2008/05/09 02:44:54 markus Exp $ */
+/* $OpenBSD: pfvar.h,v 1.266 2008/05/09 13:59:31 mpf Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -1351,19 +1351,21 @@ struct pfioc_state {
};
struct pfioc_src_node_kill {
- /* XXX returns the number of src nodes killed in psnk_af */
sa_family_t psnk_af;
struct pf_rule_addr psnk_src;
struct pf_rule_addr psnk_dst;
+ u_int psnk_killed;
};
struct pfioc_state_kill {
- /* XXX returns the number of states killed in psk_af */
+ struct pf_state_cmp psk_pfcmp;
sa_family_t psk_af;
int psk_proto;
struct pf_rule_addr psk_src;
struct pf_rule_addr psk_dst;
char psk_ifname[IFNAMSIZ];
+ char psk_label[PF_RULE_LABEL_SIZE];
+ u_int psk_killed;
};
struct pfioc_states {