git: c71487dfba1f - stable/14 - pfctl: fix recursive printing of nat anchors
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 18 Jun 2024 14:47:22 UTC
The branch stable/14 has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=c71487dfba1f34bf06e3ae35890849bf0b454afc
commit c71487dfba1f34bf06e3ae35890849bf0b454afc
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2024-05-28 14:26:28 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2024-06-18 07:57:42 +0000
pfctl: fix recursive printing of nat anchors
Similar to the preceding fix for rules, ensure that we
recursively list wildcard anchors for nat rules.
MFC after: 3 weeks
Sponsored by: Rubicon Communications, LLC ("Netgate")
(cherry picked from commit 8ddd0359bca5c5fc38189000a80a3180854a8a2e)
---
sbin/pfctl/pfctl.c | 103 +++++++++++++++++++++++++++++++++++++----------------
1 file changed, 72 insertions(+), 31 deletions(-)
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index d5541571a135..621d97d6c555 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -98,7 +98,7 @@ void pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int);
void pfctl_print_rule_counters(struct pfctl_rule *, int);
int pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int, int);
int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int);
-int pfctl_show_nat(int, char *, int, char *, int);
+int pfctl_show_nat(int, char *, int, char *, int, int);
int pfctl_show_src_nodes(int, int);
int pfctl_show_states(int, const char *, int);
int pfctl_show_status(int, int);
@@ -1398,7 +1398,8 @@ 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)
+pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth,
+ int wildcard)
{
struct pfctl_rules_info ri;
struct pfctl_rule rule;
@@ -1406,14 +1407,65 @@ pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth)
u_int32_t nr;
static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
int i, dotitle = opts & PF_OPT_SHOWALL;
- int brace, ret;
+ int ret;
int len = strlen(path);
- char *p;
+ char *npath, *p;
- if (path[0])
- snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
- else
- snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
+ /*
+ * Truncate a trailing / and * on an anchorname before searching for
+ * the ruleset, this is syntactic sugar that doesn't actually make it
+ * to the kernel.
+ */
+ if ((p = strrchr(anchorname, '/')) != NULL &&
+ p[1] == '*' && p[2] == '\0') {
+ p[0] = '\0';
+ }
+
+ if (anchorname[0] == '/') {
+ if ((npath = calloc(1, MAXPATHLEN)) == NULL)
+ errx(1, "pfctl_rules: calloc");
+ snprintf(npath, MAXPATHLEN, "%s", anchorname);
+ } else {
+ if (path[0])
+ snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
+ else
+ snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
+ npath = path;
+ }
+
+ /*
+ * If this anchor was called with a wildcard path, go through
+ * the rulesets in the anchor rather than the rules.
+ */
+ if (wildcard && (opts & PF_OPT_RECURSE)) {
+ struct pfioc_ruleset prs;
+ u_int32_t mnr, nr;
+ memset(&prs, 0, sizeof(prs));
+ memcpy(prs.path, npath, sizeof(prs.path));
+ if (ioctl(dev, DIOCGETRULESETS, &prs)) {
+ if (errno == EINVAL)
+ fprintf(stderr, "NAT anchor '%s' "
+ "not found.\n", anchorname);
+ else
+ err(1, "DIOCGETRULESETS");
+ }
+ mnr = prs.nr;
+
+ pfctl_print_rule_counters(&rule, opts);
+ for (nr = 0; nr < mnr; ++nr) {
+ prs.nr = nr;
+ if (ioctl(dev, DIOCGETRULESET, &prs))
+ err(1, "DIOCGETRULESET");
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ printf("nat-anchor \"%s\" all {\n", prs.name);
+ pfctl_show_nat(dev, npath, opts,
+ prs.name, depth + 1, 0);
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ printf("}\n");
+ }
+ path[len] = '\0';
+ return (0);
+ }
for (i = 0; i < 3; i++) {
ret = pfctl_get_rules_info(dev, &ri, nattype[i], path);
@@ -1422,7 +1474,6 @@ pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth)
return (-1);
}
for (nr = 0; nr < ri.nr; ++nr) {
- brace = 0;
INDENT(depth, !(opts & PF_OPT_VERBOSE));
if (pfctl_get_rule(dev, nr, ri.ticket, path,
@@ -1434,35 +1485,25 @@ pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth)
ri.ticket, nattype[i], path) != 0)
return (-1);
- if (anchor_call[0] &&
- ((((p = strrchr(anchor_call, '_')) != NULL) &&
- (p == anchor_call ||
- *(--p) == '/')) || (opts & PF_OPT_RECURSE))) {
- brace++;
- if ((p = strrchr(anchor_call, '/')) !=
- NULL)
- p++;
- else
- p = &anchor_call[0];
- } else
- p = &anchor_call[0];
-
if (dotitle) {
pfctl_print_title("TRANSLATION RULES:");
dotitle = 0;
}
print_rule(&rule, anchor_call,
opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC);
- if (brace)
+ if (anchor_call[0] &&
+ (((p = strrchr(anchor_call, '/')) ?
+ p[1] == '_' : anchor_call[0] == '_') ||
+ opts & PF_OPT_RECURSE)) {
printf(" {\n");
- else
- printf("\n");
- pfctl_print_rule_counters(&rule, opts);
- pfctl_clear_pool(&rule.rpool);
- if (brace) {
- pfctl_show_nat(dev, path, opts, p, depth + 1);
+ pfctl_print_rule_counters(&rule, opts);
+ pfctl_show_nat(dev, npath, opts, anchor_call,
+ depth + 1, rule.anchor_wildcard);
INDENT(depth, !(opts & PF_OPT_VERBOSE));
printf("}\n");
+ } else {
+ printf("\n");
+ pfctl_print_rule_counters(&rule, opts);
}
}
}
@@ -3058,7 +3099,7 @@ main(int argc, char *argv[])
break;
case 'n':
pfctl_load_fingerprints(dev, opts);
- pfctl_show_nat(dev, path, opts, anchorname, 0);
+ pfctl_show_nat(dev, path, opts, anchorname, 0, 0);
break;
case 'q':
pfctl_show_altq(dev, ifaceopt, opts,
@@ -3093,7 +3134,7 @@ main(int argc, char *argv[])
pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0,
0);
- pfctl_show_nat(dev, path, opts, anchorname, 0);
+ pfctl_show_nat(dev, path, opts, anchorname, 0, 0);
pfctl_show_rules(dev, path, opts, 0, anchorname, 0, 0);
pfctl_show_altq(dev, ifaceopt, opts, 0);
pfctl_show_states(dev, ifaceopt, opts);