Download raw body.
authpf: kill states in the session's routing domain
From: Avinash H. Duduskar <avinash.duduskar@gmail.com>
On Fri, Jul 24, 2026 at 07:43:59AM +0000, Alexandr Nedvedicky wrote:
> Also I'm not sure if the plan for sysctl(2) error handling
> is good. I think better course of action is to do exit(1)
> instead of returning rtable assuming this is what we are
> asking for.
Agreed, exit(1) is better. Falling back to the raw rtable guesses a
mapping, and a wrong guess aims the kill at a domain where nothing
matches, the same silent no-op this diff exists to fix. The sysctl
failing for the table the process runs in should not happen; if it
does, the syslog line records why we bailed.
Updated diff below, thanks for the review.
diff --git a/usr.sbin/authpf/authpf.c b/usr.sbin/authpf/authpf.c
index ab227dc6d19..a2ab2de8356 100644
--- a/usr.sbin/authpf/authpf.c
+++ b/usr.sbin/authpf/authpf.c
@@ -20,12 +20,14 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/sysctl.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/pfvar.h>
+#include <net/route.h>
#include <err.h>
#include <errno.h>
@@ -51,6 +53,7 @@ static int remove_stale_rulesets(void);
static int recursive_ruleset_purge(char *, char *);
static int change_filter(int, const char *, const char *);
static int change_table(int, const char *);
+static u_int authpf_rdomain(void);
static void authpf_kill_states(void);
int dev; /* pf device */
@@ -889,6 +892,32 @@ change_table(int add, const char *ipsrc)
return (0);
}
+/*
+ * Map the process routing table to its routing domain; a policy-routing
+ * rtable lives in rdomain 0.
+ */
+static u_int
+authpf_rdomain(void)
+{
+ struct rt_tableinfo info;
+ int mib[6];
+ size_t len = sizeof(info);
+ int rtable = getrtable();
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = 0;
+ mib[4] = NET_RT_TABLE;
+ mib[5] = rtable;
+
+ if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) {
+ syslog(LOG_ERR, "sysctl NET_RT_TABLE: %m");
+ exit(1);
+ }
+ return (info.rti_domainid);
+}
+
/*
* This is to kill off states that would otherwise be left behind stateful
* rules. This means we don't need to allow in more traffic than we really
@@ -905,6 +934,12 @@ authpf_kill_states(void)
memset(&psk, 0, sizeof(psk));
memset(&target, 0, sizeof(target));
+ /*
+ * DIOCKILLSTATES matches psk_rdomain exactly, so kill in the
+ * routing domain the session runs in, not just rdomain 0.
+ */
+ psk.psk_rdomain = authpf_rdomain();
+
if (inet_pton(AF_INET, ipsrc, &target.v4) == 1)
psk.psk_af = AF_INET;
else if (inet_pton(AF_INET6, ipsrc, &target.v6) == 1)
authpf: kill states in the session's routing domain