git: f3ab00c2b607 - main - pf: add a new log opt PF_LOG_MATCHES

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Thu, 19 Sep 2024 20:21:19 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=f3ab00c2b607f80f69963f8a38a8d1910ed4e593

commit f3ab00c2b607f80f69963f8a38a8d1910ed4e593
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2024-09-03 13:32:57 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2024-09-19 20:20:13 +0000

    pf: add a new log opt PF_LOG_MATCHES
    
    forces logging on all subsequent matching rules
    new log opt "matches"
    awesome for debugging, a rule like
    match log(matches) from $testbox
    will show you exactly which subsequent rules match on that packet
    real ok theo assumed oks ryan & dlg bikeshedding many
    
    Obtained from:  OpenBSD, henning <henning@openbsd.org>, 1603e01ae4
    Obtained from:  OpenBSD, henning <henning@openbsd.org>, f496e91672
    Obtained from:  OpenBSD, henning <henning@openbsd.org>, 07481a9fee
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D46588
---
 sbin/pfctl/parse.y        | 4 +++-
 sbin/pfctl/pfctl_parser.c | 2 ++
 share/man/man5/pf.conf.5  | 4 +++-
 sys/netpfil/pf/pf.c       | 8 ++++++--
 sys/netpfil/pf/pf.h       | 1 +
 5 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index cfa6c85b5c0a..9d95122f9826 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -507,7 +507,7 @@ int	parseport(char *, struct range *r, int);
 %token	REASSEMBLE ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
 %token	SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY
 %token	RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
-%token	ANTISPOOF FOR INCLUDE KEEPCOUNTERS SYNCOOKIES L3
+%token	ANTISPOOF FOR INCLUDE KEEPCOUNTERS SYNCOOKIES L3 MATCHES
 %token	ETHER
 %token	BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY MAPEPORTSET
 %token	ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
@@ -3222,6 +3222,7 @@ logopts		: logopt			{ $$ = $1; }
 		;
 
 logopt		: ALL		{ $$.log = PF_LOG_ALL; $$.logif = 0; }
+		| MATCHES		{ $$.log = PF_LOG_MATCHES; $$.logif = 0; }
 		| USER		{ $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
 		| GROUP		{ $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
 		| TO string	{
@@ -6365,6 +6366,7 @@ lookup(char *s)
 		{ "loginterface",	LOGINTERFACE},
 		{ "map-e-portset",	MAPEPORTSET},
 		{ "match",		MATCH},
+		{ "matches",	MATCHES},
 		{ "max",		MAXIMUM},
 		{ "max-mss",		MAXMSS},
 		{ "max-src-conn",	MAXSRCCONN},
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 2e6a1d1cb1c5..70c2ad42ca55 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -918,6 +918,8 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
 			printf(" (");
 			if (r->log & PF_LOG_ALL)
 				printf("%sall", count++ ? ", " : "");
+			if (r->log & PF_LOG_MATCHES)
+				printf("%smatches", count++ ? ", " : "");
 			if (r->log & PF_LOG_SOCKET_LOOKUP)
 				printf("%suser", count++ ? ", " : "");
 			if (r->logif)
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
index bfa79b928b69..28cd2407b41a 100644
--- a/share/man/man5/pf.conf.5
+++ b/share/man/man5/pf.conf.5
@@ -1684,6 +1684,8 @@ As with
 .Ar log ,
 packets are logged to
 .Xr pflog 4 .
+.It Ar log (matches)
+Used to force logging of this packet on all subsequent matching rules.
 .It Ar log (user)
 Logs the
 .Ux
@@ -3217,7 +3219,7 @@ pf-rule        = action [ ( "in" | "out" ) ]
                  hosts [ filteropt-list ]
 
 logopts        = logopt [ "," logopts ]
-logopt         = "all" | "user" | "to" interface-name
+logopt         = "all" | "matches" | "user" | "to" interface-name
 
 etherfilteropt-list = etherfilteropt-list etherfilteropt | etherfilteropt
 etherfilteropt = "tag" string | "tagged" string | "queue" ( string ) |
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index f340c76da40e..4d0cee4d0c4a 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -5198,7 +5198,7 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, struct pfi_kkif *kif,
 					pf_counter_u64_add_protected(&r->bytes[pd->dir == PF_OUT], pd->tot_len);
 					pf_counter_u64_critical_exit();
 					pf_rule_to_actions(r, &pd->act);
-					if (r->log)
+					if (r->log || pd->act.log & PF_LOG_MATCHES)
 						PFLOG_PACKET(kif, m, af,
 						    r->action, PFRES_MATCH, r,
 						    a, ruleset, pd, 1);
@@ -5207,6 +5207,10 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, struct pfi_kkif *kif,
 					*rm = r;
 					*am = a;
 					*rsm = ruleset;
+					if (pd->act.log & PF_LOG_MATCHES)
+						PFLOG_PACKET(kif, m, af,
+						    r->action, PFRES_MATCH, r,
+						    a, ruleset, pd, 1);
 				}
 				if ((*rm)->quick)
 					break;
@@ -5229,7 +5233,7 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, struct pfi_kkif *kif,
 	/* apply actions for last matching pass/block rule */
 	pf_rule_to_actions(r, &pd->act);
 
-	if (r->log) {
+	if (r->log || pd->act.log & PF_LOG_MATCHES) {
 		if (rewrite)
 			m_copyback(m, off, hdrlen, pd->hdr.any);
 		PFLOG_PACKET(kif, m, af, r->action, reason, r, a, ruleset, pd, 1);
diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h
index 6370164cb291..063abe83274b 100644
--- a/sys/netpfil/pf/pf.h
+++ b/sys/netpfil/pf/pf.h
@@ -137,6 +137,7 @@ enum	{ PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
 #define	PF_LOG_ALL		0x02
 #define	PF_LOG_SOCKET_LOOKUP	0x04
 #define	PF_LOG_FORCE		0x08
+#define	PF_LOG_MATCHES		0x10
 
 /* Reasons code for passing/dropping a packet */
 #define PFRES_MATCH	0		/* Explicit match of a rule */