diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -310,6 +310,7 @@ char ifname[IFNAMSIZ]; char label[PF_RULE_LABEL_SIZE]; bool kill_match; + bool nat; }; struct pfctl_state_peer { diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -1468,6 +1468,7 @@ nvlist_add_string(nvl, "ifname", kill->ifname); nvlist_add_string(nvl, "label", kill->label); nvlist_add_bool(nvl, "kill_match", kill->kill_match); + nvlist_add_bool(nvl, "nat", kill->nat); if ((ret = pfctl_do_ioctl(dev, ioctlval, 1024, &nvl)) != 0) return (ret); diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8 --- a/sbin/pfctl/pfctl.8 +++ b/sbin/pfctl/pfctl.8 @@ -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 February 22, 2021 +.Dd October 20, 2023 .Dt PFCTL 8 .Os .Sh NAME @@ -43,7 +43,7 @@ .Op Fl K Ar host | network .Xo .Oo Fl k -.Ar host | network | label | id | gateway +.Ar host | network | label | id | gateway | nat .Oc Xc .Op Fl o Ar level .Op Fl p Ar device @@ -256,15 +256,16 @@ entries from the first host/network to the second. .It Xo .Fl k -.Ar host | network | label | id | gateway +.Ar host | network | label | id | gateway | nat .Xc Kill all of the state entries matching the specified .Ar host , .Ar network , .Ar label , .Ar id , +.Ar gateway, or -.Ar gateway. +.Ar nat. .Pp For example, to kill all of the state entries originating from .Dq host : @@ -332,6 +333,10 @@ .Pp .Dl # pfctl -k gateway -k 192.168.0.0/24 .Pp +States can also be killed based on their pre-NAT address: +.Pp +.Dl # pfctl -k nat -k 192.168.0.1 +.Pp .It Fl M Kill matching states in the opposite direction (on other interfaces) when killing states. diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -725,6 +725,12 @@ sizeof(kill.ifname)) >= sizeof(kill.ifname)) errx(1, "invalid interface: %s", iface); + if (state_killers == 2 && (strcmp(state_kill[0], "nat") == 0)) { + kill.nat = true; + state_kill[0] = state_kill[1]; + state_killers = 1; + } + pfctl_addrprefix(state_kill[0], &kill.src.addr.v.a.mask); if (opts & PF_OPT_KILLMATCH) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1770,6 +1770,7 @@ char psk_label[PF_RULE_LABEL_SIZE]; u_int psk_killed; bool psk_kill_match; + bool psk_nat; }; #endif 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 @@ -2249,7 +2249,7 @@ /* For floating states look at the original kif. */ kif = s->kif == V_pfi_all ? s->orig_kif : s->kif; - sk = s->key[PF_SK_WIRE]; + sk = s->key[psk->psk_nat ? PF_SK_STACK : PF_SK_WIRE]; if (s->direction == PF_OUT) { srcaddr = &sk->addr[1]; dstaddr = &sk->addr[0]; @@ -2308,10 +2308,10 @@ if (s->direction == PF_OUT) { dir = PF_IN; - idx = PF_SK_STACK; + idx = psk->psk_nat ? PF_SK_WIRE : PF_SK_STACK; } else { dir = PF_OUT; - idx = PF_SK_WIRE; + idx = psk->psk_nat ? PF_SK_STACK : PF_SK_WIRE; } match_key.af = s->key[idx]->af; diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c --- a/sys/netpfil/pf/pf_nv.c +++ b/sys/netpfil/pf/pf_nv.c @@ -873,6 +873,9 @@ sizeof(kill->psk_label))); PFNV_CHK(pf_nvbool(nvl, "kill_match", &kill->psk_kill_match)); + if (nvlist_exists_bool(nvl, "nat")) + PFNV_CHK(pf_nvbool(nvl, "nat", &kill->psk_nat)); + errout: return (error); }