git: 54a547fcb47c - main - pf: split pf_find_or_create_ruleset() into smaller chunks
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 09 Jun 2025 21:06:55 UTC
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);
}