The branch main has been updated by kp:

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

commit 54a547fcb47c9fce54789a8b091e900b291fd1ba
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2025-05-30 13:02:50 +0000
Commit:     Kristof Provost <k...@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 <sas...@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);
 }

Reply via email to