Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Jun 2025 21:06:55 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: 54a547fcb47c - main - pf: split pf_find_or_create_ruleset() into smaller chunks
Message-ID:  <202506092106.559L6tKd089800@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=54a547fcb47c9fce54789a8b091e900b291fd1ba

commit 54a547fcb47c9fce54789a8b091e900b291fd1ba
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-05-30 13:02:50 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-06-09 19:38:47 +0000

    pf: split pf_find_or_create_ruleset() into smaller chunks
    
    tested by Hrvoje
    OK mpi@, OK bluhm@
    
    Obtained from:  OpenBSD, sashan <sashan@openbsd.org>, 0d5abfc5ba
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D50725
---
 sys/net/pfvar.h             |   2 +
 sys/netpfil/pf/pf.h         |   1 +
 sys/netpfil/pf/pf_ruleset.c | 178 ++++++++++++++++++++++++++++----------------
 3 files changed, 117 insertions(+), 64 deletions(-)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 6209a93dd995..65debf53e5ff 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -2664,6 +2664,8 @@ int			 pf_kanchor_nvcopyout(const struct pf_kruleset *,
 void			 pf_kanchor_remove(struct pf_krule *);
 void			 pf_remove_if_empty_kruleset(struct pf_kruleset *);
 struct pf_kruleset	*pf_find_kruleset(const char *);
+struct pf_kruleset	*pf_get_leaf_kruleset(char *, char **);
+struct pf_kanchor	*pf_create_kanchor(struct pf_kanchor *, const char *);
 struct pf_kruleset	*pf_find_or_create_kruleset(const char *);
 void			 pf_rs_initialize(void);
 
diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h
index b5c0eeaa8f01..2009d2907985 100644
--- a/sys/netpfil/pf/pf.h
+++ b/sys/netpfil/pf/pf.h
@@ -489,6 +489,7 @@ struct pf_osfp_ioctl {
 };
 
 #define	PF_ANCHOR_NAME_SIZE	 64
+#define	PF_ANCHOR_MAXPATH	(MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)
 
 struct pf_rule {
 	struct pf_rule_addr	 src;
diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c
index 6fd92201439d..865c5ecd72d9 100644
--- a/sys/netpfil/pf/pf_ruleset.c
+++ b/sys/netpfil/pf/pf_ruleset.c
@@ -189,13 +189,108 @@ pf_find_kruleset(const char *path)
 	else
 		return (&anchor->ruleset);
 }
+struct pf_kruleset *
+pf_get_leaf_kruleset(char *path, char **path_remainder)
+{
+	struct pf_kruleset	*ruleset;
+	char			*leaf, *p;
+	int			 i = 0;
+
+	p = path;
+	while (*p == '/')
+		p++;
+
+	ruleset = pf_find_kruleset(p);
+	leaf = p;
+	while (ruleset == NULL) {
+		leaf = strrchr(p, '/');
+		if (leaf != NULL) {
+			*leaf = '\0';
+			i++;
+			ruleset = pf_find_kruleset(p);
+		} else {
+			leaf = path;
+			/*
+			 * if no path component exists, then main ruleset is
+			 * our parent.
+			 */
+			ruleset = &pf_main_ruleset;
+		}
+	}
+
+	if (path_remainder != NULL)
+		*path_remainder = leaf;
+
+	/* restore slashes in path.  */
+	while (i != 0) {
+		while (*leaf != '\0')
+			leaf++;
+		*leaf = '/';
+		i--;
+	}
+
+	return (ruleset);
+}
+
+struct pf_kanchor *
+pf_create_kanchor(struct pf_kanchor *parent, const char *aname)
+{
+	struct pf_kanchor	*anchor, *dup;
+
+	if (!*aname || (strlen(aname) >= PF_ANCHOR_NAME_SIZE) ||
+	   ((parent != NULL) && (strlen(parent->path) >= PF_ANCHOR_MAXPATH)))
+		return (NULL);
+
+	anchor = rs_malloc(sizeof(*anchor));
+	if (anchor == NULL)
+		return (NULL);
+
+	RB_INIT(&anchor->children);
+	strlcpy(anchor->name, aname, sizeof(anchor->name));
+	if (parent != NULL) {
+		/*
+		 * Make sure path for levels 2, 3, ... is terminated by '/':
+		 *      1/2/3/...
+		 */
+		strlcpy(anchor->path, parent->path, sizeof(anchor->path));
+		strlcat(anchor->path, "/", sizeof(anchor->path));
+	}
+	strlcat(anchor->path, anchor->name, sizeof(anchor->path));
+
+	if ((dup = RB_INSERT(pf_kanchor_global, &V_pf_anchors, anchor)) !=
+	    NULL) {
+		printf("pf_find_or_create_ruleset: RB_INSERT1 "
+		    "'%s' '%s' collides with '%s' '%s'\n",
+		    anchor->path, anchor->name, dup->path, dup->name);
+		rs_free(anchor);
+		return (NULL);
+	}
+
+	if (parent != NULL) {
+		anchor->parent = parent;
+		if ((dup = RB_INSERT(pf_kanchor_node, &parent->children,
+		    anchor)) != NULL) {
+			printf("pf_find_or_create_ruleset: "
+			    "RB_INSERT2 '%s' '%s' collides with "
+			    "'%s' '%s'\n", anchor->path, anchor->name,
+			    dup->path, dup->name);
+			RB_REMOVE(pf_kanchor_global, &V_pf_anchors,
+			    anchor);
+			rs_free(anchor);
+			return (NULL);
+		}
+	}
+	pf_init_kruleset(&anchor->ruleset);
+	anchor->ruleset.anchor = anchor;
+	return (anchor);
+}
 
 struct pf_kruleset *
 pf_find_or_create_kruleset(const char *path)
 {
-	char			*p, *q, *r;
+	char			*p, *aname, *r;
 	struct pf_kruleset	*ruleset;
-	struct pf_kanchor	*anchor = NULL, *dup, *parent = NULL;
+	struct pf_kanchor	*anchor = NULL;
 
 	if (path[0] == 0)
 		return (&pf_main_ruleset);
@@ -208,76 +303,31 @@ pf_find_or_create_kruleset(const char *path)
 	if (p == NULL)
 		return (NULL);
 	strlcpy(p, path, MAXPATHLEN);
-	while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
-		*q = 0;
-		if ((ruleset = pf_find_kruleset(p)) != NULL) {
-			parent = ruleset->anchor;
-			break;
-		}
-	}
-	if (q == NULL)
-		q = p;
-	else
-		q++;
-	strlcpy(p, path, MAXPATHLEN);
-	if (!*q) {
-		rs_free(p);
-		return (NULL);
-	}
-	while ((r = strchr(q, '/')) != NULL || *q) {
+
+	ruleset = pf_get_leaf_kruleset(p, &aname);
+	anchor = ruleset->anchor;
+
+	while (*aname == '/')
+		aname++;
+	/*
+	 * aname is a path remainder, which contains nodes we must create.  We
+	 * process the aname path from left to right, effectively descending
+	 * from parents to children.
+	 */
+	while ((r = strchr(aname, '/')) != NULL || *aname) {
 		if (r != NULL)
 			*r = 0;
-		if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE ||
-		    (parent != NULL && strlen(parent->path) >=
-		    MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) {
-			rs_free(p);
-			return (NULL);
-		}
-		anchor = (struct pf_kanchor *)rs_malloc(sizeof(*anchor));
+		anchor = pf_create_kanchor(anchor, aname);
 		if (anchor == NULL) {
 			rs_free(p);
 			return (NULL);
 		}
-		RB_INIT(&anchor->children);
-		strlcpy(anchor->name, q, sizeof(anchor->name));
-		if (parent != NULL) {
-			strlcpy(anchor->path, parent->path,
-			    sizeof(anchor->path));
-			strlcat(anchor->path, "/", sizeof(anchor->path));
-		}
-		strlcat(anchor->path, anchor->name, sizeof(anchor->path));
-		if ((dup = RB_INSERT(pf_kanchor_global, &V_pf_anchors, anchor)) !=
-		    NULL) {
-			printf("pf_find_or_create_ruleset: RB_INSERT1 "
-			    "'%s' '%s' collides with '%s' '%s'\n",
-			    anchor->path, anchor->name, dup->path, dup->name);
-			rs_free(anchor);
-			rs_free(p);
-			return (NULL);
-		}
-		if (parent != NULL) {
-			anchor->parent = parent;
-			if ((dup = RB_INSERT(pf_kanchor_node, &parent->children,
-			    anchor)) != NULL) {
-				printf("pf_find_or_create_ruleset: "
-				    "RB_INSERT2 '%s' '%s' collides with "
-				    "'%s' '%s'\n", anchor->path, anchor->name,
-				    dup->path, dup->name);
-				RB_REMOVE(pf_kanchor_global, &V_pf_anchors,
-				    anchor);
-				rs_free(anchor);
-				rs_free(p);
-				return (NULL);
-			}
-		}
-		pf_init_kruleset(&anchor->ruleset);
-		anchor->ruleset.anchor = anchor;
-		parent = anchor;
-		if (r != NULL)
-			q = r + 1;
+		if (r == NULL)
+			break;
 		else
-			*q = 0;
+			aname = r + 1;
 	}
+
 	rs_free(p);
 	return (&anchor->ruleset);
 }



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