git: d271eca03f03 - stable/13 - libpfct: factor out pfctl_get_rules_info()

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 15 Mar 2022 15:20:13 UTC
The branch stable/13 has been updated by kp:

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

commit d271eca03f03121a4abdc171ac80ae282af66722
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2022-03-04 16:12:01 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-03-15 03:24:25 +0000

    libpfct: factor out pfctl_get_rules_info()
    
    Introduce pfctl_get_rules_info(), similar to pfctl_get_eth_rules_info()
    to retrieve rules information (ticket and total number of rules).
    
    Use the new function in pfctl.
    
    MFC after:      1 week
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D34443
    
    (cherry picked from commit 8c1400b0a1083c9e2bf8f3418eb3e3cfba1a8444)
---
 lib/libpfctl/libpfctl.c | 22 ++++++++++++
 lib/libpfctl/libpfctl.h |  7 ++++
 sbin/pfctl/pfctl.c      | 93 +++++++++++++++++++++++--------------------------
 3 files changed, 72 insertions(+), 50 deletions(-)

diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index 4c110131dcbe..3a06600f396c 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -661,6 +661,28 @@ pfctl_add_rule(int dev, const struct pfctl_rule *r, const char *anchor,
 	return (ret);
 }
 
+int
+pfctl_get_rules_info(int dev, struct pfctl_rules_info *rules, uint32_t ruleset,
+    const char *path)
+{
+	struct pfioc_rule pr;
+	int ret;
+
+	bzero(&pr, sizeof(pr));
+	if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor))
+		return (E2BIG);
+
+	pr.rule.action = ruleset;
+	ret = ioctl(dev, DIOCGETRULES, &pr);
+	if (ret != 0)
+		return (ret);
+
+	rules->nr = pr.nr;
+	rules->ticket = pr.ticket;
+
+	return (0);
+}
+
 int
 pfctl_get_rule(int dev, uint32_t nr, uint32_t ticket, const char *anchor,
     uint32_t ruleset, struct pfctl_rule *rule, char *anchor_call)
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index 3b4e61be0165..726ec89cd3d6 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -76,6 +76,11 @@ struct pfctl_pool {
 	uint8_t			 opts;
 };
 
