Use kbtree BST for exact match in user, keyword, and ip 'from' fields

So, now we use two separate data structures: binary search trees (BST)
for exact match and linked lists for substring match.

Currently, only user, keyword, and ip 'from' fields in filtering rules
use these two data structures. This also means that now we support exact
and substring matches in 'from' fields.

Filtering rules should be written with exact matches instead of
substring matches, as much as possible. Because BST search must be much
faster than substring search over linked lists.

We have modifed kbtree to support complex data structures in from
fields.
pull/48/head
Soner Tari 3 years ago
parent 95dd3bb9f8
commit 15991dfb93

@ -5,9 +5,9 @@
(Divert|Split|Pass|Block|Match)
([from (
user (username|$macro|*) [desc (keyword|$macro|*)]|
desc (keyword|$macro|*)|
ip (clientip|$macro|*)|
user (username[*]|$macro|*) [desc (keyword[*]|$macro|*)]|
desc (keyword[*]|$macro|*)|
ip (clientip[*]|$macro|*)|
*)]
[to (
sni (servername[*]|$macro|*)|

@ -295,9 +295,9 @@ The syntax of filtering rules is as follows:
(Divert|Split|Pass|Block|Match)
([from (
user (username|$macro|*) [desc (keyword|$macro|*)]|
desc (keyword|$macro|*)|
ip (clientip|$macro|*)|
user (username[*]|$macro|*) [desc (keyword[*]|$macro|*)]|
desc (keyword[*]|$macro|*)|
ip (clientip[*]|$macro|*)|
*)]
[to (
sni (servername[*]|$macro|*)|
@ -405,9 +405,9 @@ Macro expansion is supported. The `Define` option can be used for defining
macros to be used in filtering rules. Macro names must start with a `$` char.
The macro name must be followed by words separated with spaces.
You can append an asterisk `*` to the site field of filtering rules for
substring matching. Otherwise, the filter searches for an exact match with the
site field in the rule.
You can append an asterisk `*` to the fields in filtering rules for substring
matching. Otherwise, the filter searches for an exact match with the field in
the rule.
The ordering of filtering rules is important. The ordering of from, to, and
log parts is not important. The ordering of log actions is not important.

File diff suppressed because it is too large Load Diff

@ -29,6 +29,7 @@
#define FILTER_H
#include "opts.h"
#include "kbtree.h"
#define FILTER_ACTION_NONE 0x00000000U
#define FILTER_ACTION_MATCH 0x00000200U
@ -90,15 +91,20 @@ typedef struct filter_action {
typedef struct filter_rule {
// from: source filter
unsigned int all_conns : 1; /* 1 to apply to all src ips and users */
unsigned int all_conns : 1; /* 1 to apply to all src ips and users */
#ifndef WITHOUT_USERAUTH
unsigned int all_users : 1; /* 1 to apply to all users */
unsigned int all_users : 1; /* 1 to apply to all users */
char *user;
unsigned int exact_user : 1; /* 1 for exact, 0 for substring match */
char *keyword;
unsigned int exact_keyword : 1; /* 1 for exact, 0 for substring match */
#endif /* !WITHOUT_USERAUTH */
char *ip;
unsigned int exact_ip : 1; /* 1 for exact, 0 for substring match */
// to: target filter
char *site;
@ -157,31 +163,65 @@ typedef struct filter_list {
typedef struct filter_ip {
char *ip;
struct filter_list *list;
struct filter_ip *next;
} filter_ip_t;
typedef struct filter_ip_list {
struct filter_ip *ip;
struct filter_ip_list *next;
} filter_ip_list_t;
#ifndef WITHOUT_USERAUTH
typedef struct filter_keyword {
char *keyword;
struct filter_list *list;
struct filter_keyword *next;
} filter_keyword_t;
typedef const char *str_t;
#define getk_keyword(a) (a)->keyword
typedef filter_keyword_t *filter_keyword_p_t;
KBTREE_INIT(keyword, filter_keyword_p_t, kb_str_cmp, str_t, getk_keyword)
typedef struct filter_keyword_list {
struct filter_keyword *keyword;
struct filter_keyword_list *next;
} filter_keyword_list_t;
typedef struct filter_user {
char *user;
struct filter_list *list;
struct filter_keyword *keyword;
struct filter_user *next;
kbtree_t(keyword) *keyword_btree;
struct filter_keyword_list *keyword_list;
} filter_user_t;
#define getk_user(a) (a)->user
typedef filter_user_t *filter_user_p_t;
KBTREE_INIT(user, filter_user_p_t, kb_str_cmp, str_t, getk_user)
typedef struct filter_user_list {
struct filter_user *user;
struct filter_user_list *next;
} filter_user_list_t;
#endif /* !WITHOUT_USERAUTH */
#define getk_ip(a) (a)->ip
typedef filter_ip_t *filter_ip_p_t;
KBTREE_INIT(ip, filter_ip_p_t, kb_str_cmp, str_t, getk_ip)
typedef struct filter {
#ifndef WITHOUT_USERAUTH
struct filter_user *user;
struct filter_keyword *keyword;
kbtree_t(user) *user_btree; // exact
struct filter_user_list *user_list; // substring
kbtree_t(keyword) *keyword_btree; // exact
struct filter_keyword_list *keyword_list; // substring
struct filter_list *all_user;
#endif /* !WITHOUT_USERAUTH */
struct filter_ip *ip;
kbtree_t(ip) *ip_btree; // exact
struct filter_ip_list *ip_list; // substring
struct filter_list *all;
} filter_t;
@ -206,10 +246,10 @@ char *filter_str(filter_t *);
int filter_passsite_set(opts_t *, char *, int) WUNRES;
int filter_macro_set(opts_t *, char *, int) WUNRES;
filter_ip_t *filter_ip_find(filter_ip_t *, char *) NONNULL(2);
filter_ip_t *filter_ip_find(filter_t *, char *) NONNULL(1,2);
#ifndef WITHOUT_USERAUTH
filter_keyword_t *filter_keyword_find(filter_keyword_t *, char *) NONNULL(2);
filter_user_t *filter_user_find(filter_user_t *, char *) NONNULL(2);
filter_keyword_t *filter_keyword_find(filter_t *, filter_user_t *, char *) NONNULL(1,3);
filter_user_t *filter_user_find(filter_t *, char *) NONNULL(1,2);
#endif /* !WITHOUT_USERAUTH */
int filter_rule_set(opts_t *, const char *, char *, int) NONNULL(1,2,3) WUNRES;
filter_t *filter_set(filter_rule_t *);

@ -0,0 +1,450 @@
/*-
* Copyright 1997-1999, 2001, John-Mark Gurney.
* 2008-2009, Attractive Chaos <attractor@live.co.uk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This is a modified version of the original kbtree implementation. This
* version supports comparing tree nodes of complex data types using
* customized keys. So, key-value pairs can be stored in kbtree.
*
* - The __getk() parameter is used to get the key to be used with the __cmp()
* comparison function.
* - The key_t parameter is the type of the key returned by __getk().
*
* For example, the tree nodes can be considered as the values of key-value
* pairs, which may be of a complex data type. And the key may a field in that
* complex data type.
*/
#ifndef __AC_KBTREE_H
#define __AC_KBTREE_H
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define KB_MAX_DEPTH 64
typedef struct {
__uint32_t is_internal:1, n:31;
} kbnode_t;
typedef struct {
kbnode_t *x;
int i;
} kbpos_t;
typedef struct {
kbpos_t stack[KB_MAX_DEPTH], *p;
} kbitr_t;
#define __KB_KEY(type, x) ((type*)((char*)x + 4))
#define __KB_PTR(btr, x) ((kbnode_t**)((char*)x + btr->off_ptr))
#define __KB_TREE_T(name) \
typedef struct { \
kbnode_t *root; \
int off_key, off_ptr, ilen, elen; \
int n, t; \
int n_keys, n_nodes; \
} kbtree_##name##_t;
#define __KB_INIT(name, node_t) \
static UNUSED inline kbtree_##name##_t *kb_init_##name(int size) \
{ \
kbtree_##name##_t *b; \
b = (kbtree_##name##_t*)calloc(1, sizeof(kbtree_##name##_t)); \
b->t = ((size - 4 - sizeof(void*)) / (sizeof(void*) + sizeof(node_t)) + 1) >> 1; \
if (b->t < 2) { \
free(b); return 0; \
} \
b->n = 2 * b->t - 1; \
b->off_ptr = 4 + b->n * sizeof(node_t); \
b->ilen = (4 + sizeof(void*) + b->n * (sizeof(void*) + sizeof(node_t)) + 3) >> 2 << 2; \
b->elen = (b->off_ptr + 3) >> 2 << 2; \
b->root = (kbnode_t*)calloc(1, b->ilen); \
++b->n_nodes; \
return b; \
}
#define __kb_destroy(b) do { \
int i, max = 8; \
kbnode_t *x, **top, **stack = 0; \
if (b) { \
top = stack = (kbnode_t**)calloc(max, sizeof(kbnode_t*)); \
*top++ = (b)->root; \
while (top != stack) { \
x = *--top; \
if (x->is_internal == 0) { free(x); continue; } \
for (i = 0; i <= x->n; ++i) \
if (__KB_PTR(b, x)[i]) { \
if (top - stack == max) { \
max <<= 1; \
stack = (kbnode_t**)realloc(stack, max * sizeof(kbnode_t*)); \
top = stack + (max>>1); \
} \
*top++ = __KB_PTR(b, x)[i]; \
} \
free(x); \
} \
} \
free(b); free(stack); \
} while (0)
#define __KB_GET_AUX1(name, node_t, __cmp, key_t, __getk) \
static UNUSED inline int __kb_getp_aux_##name(kbnode_t * x, const key_t k, int *r) \
{ \
int tr, *rr, begin = 0, end = x->n; \
if (x->n == 0) return -1; \
rr = r? r : &tr; \
while (begin < end) { \
int mid = (begin + end) >> 1; \
if (__cmp(__getk(__KB_KEY(node_t, x)[mid]), k) < 0) begin = mid + 1; \
else end = mid; \
} \
if (begin == x->n) { *rr = 1; return x->n - 1; } \
if ((*rr = __cmp(k, __getk(__KB_KEY(node_t, x)[begin]))) < 0) --begin; \
return begin; \
}
#define __KB_GET(name, node_t, key_t) \
static node_t *kb_getp_##name(kbtree_##name##_t *b, const key_t k) \
{ \
int i, r = 0; \
kbnode_t *x = b->root; \
while (x) { \
i = __kb_getp_aux_##name(x, k, &r); \
if (i >= 0 && r == 0) return &__KB_KEY(node_t, x)[i]; \
if (x->is_internal == 0) return 0; \
x = __KB_PTR(b, x)[i + 1]; \
} \
return 0; \
} \
static UNUSED inline node_t *kb_get_##name(kbtree_##name##_t *b, const key_t k) \
{ \
return kb_getp_##name(b, k); \
}
#define __KB_INTERVAL(name, node_t, __getk) \
static void kb_intervalp_##name(kbtree_##name##_t *b, node_t * k, node_t **lower, node_t **upper) \
{ \
int i, r = 0; \
kbnode_t *x = b->root; \
*lower = *upper = 0; \
while (x) { \
i = __kb_getp_aux_##name(x, __getk(*k), &r); \
if (i >= 0 && r == 0) { \
*lower = *upper = &__KB_KEY(node_t, x)[i]; \
return; \
} \
if (i >= 0) *lower = &__KB_KEY(node_t, x)[i]; \
if (i < x->n - 1) *upper = &__KB_KEY(node_t, x)[i + 1]; \
if (x->is_internal == 0) return; \
x = __KB_PTR(b, x)[i + 1]; \
} \
} \
static UNUSED inline void kb_interval_##name(kbtree_##name##_t *b, node_t k, node_t **lower, node_t **upper) \
{ \
kb_intervalp_##name(b, &k, lower, upper); \
}
#define __KB_PUT(name, node_t, __cmp, __getk) \
/* x must be an internal node */ \
static void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \
{ \
kbnode_t *z; \
z = (kbnode_t*)calloc(1, y->is_internal? b->ilen : b->elen); \
++b->n_nodes; \
z->is_internal = y->is_internal; \
z->n = b->t - 1; \
memcpy(__KB_KEY(node_t, z), __KB_KEY(node_t, y) + b->t, sizeof(node_t) * (b->t - 1)); \
if (y->is_internal) memcpy(__KB_PTR(b, z), __KB_PTR(b, y) + b->t, sizeof(void*) * b->t); \
y->n = b->t - 1; \
memmove(__KB_PTR(b, x) + i + 2, __KB_PTR(b, x) + i + 1, sizeof(void*) * (x->n - i)); \
__KB_PTR(b, x)[i + 1] = z; \
memmove(__KB_KEY(node_t, x) + i + 1, __KB_KEY(node_t, x) + i, sizeof(node_t) * (x->n - i)); \
__KB_KEY(node_t, x)[i] = __KB_KEY(node_t, y)[b->t - 1]; \
++x->n; \
} \
static node_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, node_t * k) \
{ \
int i = x->n - 1; \
node_t *ret; \
if (x->is_internal == 0) { \
i = __kb_getp_aux_##name(x, __getk(*k), 0); \
if (i != x->n - 1) \
memmove(__KB_KEY(node_t, x) + i + 2, __KB_KEY(node_t, x) + i + 1, (x->n - i - 1) * sizeof(node_t)); \
ret = &__KB_KEY(node_t, x)[i + 1]; \
*ret = *k; \
++x->n; \
} else { \
i = __kb_getp_aux_##name(x, __getk(*k), 0) + 1; \
if (__KB_PTR(b, x)[i]->n == 2 * b->t - 1) { \
__kb_split_##name(b, x, i, __KB_PTR(b, x)[i]); \
if (__cmp(__getk(*k), __getk(__KB_KEY(node_t, x)[i])) > 0) ++i; \
} \
ret = __kb_putp_aux_##name(b, __KB_PTR(b, x)[i], k); \
} \
return ret; \
} \
static node_t *kb_putp_##name(kbtree_##name##_t *b, node_t * k) \
{ \
kbnode_t *r, *s; \
++b->n_keys; \
r = b->root; \
if (r->n == 2 * b->t - 1) { \
++b->n_nodes; \
s = (kbnode_t*)calloc(1, b->ilen); \
b->root = s; s->is_internal = 1; s->n = 0; \
__KB_PTR(b, s)[0] = r; \
__kb_split_##name(b, s, 0, r); \
r = s; \
} \
return __kb_putp_aux_##name(b, r, k); \
} \
static UNUSED inline void kb_put_##name(kbtree_##name##_t *b, node_t k) \
{ \
kb_putp_##name(b, &k); \
}
#define __KB_DEL(name, node_t, __getk) \
static node_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, node_t * k, int s) \
{ \
int yn, zn, i, r = 0; \
kbnode_t *xp, *y, *z; \
node_t kp; \
if (x == 0) return *k; \
if (s) { /* s can only be 0, 1 or 2 */ \
r = x->is_internal == 0? 0 : s == 1? 1 : -1; \
i = s == 1? x->n - 1 : -1; \
} else i = __kb_getp_aux_##name(x, __getk(*k), &r); \
if (x->is_internal == 0) { \
if (s == 2) ++i; \
kp = __KB_KEY(node_t, x)[i]; \
memmove(__KB_KEY(node_t, x) + i, __KB_KEY(node_t, x) + i + 1, (x->n - i - 1) * sizeof(node_t)); \
--x->n; \
return kp; \
} \
if (r == 0) { \
if ((yn = __KB_PTR(b, x)[i]->n) >= b->t) { \
xp = __KB_PTR(b, x)[i]; \
kp = __KB_KEY(node_t, x)[i]; \
__KB_KEY(node_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 1); \
return kp; \
} else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= b->t) { \
xp = __KB_PTR(b, x)[i + 1]; \
kp = __KB_KEY(node_t, x)[i]; \
__KB_KEY(node_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 2); \
return kp; \
} else if (yn == b->t - 1 && zn == b->t - 1) { \
y = __KB_PTR(b, x)[i]; z = __KB_PTR(b, x)[i + 1]; \
__KB_KEY(node_t, y)[y->n++] = *k; \
memmove(__KB_KEY(node_t, y) + y->n, __KB_KEY(node_t, z), z->n * sizeof(node_t)); \
if (y->is_internal) memmove(__KB_PTR(b, y) + y->n, __KB_PTR(b, z), (z->n + 1) * sizeof(void*)); \
y->n += z->n; \
memmove(__KB_KEY(node_t, x) + i, __KB_KEY(node_t, x) + i + 1, (x->n - i - 1) * sizeof(node_t)); \
memmove(__KB_PTR(b, x) + i + 1, __KB_PTR(b, x) + i + 2, (x->n - i - 1) * sizeof(void*)); \
--x->n; \
free(z); \
return __kb_delp_aux_##name(b, y, k, s); \
} \
} \
++i; \
if ((xp = __KB_PTR(b, x)[i])->n == b->t - 1) { \
if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= b->t) { \
memmove(__KB_KEY(node_t, xp) + 1, __KB_KEY(node_t, xp), xp->n * sizeof(node_t)); \
if (xp->is_internal) memmove(__KB_PTR(b, xp) + 1, __KB_PTR(b, xp), (xp->n + 1) * sizeof(void*)); \
__KB_KEY(node_t, xp)[0] = __KB_KEY(node_t, x)[i - 1]; \
__KB_KEY(node_t, x)[i - 1] = __KB_KEY(node_t, y)[y->n - 1]; \
if (xp->is_internal) __KB_PTR(b, xp)[0] = __KB_PTR(b, y)[y->n]; \
--y->n; ++xp->n; \
} else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= b->t) { \
__KB_KEY(node_t, xp)[xp->n++] = __KB_KEY(node_t, x)[i]; \
__KB_KEY(node_t, x)[i] = __KB_KEY(node_t, y)[0]; \
if (xp->is_internal) __KB_PTR(b, xp)[xp->n] = __KB_PTR(b, y)[0]; \
--y->n; \
memmove(__KB_KEY(node_t, y), __KB_KEY(node_t, y) + 1, y->n * sizeof(node_t)); \
if (y->is_internal) memmove(__KB_PTR(b, y), __KB_PTR(b, y) + 1, (y->n + 1) * sizeof(void*)); \
} else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == b->t - 1) { \
__KB_KEY(node_t, y)[y->n++] = __KB_KEY(node_t, x)[i - 1]; \
memmove(__KB_KEY(node_t, y) + y->n, __KB_KEY(node_t, xp), xp->n * sizeof(node_t)); \
if (y->is_internal) memmove(__KB_PTR(b, y) + y->n, __KB_PTR(b, xp), (xp->n + 1) * sizeof(void*)); \
y->n += xp->n; \
memmove(__KB_KEY(node_t, x) + i - 1, __KB_KEY(node_t, x) + i, (x->n - i) * sizeof(node_t)); \
memmove(__KB_PTR(b, x) + i, __KB_PTR(b, x) + i + 1, (x->n - i) * sizeof(void*)); \
--x->n; \
free(xp); \
xp = y; \
} else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == b->t - 1) { \
__KB_KEY(node_t, xp)[xp->n++] = __KB_KEY(node_t, x)[i]; \
memmove(__KB_KEY(node_t, xp) + xp->n, __KB_KEY(node_t, y), y->n * sizeof(node_t)); \
if (xp->is_internal) memmove(__KB_PTR(b, xp) + xp->n, __KB_PTR(b, y), (y->n + 1) * sizeof(void*)); \
xp->n += y->n; \
memmove(__KB_KEY(node_t, x) + i, __KB_KEY(node_t, x) + i + 1, (x->n - i - 1) * sizeof(node_t)); \
memmove(__KB_PTR(b, x) + i + 1, __KB_PTR(b, x) + i + 2, (x->n - i - 1) * sizeof(void*)); \
--x->n; \
free(y); \
} \
} \
return __kb_delp_aux_##name(b, xp, k, s); \
} \
static node_t kb_delp_##name(kbtree_##name##_t *b, node_t * k) \
{ \
kbnode_t *x; \
node_t ret; \
ret = __kb_delp_aux_##name(b, b->root, k, 0); \
--b->n_keys; \
if (b->root->n == 0 && b->root->is_internal) { \
--b->n_nodes; \
x = b->root; \
b->root = __KB_PTR(b, x)[0]; \
free(x); \
} \
return ret; \
} \
static UNUSED inline node_t kb_del_##name(kbtree_##name##_t *b, node_t k) \
{ \
return kb_delp_##name(b, &k); \
}
#define __KB_ITR(name, node_t, __getk) \
static UNUSED inline void kb_itr_first_##name(kbtree_##name##_t *b, kbitr_t *itr) \
{ \
itr->p = 0; \
if (b->n_keys == 0) return; \
itr->p = itr->stack; \
itr->p->x = b->root; itr->p->i = 0; \
while (itr->p->x->is_internal && __KB_PTR(b, itr->p->x)[0] != 0) { \
kbnode_t *x = itr->p->x; \
++itr->p; \
itr->p->x = __KB_PTR(b, x)[0]; itr->p->i = 0; \
} \
} \
static UNUSED inline int kb_itr_get_##name(kbtree_##name##_t *b, node_t * k, kbitr_t *itr) \
{ \
int i, r = 0; \
itr->p = itr->stack; \
itr->p->x = b->root; itr->p->i = 0; \
while (itr->p->x) { \
i = __kb_getp_aux_##name(itr->p->x, __getk(*k), &r); \
if (i >= 0 && r == 0) return 0; \
if (itr->p->x->is_internal == 0) return -1; \
itr->p[1].x = __KB_PTR(b, itr->p->x)[i + 1]; \
itr->p[1].i = i; \
++itr->p; \
} \
return -1; \
} \
static UNUSED inline int kb_itr_next_##name(kbtree_##name##_t *b, kbitr_t *itr) \
{ \
if (itr->p < itr->stack) return 0; \
for (;;) { \
++itr->p->i; \
while (itr->p->x && itr->p->i <= itr->p->x->n) { \
itr->p[1].i = 0; \
itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \
++itr->p; \
} \
--itr->p; \
if (itr->p < itr->stack) return 0; \
if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \
} \
}
#define KBTREE_INIT(name, node_t, __cmp, key_t, __getk) \
__KB_TREE_T(name) \
__KB_INIT(name, node_t) \
__KB_GET_AUX1(name, node_t, __cmp, key_t, __getk) \
__KB_GET(name, node_t, key_t) \
__KB_INTERVAL(name, node_t, __getk) \
__KB_PUT(name, node_t, __cmp, __getk) \
__KB_DEL(name, node_t, __getk) \
__KB_ITR(name, node_t, __getk)
#define KB_DEFAULT_SIZE 512
#define kbtree_t(name) kbtree_##name##_t
#define kb_init(name, s) kb_init_##name(s)
#define kb_destroy(name, b) __kb_destroy(b)
#define kb_get(name, b, k) kb_get_##name(b, k)
#define kb_put(name, b, k) kb_put_##name(b, k)
#define kb_del(name, b, k) kb_del_##name(b, k)
#define kb_interval(name, b, k, l, u) kb_interval_##name(b, k, l, u)
#define kb_getp(name, b, k) kb_getp_##name(b, k)
#define kb_putp(name, b, k) kb_putp_##name(b, k)
#define kb_delp(name, b, k) kb_delp_##name(b, k)
#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u)
#define kb_itr_first(name, b, i) kb_itr_first_##name(b, i)
#define kb_itr_get(name, b, k, i) kb_itr_get_##name(b, k, i)
#define kb_itr_next(name, b, i) kb_itr_next_##name(b, i)
#define kb_itr_key(type, itr) __KB_KEY(type, (itr)->p->x)[(itr)->p->i]
#define kb_itr_valid(itr) ((itr)->p >= (itr)->stack)
#define kb_size(b) ((b)->n_keys)
#define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b)))
#define kb_str_cmp(a, b) strcmp(a, b)
/* The following is *DEPRECATED*!!! Use the iterator interface instead! */
typedef struct {
kbnode_t *x;
int i;
} __kbstack_t;
#define __kb_traverse(node_t, b, __func) do { \
int __kmax = 8; \
__kbstack_t *__kstack, *__kp; \
__kp = __kstack = (__kbstack_t*)calloc(__kmax, sizeof(__kbstack_t)); \
__kp->x = (b)->root; __kp->i = 0; \
for (;;) { \
while (__kp->x && __kp->i <= __kp->x->n) { \
if (__kp - __kstack == __kmax - 1) { \
__kmax <<= 1; \
__kstack = (__kbstack_t*)realloc(__kstack, __kmax * sizeof(__kbstack_t)); \
__kp = __kstack + (__kmax>>1) - 1; \
} \
(__kp+1)->i = 0; (__kp+1)->x = __kp->x->is_internal? __KB_PTR(b, __kp->x)[__kp->i] : 0; \
++__kp; \
} \
--__kp; \
if (__kp >= __kstack) { \
if (__kp->x && __kp->i < __kp->x->n) __func(&__KB_KEY(node_t, __kp->x)[__kp->i]); \
++__kp->i; \
} else break; \
} \
free(__kstack); \
} while (0)
#define __kb_get_first(node_t, b, ret) do { \
kbnode_t *__x = (b)->root; \
while (__KB_PTR(b, __x)[0] != 0) \
__x = __KB_PTR(b, __x)[0]; \
(ret) = __KB_KEY(node_t, __x)[0]; \
} while (0)
#endif /* __AC_KBTREE_H */

