aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2021-04-29 13:10:50 +0000
committerKristof Provost <kp@FreeBSD.org>2021-05-14 08:20:32 +0000
commitf756e230f5e68ce589d3cca81726d5c01db0d0cf (patch)
treebbc7e85ac32faceb678dde7e3f7d83cea90cd340
parent1cbb276258a4e7d5133da02e318bfe4edc2f7f80 (diff)
downloadsrc-f756e230f5e68ce589d3cca81726d5c01db0d0cf.tar.gz
src-f756e230f5e68ce589d3cca81726d5c01db0d0cf.zip
pfctl: Start using DIOCCLRSTATESNV
MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D30053 (cherry picked from commit 53714a586133fd8ae662427007f84ec663cd83ef)
-rw-r--r--lib/libpfctl/libpfctl.c59
-rw-r--r--lib/libpfctl/libpfctl.h18
-rw-r--r--sbin/pfctl/pfctl.c21
3 files changed, 88 insertions, 10 deletions
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index b07fcda9bd5a..8c8b21d22a46 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -608,3 +608,62 @@ pfctl_set_keepcounters(int dev, bool keep)
free(nv.data);
return (ret);
}
+
+static void
+pfctl_nv_add_state_cmp(nvlist_t *nvl, const char *name,
+ const struct pfctl_state_cmp *cmp)
+{
+ nvlist_t *nv;
+
+ nv = nvlist_create(0);
+
+ nvlist_add_number(nv, "id", cmp->id);
+ nvlist_add_number(nv, "creatorid", cmp->creatorid);
+ nvlist_add_number(nv, "direction", cmp->direction);
+
+ nvlist_add_nvlist(nvl, name, nv);
+}
+
+int
+pfctl_clear_states(int dev, const struct pfctl_kill *kill,
+ unsigned int *killed)
+{
+ struct pfioc_nv nv;
+ nvlist_t *nvl;
+ int ret;
+
+ nvl = nvlist_create(0);
+
+ pfctl_nv_add_state_cmp(nvl, "cmp", &kill->cmp);
+ nvlist_add_number(nvl, "af", kill->af);
+ nvlist_add_number(nvl, "proto", kill->proto);
+ pfctl_nv_add_rule_addr(nvl, "src", &kill->src);
+ pfctl_nv_add_rule_addr(nvl, "dst", &kill->dst);
+ nvlist_add_string(nvl, "ifname", kill->ifname);
+ nvlist_add_string(nvl, "label", kill->label);
+
+ nv.data = nvlist_pack(nvl, &nv.len);
+ nv.size = nv.len;
+ nvlist_destroy(nvl);
+ nvl = NULL;
+
+ ret = ioctl(dev, DIOCCLRSTATESNV, &nv);
+ if (ret != 0) {
+ free(nv.data);
+ return (ret);
+ }
+
+ nvl = nvlist_unpack(nv.data, nv.len, 0);
+ if (nvl == NULL) {
+ free(nv.data);
+ return (EIO);
+ }
+
+ if (killed)
+ *killed = nvlist_get_number(nvl, "killed");
+
+ nvlist_destroy(nvl);
+ free(nv.data);
+
+ return (ret);
+}
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index e19187fc2526..3ec2a7fa535f 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -179,6 +179,22 @@ RB_PROTOTYPE(pfctl_anchor_global, pfctl_anchor, entry_global,
RB_PROTOTYPE(pfctl_anchor_node, pfctl_anchor, entry_node,
pf_anchor_compare);
+struct pfctl_state_cmp {
+ uint64_t id;
+ uint32_t creatorid;
+ uint8_t direction;
+};
+
+struct pfctl_kill {
+ struct pfctl_state_cmp cmp;
+ sa_family_t af;
+ int proto;
+ struct pf_rule_addr src;
+ struct pf_rule_addr dst;
+ char ifname[IFNAMSIZ];
+ char label[PF_RULE_LABEL_SIZE];
+};
+
int pfctl_get_rule(int dev, u_int32_t nr, u_int32_t ticket,
const char *anchor, u_int32_t ruleset, struct pfctl_rule *rule,
char *anchor_call);
@@ -189,5 +205,7 @@ int pfctl_add_rule(int dev, const struct pfctl_rule *r,
const char *anchor, const char *anchor_call, u_int32_t ticket,
u_int32_t pool_ticket);
int pfctl_set_keepcounters(int dev, bool keep);
+int pfctl_clear_states(int dev, const struct pfctl_kill *kill,
+ unsigned int *killed);
#endif
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index af2ae6fe3bf0..2cfca24c0cfa 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -79,7 +79,7 @@ int pfctl_clear_rules(int, int, char *);
int pfctl_clear_nat(int, int, char *);
int pfctl_clear_altq(int, int);
int pfctl_clear_src_nodes(int, int);
-int pfctl_clear_states(int, const char *, int);
+int pfctl_clear_iface_states(int, const char *, int);
void pfctl_addrprefix(char *, struct pf_addr *);
int pfctl_kill_src_nodes(int, const char *, int);
int pfctl_net_kill_states(int, const char *, int);
@@ -467,19 +467,20 @@ pfctl_clear_src_nodes(int dev, int opts)
}
int
-pfctl_clear_states(int dev, const char *iface, int opts)
+pfctl_clear_iface_states(int dev, const char *iface, int opts)
{
- struct pfioc_state_kill psk;
+ struct pfctl_kill kill;
+ unsigned int killed;
- memset(&psk, 0, sizeof(psk));
- if (iface != NULL && strlcpy(psk.psk_ifname, iface,
- sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
+ memset(&kill, 0, sizeof(kill));
+ if (iface != NULL && strlcpy(kill.ifname, iface,
+ sizeof(kill.ifname)) >= sizeof(kill.ifname))
errx(1, "invalid interface: %s", iface);
- if (ioctl(dev, DIOCCLRSTATES, &psk))
+ if (pfctl_clear_states(dev, &kill, &killed))
err(1, "DIOCCLRSTATES");
if ((opts & PF_OPT_QUIET) == 0)
- fprintf(stderr, "%d states cleared\n", psk.psk_killed);
+ fprintf(stderr, "%d states cleared\n", killed);
return (0);
}
@@ -2417,7 +2418,7 @@ main(int argc, char *argv[])
pfctl_clear_altq(dev, opts);
break;
case 's':
- pfctl_clear_states(dev, ifaceopt, opts);
+ pfctl_clear_iface_states(dev, ifaceopt, opts);
break;
case 'S':
pfctl_clear_src_nodes(dev, opts);
@@ -2431,7 +2432,7 @@ main(int argc, char *argv[])
pfctl_clear_tables(anchorname, opts);
if (!*anchorname) {
pfctl_clear_altq(dev, opts);
- pfctl_clear_states(dev, ifaceopt, opts);
+ pfctl_clear_iface_states(dev, ifaceopt, opts);
pfctl_clear_src_nodes(dev, opts);
pfctl_clear_stats(dev, opts);
pfctl_clear_fingerprints(dev, opts);