+struct pfctl_rules_info {
+	uint32_t	nr;
+	uint32_t	ticket;
+};
+
 struct pfctl_rule {
 	struct pf_rule_addr	 src;
 	struct pf_rule_addr	 dst;
@@ -288,6 +293,8 @@ struct pfctl_syncookies {
 struct pfctl_status* pfctl_get_status(int dev);
 void	pfctl_free_status(struct pfctl_status *status);
 
+int	pfctl_get_rules_info(int dev, struct pfctl_rules_info *rules,
+	    uint32_t ruleset, const char *path);
 int	pfctl_get_rule(int dev, uint32_t nr, uint32_t ticket,
 	    const char *anchor, uint32_t ruleset, struct pfctl_rule *rule,
 	    char *anchor_call);
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 7dfcd7cc494a..676d3eb1ce8d 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1029,13 +1029,15 @@ int
 pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
     char *anchorname, int depth)
 {
-	struct pfioc_rule pr;
+	struct pfctl_rules_info ri;
 	struct pfctl_rule rule;
-	u_int32_t nr, mnr, header = 0;
+	char anchor_call[MAXPATHLEN];
+	u_int32_t nr, header = 0;
 	int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
 	int numeric = opts & PF_OPT_NUMERIC;
 	int len = strlen(path);
 	int brace;
+	int ret;
 	char *p;
 
 	if (path[0])
@@ -1043,39 +1045,35 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
 	else
 		snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
 
-	memset(&pr, 0, sizeof(pr));
-	memcpy(pr.anchor, path, sizeof(pr.anchor));
 	if (opts & PF_OPT_SHOWALL) {
-		pr.rule.action = PF_PASS;
-		if (ioctl(dev, DIOCGETRULES, &pr)) {
+		ret = pfctl_get_rules_info(dev, &ri, PF_PASS, anchorname);
+		if (ret != 0) {
 			warn("DIOCGETRULES");
 			goto error;
 		}
 		header++;
 	}
-	pr.rule.action = PF_SCRUB;
-	if (ioctl(dev, DIOCGETRULES, &pr)) {
+	ret = pfctl_get_rules_info(dev, &ri, PF_SCRUB, anchorname);
+	if (ret != 0) {
 		warn("DIOCGETRULES");
 		goto error;
 	}
 	if (opts & PF_OPT_SHOWALL) {
-		if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header))
+		if (format == PFCTL_SHOW_RULES && (ri.nr > 0 || header))
 			pfctl_print_title("FILTER RULES:");
 		else if (format == PFCTL_SHOW_LABELS && labels)
 			pfctl_print_title("LABEL COUNTERS:");
 	}
-	mnr = pr.nr;
 
-	for (nr = 0; nr < mnr; ++nr) {
-		pr.nr = nr;
-		if (pfctl_get_clear_rule(dev, nr, pr.ticket, path, PF_SCRUB,
-		    &rule, pr.anchor_call, opts & PF_OPT_CLRRULECTRS)) {
+	for (nr = 0; nr < ri.nr; ++nr) {
+		if (pfctl_get_clear_rule(dev, nr, ri.ticket, path, PF_SCRUB,
+		    &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) {
 			warn("DIOCGETRULENV");
 			goto error;
 		}
 
 		if (pfctl_get_pool(dev, &rule.rpool,
-		    nr, pr.ticket, PF_SCRUB, path) != 0)
+		    nr, ri.ticket, PF_SCRUB, path) != 0)
 			goto error;
 
 		switch (format) {
@@ -1084,7 +1082,7 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
 		case PFCTL_SHOW_RULES:
 			if (rule.label[0] && (opts & PF_OPT_SHOWALL))
 				labels = 1;
-			print_rule(&rule, pr.anchor_call, rule_numbers, numeric);
+			print_rule(&rule, anchor_call, rule_numbers, numeric);
 			printf("\n");
 			pfctl_print_rule_counters(&rule, opts);
 			break;
@@ -1093,22 +1091,20 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
 		}
 		pfctl_clear_pool(&rule.rpool);
 	}
-	pr.rule.action = PF_PASS;
-	if (ioctl(dev, DIOCGETRULES, &pr)) {
+	ret = pfctl_get_rules_info(dev, &ri, PF_PASS, anchorname);
+	if (ret != 0) {
 		warn("DIOCGETRULES");
 		goto error;
 	}
-	mnr = pr.nr;
-	for (nr = 0; nr < mnr; ++nr) {
-		pr.nr = nr;
-		if (pfctl_get_clear_rule(dev, nr, pr.ticket, path, PF_PASS,
-		    &rule, pr.anchor_call, opts & PF_OPT_CLRRULECTRS)) {
+	for (nr = 0; nr < ri.nr; ++nr) {
+		if (pfctl_get_clear_rule(dev, nr, ri.ticket, path, PF_PASS,
+		    &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) {
 			warn("DIOCGETRULE");
 			goto error;
 		}
 
 		if (pfctl_get_pool(dev, &rule.rpool,
-		    nr, pr.ticket, PF_PASS, path) != 0)
+		    nr, ri.ticket, PF_PASS, path) != 0)
 			goto error;
 
 		switch (format) {
@@ -1142,18 +1138,18 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
 			if (rule.label[0] && (opts & PF_OPT_SHOWALL))
 				labels = 1;
 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
-			if (pr.anchor_call[0] &&
-			   ((((p = strrchr(pr.anchor_call, '_')) != NULL) &&
-			   ((void *)p == (void *)pr.anchor_call ||
+			if (anchor_call[0] &&
+			   ((((p = strrchr(anchor_call, '_')) != NULL) &&
+			   ((void *)p == (void *)anchor_call ||
 			   *(--p) == '/')) || (opts & PF_OPT_RECURSE))) {
 				brace++;
-				if ((p = strrchr(pr.anchor_call, '/')) !=
+				if ((p = strrchr(anchor_call, '/')) !=
 				    NULL)
 					p++;
 				else
-					p = &pr.anchor_call[0];
+					p = &anchor_call[0];
 			} else
-				p = &pr.anchor_call[0];
+				p = &anchor_call[0];
 		
 			print_rule(&rule, p, rule_numbers, numeric);
 			if (brace)
@@ -1184,55 +1180,52 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
 int
 pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth)
 {
-	struct pfioc_rule pr;
+	struct pfctl_rules_info ri;
 	struct pfctl_rule rule;
-	u_int32_t mnr, nr;
+	char anchor_call[MAXPATHLEN];
+	u_int32_t nr;
 	static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
 	int i, dotitle = opts & PF_OPT_SHOWALL;
-	int brace;
+	int brace, ret;
 	char *p;
 
 	for (i = 0; i < 3; i++) {
-		memset(&pr, 0, sizeof(pr));
-		memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
-		pr.rule.action = nattype[i];
-		if (ioctl(dev, DIOCGETRULES, &pr)) {
+		ret = pfctl_get_rules_info(dev, &ri, nattype[i], anchorname);
+		if (ret != 0) {
 			warn("DIOCGETRULES");
 			return (-1);
 		}
-		mnr = pr.nr;
-		for (nr = 0; nr < mnr; ++nr) {
+		for (nr = 0; nr < ri.nr; ++nr) {
 			brace = 0;
 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
 
-			pr.nr = nr;
-			if (pfctl_get_rule(dev, nr, pr.ticket, anchorname,
-			    nattype[i], &rule, pr.anchor_call)) {
+			if (pfctl_get_rule(dev, nr, ri.ticket, anchorname,
+			    nattype[i], &rule, anchor_call)) {
 				warn("DIOCGETRULE");
 				return (-1);
 			}
 			if (pfctl_get_pool(dev, &rule.rpool, nr,
-			    pr.ticket, nattype[i], anchorname) != 0)
+			    ri.ticket, nattype[i], anchorname) != 0)
 				return (-1);
 
-			if (pr.anchor_call[0] &&
-			   ((((p = strrchr(pr.anchor_call, '_')) != NULL) &&
-			   (p == pr.anchor_call ||
+			if (anchor_call[0] &&
+			   ((((p = strrchr(anchor_call, '_')) != NULL) &&
+			   (p == anchor_call ||
 			   *(--p) == '/')) || (opts & PF_OPT_RECURSE))) {
 				brace++;
-				if ((p = strrchr(pr.anchor_call, '/')) !=
+				if ((p = strrchr(anchor_call, '/')) !=
 				    NULL)
 					p++;
 				else
-					p = &pr.anchor_call[0];
+					p = &anchor_call[0];
 			} else
-				p = &pr.anchor_call[0];
+				p = &anchor_call[0];
 
 			if (dotitle) {
 				pfctl_print_title("TRANSLATION RULES:");
 				dotitle = 0;
 			}
-			print_rule(&rule, pr.anchor_call,
+			print_rule(&rule, anchor_call,
 			    opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC);
 			if (brace)
 				printf(" {\n");