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 |