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>