Page MenuHomeFreeBSD

D30058.diff
No OneTemporary

D30058.diff

diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -191,6 +191,7 @@
int proto;
struct pf_rule_addr src;
struct pf_rule_addr dst;
+ struct pf_rule_addr rt_addr;
char ifname[IFNAMSIZ];
char label[PF_RULE_LABEL_SIZE];
};
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -642,6 +642,7 @@
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);
+ pfctl_nv_add_rule_addr(nvl, "rt_addr", &kill->rt_addr);
nvlist_add_string(nvl, "ifname", kill->ifname);
nvlist_add_string(nvl, "label", kill->label);
diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8
--- a/sbin/pfctl/pfctl.8
+++ b/sbin/pfctl/pfctl.8
@@ -45,7 +45,7 @@
.Op Fl K Ar host | network
.Xo
.Oo Fl k
-.Ar host | network | label | id
+.Ar host | network | label | id | gateway
.Oc Xc
.Op Fl o Ar level
.Op Fl p Ar device
@@ -256,14 +256,15 @@
entries from the first host/network to the second.
.It Xo
.Fl k
-.Ar host | network | label | id
+.Ar host | network | label | id | gateway
.Xc
Kill all of the state entries matching the specified
.Ar host ,
.Ar network ,
.Ar label ,
+.Ar id ,
or
-.Ar id .
+.Ar gateway.
.Pp
For example, to kill all of the state entries originating from
.Dq host :
@@ -317,6 +318,19 @@
firewall with hostid 00000002 use:
.Pp
.Dl # pfctl -k id -k 4823e84500000018/2
+.Pp
+It is also possible to kill states created from a rule with the route-to/reply-to
+parameter set to route the connection through a particular gateway.
+Note that rules routing via the default routing table (not via a route-to
+rule) will have their rt_addr set as 0.0.0.0 or ::.
+To kill all states using a gateway of 192.168.0.1 use:
+.Pp
+.Dl # pfctl -k gateway -k 192.168.0.1
+.Pp
+A network prefix length can also be specified.
+To kill all states using a gateway in 192.168.0.0/24:
+.Pp
+.Dl # pfctl -k gateway -k 192.168.0.0/24
.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
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -83,6 +83,7 @@
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);
+int pfctl_gateway_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 *);
@@ -246,7 +247,7 @@
fprintf(stderr,
"usage: %s [-AdeghmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n"
"\t[-f file] [-i interface] [-K host | network]\n"
- "\t[-k host | network | label | id] [-o level] [-p device]\n"
+ "\t[-k host | network | gateway | label | id] [-o level] [-p device]\n"
"\t[-s modifier] [-t table -T command [address ...]] [-x level]\n",
__progname);
@@ -744,6 +745,67 @@
return (0);
}
+int
+pfctl_gateway_kill_states(int dev, const char *iface, int opts)
+{
+ struct pfctl_kill kill;
+ struct addrinfo *res, *resp;
+ struct sockaddr last_src;
+ unsigned int newkilled;
+ int killed = 0;
+ int ret_ga;
+
+ if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
+ warnx("no gateway specified");
+ usage();
+ }
+
+ memset(&kill, 0, sizeof(kill));
+ memset(&kill.rt_addr.addr.v.a.mask, 0xff,
+ sizeof(kill.rt_addr.addr.v.a.mask));
+ memset(&last_src, 0xff, sizeof(last_src));
+ if (iface != NULL && strlcpy(kill.ifname, iface,
+ sizeof(kill.ifname)) >= sizeof(kill.ifname))
+ errx(1, "invalid interface: %s", iface);
+
+ pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask);
+
+ if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res))) {
+ errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
+ /* NOTREACHED */
+ }
+ for (resp = res; resp; resp = resp->ai_next) {
+ if (resp->ai_addr == NULL)
+ continue;
+ /* We get lots of duplicates. Catch the easy ones */
+ if (memcmp(&last_src, resp->ai_addr, sizeof(last_src)) == 0)
+ continue;
+ last_src = *(struct sockaddr *)resp->ai_addr;
+
+ kill.af = resp->ai_family;
+
+ if (kill.af == AF_INET)
+ kill.rt_addr.addr.v.a.addr.v4 =
+ ((struct sockaddr_in *)resp->ai_addr)->sin_addr;
+ else if (kill.af == AF_INET6)
+ kill.rt_addr.addr.v.a.addr.v6 =
+ ((struct sockaddr_in6 *)resp->ai_addr)->
+ sin6_addr;
+ else
+ errx(1, "Unknown address family %d", kill.af);
+
+ if (pfctl_kill_states(dev, &kill, &newkilled))
+ err(1, "DIOCKILLSTATES");
+ killed += newkilled;
+ }
+
+ freeaddrinfo(res);
+
+ if ((opts & PF_OPT_QUIET) == 0)
+ fprintf(stderr, "killed %d states\n", killed);
+ return (0);
+}
+
int
pfctl_label_kill_states(int dev, const char *iface, int opts)
{
@@ -2455,6 +2517,8 @@
pfctl_label_kill_states(dev, ifaceopt, opts);
else if (!strcmp(state_kill[0], "id"))
pfctl_id_kill_states(dev, ifaceopt, opts);
+ else if (!strcmp(state_kill[0], "gateway"))
+ pfctl_gateway_kill_states(dev, ifaceopt, opts);
else
pfctl_net_kill_states(dev, ifaceopt, opts);
}
diff --git a/share/man/man4/pf.4 b/share/man/man4/pf.4
--- a/share/man/man4/pf.4
+++ b/share/man/man4/pf.4
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 5, 2018
+.Dd May 7, 2021
.Dt PF 4
.Os
.Sh NAME
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1081,6 +1081,7 @@
int psk_proto;
struct pf_rule_addr psk_src;
struct pf_rule_addr psk_dst;
+ struct pf_rule_addr psk_rt_addr;
char psk_ifname[IFNAMSIZ];
char psk_label[PF_RULE_LABEL_SIZE];
u_int psk_killed;
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -2458,6 +2458,10 @@
return (EINVAL);
PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
&kill->psk_dst));
+ if (nvlist_exists_nvlist(nvl, "rt_addr")) {
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(
+ nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr));
+ }
PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname,
sizeof(kill->psk_ifname)));
@@ -2679,6 +2683,12 @@
&psk->psk_dst.addr.v.a.mask, dstaddr, sk->af))
continue;
+ if (! PF_MATCHA(psk->psk_rt_addr.neg,
+ &psk->psk_rt_addr.addr.v.a.addr,
+ &psk->psk_rt_addr.addr.v.a.mask,
+ &s->rt_addr, sk->af))
+ continue;
+
if (psk->psk_src.port_op != 0 &&
! pf_match_port(psk->psk_src.port_op,
psk->psk_src.port[0], psk->psk_src.port[1], srcport))

File Metadata

Mime Type
text/plain
Expires
Wed, Sep 25, 12:30 PM (21 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12757581
Default Alt Text
D30058.diff (6 KB)

Event Timeline