Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf_ruleset.c
| Show First 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | |||||
| #include <sys/stdarg.h> | #include <sys/stdarg.h> | ||||
| #define DPFPRINTF(format, x...) fprintf(stderr, format , ##x) | #define DPFPRINTF(format, x...) fprintf(stderr, format , ##x) | ||||
| #else | #else | ||||
| #define DPFPRINTF(format, x...) ((void)0) | #define DPFPRINTF(format, x...) ((void)0) | ||||
| #endif /* PFDEBUG */ | #endif /* PFDEBUG */ | ||||
| #endif /* _KERNEL */ | #endif /* _KERNEL */ | ||||
| #ifdef _KERNEL | #ifdef _KERNEL | ||||
| VNET_DEFINE(struct pf_anchor_global, pf_anchors); | VNET_DEFINE(struct pf_kanchor_global, pf_anchors); | ||||
| VNET_DEFINE(struct pf_anchor, pf_main_anchor); | VNET_DEFINE(struct pf_kanchor, pf_main_anchor); | ||||
| #else /* ! _KERNEL */ | #else /* ! _KERNEL */ | ||||
| struct pf_anchor_global pf_anchors; | struct pf_anchor_global pf_anchors; | ||||
| struct pf_anchor pf_main_anchor; | struct pf_anchor pf_main_anchor; | ||||
| #undef V_pf_anchors | #undef V_pf_anchors | ||||
| #define V_pf_anchors pf_anchors | #define V_pf_anchors pf_anchors | ||||
| #undef pf_main_ruleset | #undef pf_main_ruleset | ||||
| #define pf_main_ruleset pf_main_anchor.ruleset | #define pf_main_ruleset pf_main_anchor.ruleset | ||||
| #endif /* _KERNEL */ | #endif /* _KERNEL */ | ||||
| static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *); | |||||
| #ifdef _KERNEL | |||||
| static __inline int pf_kanchor_compare(struct pf_kanchor *, | |||||
| struct pf_kanchor *); | |||||
| static struct pf_kanchor *pf_find_kanchor(const char *); | |||||
| RB_GENERATE(pf_kanchor_global, pf_kanchor, entry_global, pf_kanchor_compare); | |||||
| RB_GENERATE(pf_kanchor_node, pf_kanchor, entry_node, pf_kanchor_compare); | |||||
| #else | |||||
| static __inline int pf_anchor_compare(struct pf_anchor *, | |||||
| struct pf_anchor *); | |||||
| static struct pf_anchor *pf_find_anchor(const char *); | static struct pf_anchor *pf_find_anchor(const char *); | ||||
| RB_GENERATE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare); | RB_GENERATE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare); | ||||
| RB_GENERATE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare); | RB_GENERATE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare); | ||||
| #endif | |||||
| #ifndef _KERNEL | |||||
| static __inline int | static __inline int | ||||
| pf_anchor_compare(struct pf_anchor *a, struct pf_anchor *b) | pf_anchor_compare(struct pf_anchor *a, struct pf_anchor *b) | ||||
| { | { | ||||
| int c = strcmp(a->path, b->path); | int c = strcmp(a->path, b->path); | ||||
| return (c ? (c < 0 ? -1 : 1) : 0); | return (c ? (c < 0 ? -1 : 1) : 0); | ||||
| } | } | ||||
| #else | |||||
| static __inline int | |||||
| pf_kanchor_compare(struct pf_kanchor *a, struct pf_kanchor *b) | |||||
| { | |||||
| int c = strcmp(a->path, b->path); | |||||
| return (c ? (c < 0 ? -1 : 1) : 0); | |||||
| } | |||||
| #endif | |||||
| int | int | ||||
| pf_get_ruleset_number(u_int8_t action) | pf_get_ruleset_number(u_int8_t action) | ||||
| { | { | ||||
| switch (action) { | switch (action) { | ||||
| case PF_SCRUB: | case PF_SCRUB: | ||||
| case PF_NOSCRUB: | case PF_NOSCRUB: | ||||
| return (PF_RULESET_SCRUB); | return (PF_RULESET_SCRUB); | ||||
| break; | break; | ||||
| Show All 14 Lines | case PF_NORDR: | ||||
| return (PF_RULESET_RDR); | return (PF_RULESET_RDR); | ||||
| break; | break; | ||||
| default: | default: | ||||
| return (PF_RULESET_MAX); | return (PF_RULESET_MAX); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| #ifndef _KERNEL | |||||
| void | void | ||||
| pf_init_ruleset(struct pf_ruleset *ruleset) | pf_init_ruleset(struct pf_ruleset *ruleset) | ||||
| { | { | ||||
| int i; | int i; | ||||
| memset(ruleset, 0, sizeof(struct pf_ruleset)); | memset(ruleset, 0, sizeof(struct pf_ruleset)); | ||||
| for (i = 0; i < PF_RULESET_MAX; i++) { | for (i = 0; i < PF_RULESET_MAX; i++) { | ||||
| TAILQ_INIT(&ruleset->rules[i].queues[0]); | TAILQ_INIT(&ruleset->rules[i].queues[0]); | ||||
| Show All 11 Lines | pf_find_anchor(const char *path) | ||||
| key = (struct pf_anchor *)rs_malloc(sizeof(*key)); | key = (struct pf_anchor *)rs_malloc(sizeof(*key)); | ||||
| if (key == NULL) | if (key == NULL) | ||||
| return (NULL); | return (NULL); | ||||
| strlcpy(key->path, path, sizeof(key->path)); | strlcpy(key->path, path, sizeof(key->path)); | ||||
| found = RB_FIND(pf_anchor_global, &V_pf_anchors, key); | found = RB_FIND(pf_anchor_global, &V_pf_anchors, key); | ||||
| rs_free(key); | rs_free(key); | ||||
| return (found); | return (found); | ||||
| } | } | ||||
| #else | |||||
| static struct pf_kanchor * | |||||
| pf_find_kanchor(const char *path) | |||||
| { | |||||
| struct pf_kanchor *key, *found; | |||||
| struct pf_ruleset * | key = (struct pf_kanchor *)rs_malloc(sizeof(*key)); | ||||
| pf_find_ruleset(const char *path) | if (key == NULL) | ||||
| return (NULL); | |||||
| strlcpy(key->path, path, sizeof(key->path)); | |||||
| found = RB_FIND(pf_kanchor_global, &V_pf_anchors, key); | |||||
| rs_free(key); | |||||
| return (found); | |||||
| } | |||||
| void | |||||
| pf_init_kruleset(struct pf_kruleset *ruleset) | |||||
| { | { | ||||
| struct pf_anchor *anchor; | int i; | ||||
| memset(ruleset, 0, sizeof(struct pf_kruleset)); | |||||
| for (i = 0; i < PF_RULESET_MAX; i++) { | |||||
| TAILQ_INIT(&ruleset->rules[i].queues[0]); | |||||
| TAILQ_INIT(&ruleset->rules[i].queues[1]); | |||||
| ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0]; | |||||
| ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1]; | |||||
| } | |||||
| } | |||||
| #endif | |||||
| #ifdef _KERNEL | |||||
| struct pf_kruleset * | |||||
| pf_find_kruleset(const char *path) | |||||
| { | |||||
| struct pf_kanchor *anchor; | |||||
| while (*path == '/') | while (*path == '/') | ||||
| path++; | path++; | ||||
| if (!*path) | if (!*path) | ||||
| return (&pf_main_ruleset); | return (&pf_main_ruleset); | ||||
| anchor = pf_find_anchor(path); | anchor = pf_find_kanchor(path); | ||||
| if (anchor == NULL) | if (anchor == NULL) | ||||
| return (NULL); | return (NULL); | ||||
| else | else | ||||
| return (&anchor->ruleset); | return (&anchor->ruleset); | ||||
| } | } | ||||
| struct pf_ruleset * | struct pf_kruleset * | ||||
| pf_find_or_create_ruleset(const char *path) | pf_find_or_create_kruleset(const char *path) | ||||
| { | { | ||||
| char *p, *q, *r; | char *p, *q, *r; | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pf_anchor *anchor = NULL, *dup, *parent = NULL; | struct pf_kanchor *anchor = NULL, *dup, *parent = NULL; | ||||
| if (path[0] == 0) | if (path[0] == 0) | ||||
| return (&pf_main_ruleset); | return (&pf_main_ruleset); | ||||
| while (*path == '/') | while (*path == '/') | ||||
| path++; | path++; | ||||
| ruleset = pf_find_ruleset(path); | ruleset = pf_find_kruleset(path); | ||||
| if (ruleset != NULL) | if (ruleset != NULL) | ||||
| return (ruleset); | return (ruleset); | ||||
| p = (char *)rs_malloc(MAXPATHLEN); | p = (char *)rs_malloc(MAXPATHLEN); | ||||
| if (p == NULL) | if (p == NULL) | ||||
| return (NULL); | return (NULL); | ||||
| strlcpy(p, path, MAXPATHLEN); | strlcpy(p, path, MAXPATHLEN); | ||||
| while (parent == NULL && (q = strrchr(p, '/')) != NULL) { | while (parent == NULL && (q = strrchr(p, '/')) != NULL) { | ||||
| *q = 0; | *q = 0; | ||||
| if ((ruleset = pf_find_ruleset(p)) != NULL) { | if ((ruleset = pf_find_kruleset(p)) != NULL) { | ||||
| parent = ruleset->anchor; | parent = ruleset->anchor; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (q == NULL) | if (q == NULL) | ||||
| q = p; | q = p; | ||||
| else | else | ||||
| q++; | q++; | ||||
| strlcpy(p, path, MAXPATHLEN); | strlcpy(p, path, MAXPATHLEN); | ||||
| if (!*q) { | if (!*q) { | ||||
| rs_free(p); | rs_free(p); | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| while ((r = strchr(q, '/')) != NULL || *q) { | while ((r = strchr(q, '/')) != NULL || *q) { | ||||
| if (r != NULL) | if (r != NULL) | ||||
| *r = 0; | *r = 0; | ||||
| if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE || | if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE || | ||||
| (parent != NULL && strlen(parent->path) >= | (parent != NULL && strlen(parent->path) >= | ||||
| MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) { | MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) { | ||||
| rs_free(p); | rs_free(p); | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| anchor = (struct pf_anchor *)rs_malloc(sizeof(*anchor)); | anchor = (struct pf_kanchor *)rs_malloc(sizeof(*anchor)); | ||||
| if (anchor == NULL) { | if (anchor == NULL) { | ||||
| rs_free(p); | rs_free(p); | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| RB_INIT(&anchor->children); | RB_INIT(&anchor->children); | ||||
| strlcpy(anchor->name, q, sizeof(anchor->name)); | strlcpy(anchor->name, q, sizeof(anchor->name)); | ||||
| if (parent != NULL) { | if (parent != NULL) { | ||||
| strlcpy(anchor->path, parent->path, | strlcpy(anchor->path, parent->path, | ||||
| sizeof(anchor->path)); | sizeof(anchor->path)); | ||||
| strlcat(anchor->path, "/", sizeof(anchor->path)); | strlcat(anchor->path, "/", sizeof(anchor->path)); | ||||
| } | } | ||||
| strlcat(anchor->path, anchor->name, sizeof(anchor->path)); | strlcat(anchor->path, anchor->name, sizeof(anchor->path)); | ||||
| if ((dup = RB_INSERT(pf_anchor_global, &V_pf_anchors, anchor)) != | if ((dup = RB_INSERT(pf_kanchor_global, &V_pf_anchors, anchor)) != | ||||
| NULL) { | NULL) { | ||||
| printf("pf_find_or_create_ruleset: RB_INSERT1 " | printf("pf_find_or_create_ruleset: RB_INSERT1 " | ||||
| "'%s' '%s' collides with '%s' '%s'\n", | "'%s' '%s' collides with '%s' '%s'\n", | ||||
| anchor->path, anchor->name, dup->path, dup->name); | anchor->path, anchor->name, dup->path, dup->name); | ||||
| rs_free(anchor); | rs_free(anchor); | ||||
| rs_free(p); | rs_free(p); | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| if (parent != NULL) { | if (parent != NULL) { | ||||
| anchor->parent = parent; | anchor->parent = parent; | ||||
| if ((dup = RB_INSERT(pf_anchor_node, &parent->children, | if ((dup = RB_INSERT(pf_kanchor_node, &parent->children, | ||||
| anchor)) != NULL) { | anchor)) != NULL) { | ||||
| printf("pf_find_or_create_ruleset: " | printf("pf_find_or_create_ruleset: " | ||||
| "RB_INSERT2 '%s' '%s' collides with " | "RB_INSERT2 '%s' '%s' collides with " | ||||
| "'%s' '%s'\n", anchor->path, anchor->name, | "'%s' '%s'\n", anchor->path, anchor->name, | ||||
| dup->path, dup->name); | dup->path, dup->name); | ||||
| RB_REMOVE(pf_anchor_global, &V_pf_anchors, | RB_REMOVE(pf_kanchor_global, &V_pf_anchors, | ||||
| anchor); | anchor); | ||||
| rs_free(anchor); | rs_free(anchor); | ||||
| rs_free(p); | rs_free(p); | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| } | } | ||||
| pf_init_ruleset(&anchor->ruleset); | pf_init_kruleset(&anchor->ruleset); | ||||
| anchor->ruleset.anchor = anchor; | anchor->ruleset.anchor = anchor; | ||||
| parent = anchor; | parent = anchor; | ||||
| if (r != NULL) | if (r != NULL) | ||||
| q = r + 1; | q = r + 1; | ||||
| else | else | ||||
| *q = 0; | *q = 0; | ||||
| } | } | ||||
| rs_free(p); | rs_free(p); | ||||
| return (&anchor->ruleset); | return (&anchor->ruleset); | ||||
| } | } | ||||
| void | void | ||||
| pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset) | pf_remove_if_empty_kruleset(struct pf_kruleset *ruleset) | ||||
| { | { | ||||
| struct pf_anchor *parent; | struct pf_kanchor *parent; | ||||
| int i; | int i; | ||||
| while (ruleset != NULL) { | while (ruleset != NULL) { | ||||
| if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL || | if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL || | ||||
| !RB_EMPTY(&ruleset->anchor->children) || | !RB_EMPTY(&ruleset->anchor->children) || | ||||
| ruleset->anchor->refcnt > 0 || ruleset->tables > 0 || | ruleset->anchor->refcnt > 0 || ruleset->tables > 0 || | ||||
| ruleset->topen) | ruleset->topen) | ||||
| return; | return; | ||||
| for (i = 0; i < PF_RULESET_MAX; ++i) | for (i = 0; i < PF_RULESET_MAX; ++i) | ||||
| if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) || | if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) || | ||||
| !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) || | !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) || | ||||
| ruleset->rules[i].inactive.open) | ruleset->rules[i].inactive.open) | ||||
| return; | return; | ||||
| RB_REMOVE(pf_anchor_global, &V_pf_anchors, ruleset->anchor); | RB_REMOVE(pf_kanchor_global, &V_pf_anchors, ruleset->anchor); | ||||
| if ((parent = ruleset->anchor->parent) != NULL) | if ((parent = ruleset->anchor->parent) != NULL) | ||||
| RB_REMOVE(pf_anchor_node, &parent->children, | RB_REMOVE(pf_kanchor_node, &parent->children, | ||||
| ruleset->anchor); | ruleset->anchor); | ||||
| rs_free(ruleset->anchor); | rs_free(ruleset->anchor); | ||||
| if (parent == NULL) | if (parent == NULL) | ||||
| return; | return; | ||||
| ruleset = &parent->ruleset; | ruleset = &parent->ruleset; | ||||
| } | } | ||||
| } | } | ||||
| int | int | ||||
| pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s, | pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s, | ||||
| const char *name) | const char *name) | ||||
| { | { | ||||
| char *p, *path; | char *p, *path; | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| r->anchor = NULL; | r->anchor = NULL; | ||||
| r->anchor_relative = 0; | r->anchor_relative = 0; | ||||
| r->anchor_wildcard = 0; | r->anchor_wildcard = 0; | ||||
| if (!name[0]) | if (!name[0]) | ||||
| return (0); | return (0); | ||||
| path = (char *)rs_malloc(MAXPATHLEN); | path = (char *)rs_malloc(MAXPATHLEN); | ||||
| if (path == NULL) | if (path == NULL) | ||||
| Show All 23 Lines | else { | ||||
| if (path[0]) | if (path[0]) | ||||
| strlcat(path, "/", MAXPATHLEN); | strlcat(path, "/", MAXPATHLEN); | ||||
| strlcat(path, name, MAXPATHLEN); | strlcat(path, name, MAXPATHLEN); | ||||
| } | } | ||||
| if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) { | if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) { | ||||
| r->anchor_wildcard = 1; | r->anchor_wildcard = 1; | ||||
| *p = 0; | *p = 0; | ||||
| } | } | ||||
| ruleset = pf_find_or_create_ruleset(path); | ruleset = pf_find_or_create_kruleset(path); | ||||
| rs_free(path); | rs_free(path); | ||||
| if (ruleset == NULL || ruleset->anchor == NULL) { | if (ruleset == NULL || ruleset->anchor == NULL) { | ||||
| printf("pf_anchor_setup: ruleset\n"); | printf("pf_anchor_setup: ruleset\n"); | ||||
| return (1); | return (1); | ||||
| } | } | ||||
| r->anchor = ruleset->anchor; | r->anchor = ruleset->anchor; | ||||
| r->anchor->refcnt++; | r->anchor->refcnt++; | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| int | int | ||||
| pf_anchor_copyout(const struct pf_ruleset *rs, const struct pf_rule *r, | pf_kanchor_copyout(const struct pf_kruleset *rs, const struct pf_krule *r, | ||||
| struct pfioc_rule *pr) | struct pfioc_rule *pr) | ||||
| { | { | ||||
| pr->anchor_call[0] = 0; | pr->anchor_call[0] = 0; | ||||
| if (r->anchor == NULL) | if (r->anchor == NULL) | ||||
| return (0); | return (0); | ||||
| if (!r->anchor_relative) { | if (!r->anchor_relative) { | ||||
| strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call)); | strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call)); | ||||
| strlcat(pr->anchor_call, r->anchor->path, | strlcat(pr->anchor_call, r->anchor->path, | ||||
| Show All 29 Lines | pf_kanchor_copyout(const struct pf_kruleset *rs, const struct pf_krule *r, | ||||
| } | } | ||||
| if (r->anchor_wildcard) | if (r->anchor_wildcard) | ||||
| strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*", | strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*", | ||||
| sizeof(pr->anchor_call)); | sizeof(pr->anchor_call)); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| void | void | ||||
| pf_anchor_remove(struct pf_rule *r) | pf_kanchor_remove(struct pf_krule *r) | ||||
| { | { | ||||
| if (r->anchor == NULL) | if (r->anchor == NULL) | ||||
| return; | return; | ||||
| if (r->anchor->refcnt <= 0) { | if (r->anchor->refcnt <= 0) { | ||||
| printf("pf_anchor_remove: broken refcount\n"); | printf("pf_anchor_remove: broken refcount\n"); | ||||
| r->anchor = NULL; | r->anchor = NULL; | ||||
| return; | return; | ||||
| } | } | ||||
| if (!--r->anchor->refcnt) | if (!--r->anchor->refcnt) | ||||
| pf_remove_if_empty_ruleset(&r->anchor->ruleset); | pf_remove_if_empty_kruleset(&r->anchor->ruleset); | ||||
| r->anchor = NULL; | r->anchor = NULL; | ||||
| } | } | ||||
| #else | |||||
| struct pf_ruleset * | |||||
| pf_find_ruleset(const char *path) | |||||
| { | |||||
| struct pf_anchor *anchor; | |||||
| while (*path == '/') | |||||
| path++; | |||||
| if (!*path) | |||||
| return (&pf_main_ruleset); | |||||
| anchor = pf_find_anchor(path); | |||||
| if (anchor == NULL) | |||||
| return (NULL); | |||||
| else | |||||
| return (&anchor->ruleset); | |||||
| } | |||||
| struct pf_ruleset * | |||||
| pf_find_or_create_ruleset(const char *path) | |||||
| { | |||||
| char *p, *q, *r; | |||||
| struct pf_ruleset *ruleset; | |||||
| struct pf_anchor *anchor = NULL, *dup, *parent = NULL; | |||||
| if (path[0] == 0) | |||||
| return (&pf_main_ruleset); | |||||
| while (*path == '/') | |||||
| path++; | |||||
| ruleset = pf_find_ruleset(path); | |||||
| if (ruleset != NULL) | |||||
| return (ruleset); | |||||
| p = (char *)rs_malloc(MAXPATHLEN); | |||||
| if (p == NULL) | |||||
| return (NULL); | |||||
| strlcpy(p, path, MAXPATHLEN); | |||||
| while (parent == NULL && (q = strrchr(p, '/')) != NULL) { | |||||
| *q = 0; | |||||
| if ((ruleset = pf_find_ruleset(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) { | |||||
| 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_anchor *)rs_malloc(sizeof(*anchor)); | |||||
| 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_anchor_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_anchor_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_anchor_global, &V_pf_anchors, | |||||
| anchor); | |||||
| rs_free(anchor); | |||||
| rs_free(p); | |||||
| return (NULL); | |||||
| } | |||||
| } | |||||
| pf_init_ruleset(&anchor->ruleset); | |||||
| anchor->ruleset.anchor = anchor; | |||||
| parent = anchor; | |||||
| if (r != NULL) | |||||
| q = r + 1; | |||||
| else | |||||
| *q = 0; | |||||
| } | |||||
| rs_free(p); | |||||
| return (&anchor->ruleset); | |||||
| } | |||||
| void | |||||
| pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset) | |||||
| { | |||||
| struct pf_anchor *parent; | |||||
| int i; | |||||
| while (ruleset != NULL) { | |||||
| if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL || | |||||
| !RB_EMPTY(&ruleset->anchor->children) || | |||||
| ruleset->anchor->refcnt > 0 || ruleset->tables > 0 || | |||||
| ruleset->topen) | |||||
| return; | |||||
| for (i = 0; i < PF_RULESET_MAX; ++i) | |||||
| if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) || | |||||
| !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) || | |||||
| ruleset->rules[i].inactive.open) | |||||
| return; | |||||
| RB_REMOVE(pf_anchor_global, &V_pf_anchors, ruleset->anchor); | |||||
| if ((parent = ruleset->anchor->parent) != NULL) | |||||
| RB_REMOVE(pf_anchor_node, &parent->children, | |||||
| ruleset->anchor); | |||||
| rs_free(ruleset->anchor); | |||||
| if (parent == NULL) | |||||
| return; | |||||
| ruleset = &parent->ruleset; | |||||
| } | |||||
| } | |||||
| int | |||||
| pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s, | |||||
| const char *name) | |||||
| { | |||||
| char *p, *path; | |||||
| struct pf_ruleset *ruleset; | |||||
| r->anchor = NULL; | |||||
| r->anchor_relative = 0; | |||||
| r->anchor_wildcard = 0; | |||||
| if (!name[0]) | |||||
| return (0); | |||||
| path = (char *)rs_malloc(MAXPATHLEN); | |||||
| if (path == NULL) | |||||
| return (1); | |||||
| if (name[0] == '/') | |||||
| strlcpy(path, name + 1, MAXPATHLEN); | |||||
| else { | |||||
| /* relative path */ | |||||
| r->anchor_relative = 1; | |||||
| if (s->anchor == NULL || !s->anchor->path[0]) | |||||
| path[0] = 0; | |||||
| else | |||||
| strlcpy(path, s->anchor->path, MAXPATHLEN); | |||||
| while (name[0] == '.' && name[1] == '.' && name[2] == '/') { | |||||
| if (!path[0]) { | |||||
| printf("pf_anchor_setup: .. beyond root\n"); | |||||
| rs_free(path); | |||||
| return (1); | |||||
| } | |||||
| if ((p = strrchr(path, '/')) != NULL) | |||||
| *p = 0; | |||||
| else | |||||
| path[0] = 0; | |||||
| r->anchor_relative++; | |||||
| name += 3; | |||||
| } | |||||
| if (path[0]) | |||||
| strlcat(path, "/", MAXPATHLEN); | |||||
| strlcat(path, name, MAXPATHLEN); | |||||
| } | |||||
| if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) { | |||||
| r->anchor_wildcard = 1; | |||||
| *p = 0; | |||||
| } | |||||
| ruleset = pf_find_or_create_ruleset(path); | |||||
| rs_free(path); | |||||
| if (ruleset == NULL || ruleset->anchor == NULL) { | |||||
| printf("pf_anchor_setup: ruleset\n"); | |||||
| return (1); | |||||
| } | |||||
| r->anchor = ruleset->anchor; | |||||
| r->anchor->refcnt++; | |||||
| return (0); | |||||
| } | |||||
| #endif | |||||