The branch main has been updated by kp:

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

commit 8ddd0359bca5c5fc38189000a80a3180854a8a2e
Author:     Kristof Provost <[email protected]>
AuthorDate: 2024-05-28 14:26:28 +0000
Commit:     Kristof Provost <[email protected]>
CommitDate: 2024-05-28 20:29:28 +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")
---
 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 c89981075ea6..c43d9e88dcbe 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);
@@ -1417,7 +1417,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;
@@ -1425,14 +1426,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_h(pfh, &ri, nattype[i], path);
@@ -1441,7 +1493,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_h(pfh, nr, ri.ticket, path,
@@ -1453,35 +1504,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);
                        }
                }
        }
@@ -3101,7 +3142,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,
@@ -3136,7 +3177,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);

Reply via email to