@ -2078,11 +2078,11 @@ pxyconn_filter(pxy_conn_ctx_t *ctx, proto_filter_func_t filtercb)
#ifndef WITHOUT_USERAUTH
if (ctx->user) {
log_finest_va("Searching user: %s", ctx->user);
filter_user_t *user = filter_user_find(filter->user, ctx->user);
filter_user_t *user = filter_user_find(filter, ctx->user);
if (user) {
if (ctx->desc) {
log_finest_va("Searching user keyword: %s, %s", ctx->user, ctx->desc);
filter_keyword_t *keyword = filter_keyword_find(user->keyword, ctx->desc);
filter_keyword_t *keyword = filter_keyword_find(filter, user, ctx->desc);
if (keyword && (action = filtercb(ctx, keyword->list))) {
return action;
}
@ -2094,7 +2094,7 @@ pxyconn_filter(pxy_conn_ctx_t *ctx, proto_filter_func_t filtercb)
if (ctx->desc) {
log_finest_va("Searching keyword: %s", ctx->desc);
filter_keyword_t *keyword = filter_keyword_find(filter->keyword, ctx->desc);
filter_keyword_t *keyword = filter_keyword_find(filter, user, ctx->desc);
if (keyword && (action = filtercb(ctx, keyword->list))) {
return action;
}
@ -2108,7 +2108,7 @@ pxyconn_filter(pxy_conn_ctx_t *ctx, proto_filter_func_t filtercb)
#endif /* !WITHOUT_USERAUTH */
if (ctx->srchost_str) {
log_finest_va("Searching ip: %s", ctx->srchost_str);
filter_ip_t *ip = filter_ip_find(filter->ip, ctx->srchost_str);
filter_ip_t *ip = filter_ip_find(filter, ctx->srchost_str);
if (ip && (action = filtercb(ctx, ip->list))) {
return action;
}

@ -308,9 +308,9 @@ The syntax of filtering rules is as follows:
(Divert|Split|Pass|Block|Match)
([from (
user (username|$macro|*) [desc (keyword|$macro|*)]|
desc (keyword|$macro|*)|
ip (clientip|$macro|*)|
user (username[*]|$macro|*) [desc (keyword[*]|$macro|*)]|
desc (keyword[*]|$macro|*)|
ip (clientip[*]|$macro|*)|
*)]
[to (
sni (servername[*]|$macro|*)|
@ -419,9 +419,9 @@ Macro expansion is supported. The Define option can be used for defining
macros to be used in filtering rules. Macro names must start with a $ char.
The macro name must be followed by words separated with spaces.
.LP
You can append an asterisk * to the site field of filtering rules for
substring matching. Otherwise, the filter searches for an exact match with the
site field in the rule.
You can append an asterisk * to the fields in filtering rules for substring
matching. Otherwise, the filter searches for an exact match with the field in
the rule.
.LP
The ordering of filtering rules is important. The ordering of from, to, and
log parts is not important. The ordering of log actions is not important.

@ -291,9 +291,9 @@ PassUsers admin
#
#(Divert|Split|Pass|Block|Match)
# ([from (
# user (username|$macro|*) [desc (keyword|$macro|*)]|
# desc (keyword|$macro|*)|
# ip (clientip|$macro|*)|
# user (username[*]|$macro|*) [desc (keyword[*]|$macro|*)]|
# desc (keyword[*]|$macro|*)|
# ip (clientip[*]|$macro|*)|
# *)]
# [to (
# sni (servername[*]|$macro|*)|

@ -353,9 +353,9 @@ The syntax of filtering rules is as follows:
(Divert|Split|Pass|Block|Match)
([from (
user (username|$macro|*) [desc (keyword|$macro|*)]|
desc (keyword|$macro|*)|
ip (clientip|$macro|*)|
user (username[*]|$macro|*) [desc (keyword[*]|$macro|*)]|
desc (keyword[*]|$macro|*)|
ip (clientip[*]|$macro|*)|
*)]
[to (
sni (servername[*]|$macro|*)|

Loading…
Cancel
Save