Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Sep 2025 12:41:44 GMT
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: ceff35a3aeef - main - pfctl: fix anchor handling for nat/rdr/binat anchors
Message-ID:  <202509251241.58PCfi6X004749@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kp:

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

commit ceff35a3aeef822976bd159c8bc403b68d5571ff
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-08-28 14:26:59 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-09-25 12:41:10 +0000

    pfctl: fix anchor handling for nat/rdr/binat anchors
    
    After the refactoring in 'pfctl: fix once rules' we broke nat/rdr/binat rules.
    These no longer exist on OpenBSD, so were not considered in that patch. Factor
    out the common code and call it from all anchor types.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sbin/pfctl/parse.y | 141 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 79 insertions(+), 62 deletions(-)

diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index babe6b99013e..0f7702fc4630 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -432,6 +432,7 @@ int	 filteropts_to_rule(struct pfctl_rule *, struct filter_opts *);
 struct node_mac* node_mac_from_string(const char *);
 struct node_mac* node_mac_from_string_masklen(const char *, int);
 struct node_mac* node_mac_from_string_mask(const char *, const char *);
+static bool pfctl_setup_anchor(struct pfctl_rule *, struct pfctl *, char *);
 
 static TAILQ_HEAD(loadanchorshead, loadanchors)
     loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead);
@@ -994,7 +995,6 @@ anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
 		{
 			struct pfctl_rule	r;
 			struct node_proto	*proto;
-			char				*p;
 
 			if (check_rulestate(PFCTL_STATE_FILTER)) {
 				if ($2)
@@ -1003,68 +1003,9 @@ anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
 			}
 
 			pfctl_init_rule(&r);
+			if (! pfctl_setup_anchor(&r, pf, $2))
+				YYERROR;
 
-			if (pf->astack[pf->asd + 1]) {
-				if ($2 && strchr($2, '/') != NULL) {
-					free($2);
-					yyerror("anchor paths containing '/' "
-					   "cannot be used for inline anchors.");
-					YYERROR;
-				}
-
-				/* Move inline rules into relative location. */
-				pfctl_anchor_setup(&r,
-				    &pf->astack[pf->asd]->ruleset,
-				    $2 ? $2 : pf->alast->name);
-
-				if (r.anchor == NULL)
-					err(1, "anchorrule: unable to "
-					    "create ruleset");
-
-				if (pf->alast != r.anchor) {
-					if (r.anchor->match) {
-						yyerror("inline anchor '%s' "
-						    "already exists",
-						    r.anchor->name);
-						YYERROR;
-					}
-					mv_rules(&pf->alast->ruleset,
-					    &r.anchor->ruleset);
-					mv_tables(pf, &pfr_ktables, r.anchor, pf->alast);
-				}
-				pf_remove_if_empty_ruleset(&pf->alast->ruleset);
-				pf->alast = r.anchor;
-			} else {
-				if (!$2) {
-					yyerror("anchors without explicit "
-					    "rules must specify a name");
-					YYERROR;
-				}
-				/*
-				 * Don't make non-brace anchors part of the main anchor pool.
-				 */
-				if ((r.anchor = calloc(1, sizeof(*r.anchor))) == NULL) {
-					err(1, "anchorrule: calloc");
-				}
-				pf_init_ruleset(&r.anchor->ruleset);
-				r.anchor->ruleset.anchor = r.anchor;
-				if (strlcpy(r.anchor->path, $2,
-				    sizeof(r.anchor->path)) >= sizeof(r.anchor->path)) {
-					errx(1, "anchorrule: strlcpy");
-				}
-				if ((p = strrchr($2, '/')) != NULL) {
-					if (strlen(p) == 1) {
-						yyerror("anchorrule: bad anchor name %s",
-						    $2);
-						YYERROR;
-					}
-				} else
-					p = $2;
-				if (strlcpy(r.anchor->name, p,
-				    sizeof(r.anchor->name)) >= sizeof(r.anchor->name)) {
-					errx(1, "anchorrule: strlcpy");
-				}
-			}
 			r.direction = $3;
 			r.quick = $4.quick;
 			r.af = $6;
@@ -1113,6 +1054,8 @@ anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
 			}
 
 			pfctl_init_rule(&r);
+			if (! pfctl_setup_anchor(&r, pf, $2))
+				YYERROR;
 
 			r.action = PF_NAT;
 			r.af = $4;
@@ -1135,6 +1078,8 @@ anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
 			}
 
 			pfctl_init_rule(&r);
+			if (! pfctl_setup_anchor(&r, pf, $2))
+				YYERROR;
 
 			r.action = PF_RDR;
 			r.af = $4;
@@ -1178,6 +1123,8 @@ anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
 			}
 
 			pfctl_init_rule(&r);
+			if (! pfctl_setup_anchor(&r, pf, $2))
+				YYERROR;
 
 			r.action = PF_BINAT;
 			r.af = $4;
@@ -7860,3 +7807,73 @@ filteropts_to_rule(struct pfctl_rule *r, struct filter_opts *opts)
 
 	return (0);
 }
+
+static bool
+pfctl_setup_anchor(struct pfctl_rule *r, struct pfctl *pf, char *anchorname)
+{
+	char	*p;
+
+	if (pf->astack[pf->asd + 1]) {
+		if (anchorname && strchr(anchorname, '/') != NULL) {
+			free(anchorname);
+			yyerror("anchor paths containing '/' "
+			   "cannot be used for inline anchors.");
+			return (false);
+		}
+
+		/* Move inline rules into relative location. */
+		pfctl_anchor_setup(r,
+		    &pf->astack[pf->asd]->ruleset,
+		    anchorname ? anchorname : pf->alast->name);
+
+		if (r->anchor == NULL)
+			err(1, "anchorrule: unable to "
+			    "create ruleset");
+
+		if (pf->alast != r->anchor) {
+			if (r->anchor->match) {
+				yyerror("inline anchor '%s' "
+				    "already exists",
+				    r->anchor->name);
+				return (false);
+			}
+			mv_rules(&pf->alast->ruleset,
+			    &r->anchor->ruleset);
+			mv_tables(pf, &pfr_ktables, r->anchor, pf->alast);
+		}
+		pf_remove_if_empty_ruleset(&pf->alast->ruleset);
+		pf->alast = r->anchor;
+	} else {
+		if (! anchorname) {
+			yyerror("anchors without explicit "
+			    "rules must specify a name");
+			return (false);
+		}
+		/*
+		 * Don't make non-brace anchors part of the main anchor pool.
+		 */
+		if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) {
+			err(1, "anchorrule: calloc");
+		}
+		pf_init_ruleset(&r->anchor->ruleset);
+		r->anchor->ruleset.anchor = r->anchor;
+		if (strlcpy(r->anchor->path, anchorname,
+		    sizeof(r->anchor->path)) >= sizeof(r->anchor->path)) {
+			errx(1, "anchorrule: strlcpy");
+		}
+		if ((p = strrchr(anchorname, '/')) != NULL) {
+			if (strlen(p) == 1) {
+				yyerror("anchorrule: bad anchor name %s",
+				    anchorname);
+				return (false);
+			}
+		} else
+			p = anchorname;
+		if (strlcpy(r->anchor->name, p,
+		    sizeof(r->anchor->name)) >= sizeof(r->anchor->name)) {
+			errx(1, "anchorrule: strlcpy");
+		}
+	}
+
+	return (true);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202509251241.58PCfi6X004749>