Browse Source

[Feature] Implement settings id propagation between deps

tags/2.0
Vsevolod Stakhov 4 years ago
parent
commit
7e081148fd
4 changed files with 166 additions and 57 deletions
  1. 160
    53
      src/libserver/rspamd_symcache.c
  2. 2
    1
      src/libserver/rspamd_symcache.h
  3. 2
    1
      src/lua/lua_config.c
  4. 2
    2
      src/plugins/surbl.c

+ 160
- 53
src/libserver/rspamd_symcache.c View File

@@ -193,9 +193,10 @@ struct rspamd_symcache_dynamic_item {


struct cache_dependency {
struct rspamd_symcache_item *item;
gchar *sym;
gint id;
struct rspamd_symcache_item *item; /* Real dependency */
gchar *sym; /* Symbolic dep name */
gint id; /* Real from */
gint vid; /* Virtual from */
};

struct delayed_cache_dependency {
@@ -533,12 +534,139 @@ rspamd_symcache_resort (struct rspamd_symcache *cache)
cache->items_by_order = ord;
}

static void
rspamd_symcache_propagate_dep (struct rspamd_symcache *cache,
struct rspamd_symcache_item *it,
struct rspamd_symcache_item *dit)
{
const guint *ids;
guint nids = 0;

ids = rspamd_symcache_get_allowed_settings_ids (cache, dit->symbol, &nids);

/* TODO: merge? */
if (nids > 0) {
msg_info_cache ("propagate allowed ids from %s to %s",
dit->symbol, it->symbol);

rspamd_symcache_set_allowed_settings_ids (cache, it->symbol, ids,
nids);
}

ids = rspamd_symcache_get_forbidden_settings_ids (cache, dit->symbol, &nids);

if (nids > 0) {
msg_info_cache ("propagate forbidden ids from %s to %s",
dit->symbol, it->symbol);

rspamd_symcache_set_forbidden_settings_ids (cache, it->symbol, ids,
nids);
}
}

static void
rspamd_symcache_process_dep (struct rspamd_symcache *cache,
struct rspamd_symcache_item *it,
struct cache_dependency *dep)
{
struct rspamd_symcache_item *dit = NULL, *vdit = NULL;
struct cache_dependency *rdep;

if (dep->id >= 0) {
dit = rspamd_symcache_find_filter (cache, dep->sym, true);
}

if (dep->vid >= 0) {
/* Case of the virtual symbol that depends on another (maybe virtual) symbol */
vdit = rspamd_symcache_find_filter (cache, dep->sym, false);
}
else {
vdit = dit;
}

if (dit != NULL) {
if (!dit->is_filter) {
/*
* Check sanity:
* - filters -> prefilter dependency is OK and always satisfied
* - postfilter -> (filter, prefilter) dep is ok
* - idempotent -> (any) dep is OK
*
* Otherwise, emit error
* However, even if everything is fine this dep is useless ¯\_(ツ)_/¯
*/
gboolean ok_dep = FALSE;

if (it->is_filter) {
if (dit->type & SYMBOL_TYPE_PREFILTER) {
ok_dep = TRUE;
}
}
else if (it->type & SYMBOL_TYPE_POSTFILTER) {
if (dit->type & SYMBOL_TYPE_PREFILTER) {
ok_dep = TRUE;
}
}
else if (it->type & SYMBOL_TYPE_IDEMPOTENT) {
if (dit->type & (SYMBOL_TYPE_PREFILTER|SYMBOL_TYPE_POSTFILTER)) {
ok_dep = TRUE;
}
}
else if (it->type & SYMBOL_TYPE_PREFILTER) {
if (it->priority < dit->priority) {
/* Also OK */
ok_dep = TRUE;
}
}

if (!ok_dep) {
msg_err_cache ("cannot add dependency from %s on %s: invalid symbol types",
dep->sym, dit->symbol);

return;
}
}
else {
if (dit->id == it->id) {
msg_err_cache ("cannot add dependency on self: %s -> %s "
"(resolved to %s)",
it->symbol, dep->sym, dit->symbol);
} else {
rdep = rspamd_mempool_alloc (cache->static_pool,
sizeof (*rdep));

rdep->sym = dep->sym;
rdep->item = it;
rdep->id = it->id;
g_assert (dit->rdeps != NULL);
g_ptr_array_add (dit->rdeps, rdep);
dep->item = dit;
dep->id = dit->id;

msg_debug_cache ("add dependency from %d on %d", it->id,
dit->id);
}
}
}
else if (dep->id >= 0) {
msg_err_cache ("cannot find dependency on symbol %s for symbol %s",
dep->sym, it->symbol);

return;
}

if (vdit) {
/* Use virtual symbol to propagate deps */
rspamd_symcache_propagate_dep (cache, it, vdit);
}
}

/* Sort items in logical order */
static void
rspamd_symcache_post_init (struct rspamd_symcache *cache)
{
struct rspamd_symcache_item *it, *dit;
struct cache_dependency *dep, *rdep;
struct rspamd_symcache_item *it, *vit;
struct cache_dependency *dep;
struct delayed_cache_dependency *ddep;
struct delayed_cache_condition *dcond;
GList *cur;
@@ -548,6 +676,7 @@ rspamd_symcache_post_init (struct rspamd_symcache *cache)
while (cur) {
ddep = cur->data;

vit = rspamd_symcache_find_filter (cache, ddep->from, false);
it = rspamd_symcache_find_filter (cache, ddep->from, true);

if (it == NULL) {
@@ -555,9 +684,9 @@ rspamd_symcache_post_init (struct rspamd_symcache *cache)
"%s is missing", ddep->from, ddep->to, ddep->from);
}
else {
msg_debug_cache ("delayed between %s(%d) -> %s", ddep->from,
it->id, ddep->to);
rspamd_symcache_add_dependency (cache, it->id, ddep->to);
msg_debug_cache ("delayed between %s(%d:%d) -> %s", ddep->from,
it->id, vit->id, ddep->to);
rspamd_symcache_add_dependency (cache, it->id, ddep->to, vit->id);
}

cur = g_list_next (cur);
@@ -585,40 +714,7 @@ rspamd_symcache_post_init (struct rspamd_symcache *cache)
PTR_ARRAY_FOREACH (cache->items_by_id, i, it) {

PTR_ARRAY_FOREACH (it->deps, j, dep) {
dit = rspamd_symcache_find_filter (cache, dep->sym, true);

if (dit != NULL) {
if (!dit->is_filter) {
msg_err_cache ("cannot depend on non filter symbol "
"(%s wants to add dependency on %s)",
dep->sym, dit->symbol);
}
else {
if (dit->id == i) {
msg_err_cache ("cannot add dependency on self: %s -> %s "
"(resolved to %s)",
it->symbol, dep->sym, dit->symbol);
} else {
rdep = rspamd_mempool_alloc (cache->static_pool,
sizeof (*rdep));

rdep->sym = dep->sym;
rdep->item = it;
rdep->id = i;
g_assert (dit->rdeps != NULL);
g_ptr_array_add (dit->rdeps, rdep);
dep->item = dit;
dep->id = dit->id;

msg_debug_cache ("add dependency from %d on %d", it->id,
dit->id);
}
}
}
else {
msg_err_cache ("cannot find dependency on symbol %s for symbol %s",
dep->sym, it->symbol);
}
rspamd_symcache_process_dep (cache, it, dep);
}

if (it->deps) {
@@ -1083,15 +1179,12 @@ rspamd_symcache_add_symbol (struct rspamd_symcache *cache,
cache->used_items, item->id);
}

if (item->is_filter) {
/* Only plain filters can have deps and rdeps */
item->deps = g_ptr_array_new ();
item->rdeps = g_ptr_array_new ();
rspamd_mempool_add_destructor (cache->static_pool,
rspamd_ptr_array_free_hard, item->deps);
rspamd_mempool_add_destructor (cache->static_pool,
rspamd_ptr_array_free_hard, item->rdeps);
}
item->deps = g_ptr_array_new ();
item->rdeps = g_ptr_array_new ();
rspamd_mempool_add_destructor (cache->static_pool,
rspamd_ptr_array_free_hard, item->deps);
rspamd_mempool_add_destructor (cache->static_pool,
rspamd_ptr_array_free_hard, item->rdeps);

if (name != NULL) {
g_hash_table_insert (cache->items_by_symbol, item->symbol, item);
@@ -2384,9 +2477,10 @@ rspamd_symcache_inc_frequency (struct rspamd_symcache *cache,

void
rspamd_symcache_add_dependency (struct rspamd_symcache *cache,
gint id_from, const gchar *to)
gint id_from, const gchar *to,
gint virtual_id_from)
{
struct rspamd_symcache_item *source;
struct rspamd_symcache_item *source, *vsource;
struct cache_dependency *dep;

g_assert (id_from >= 0 && id_from < (gint)cache->items_by_id->len);
@@ -2397,7 +2491,20 @@ rspamd_symcache_add_dependency (struct rspamd_symcache *cache,
dep->sym = rspamd_mempool_strdup (cache->static_pool, to);
/* Will be filled later */
dep->item = NULL;
dep->vid = -1;
g_ptr_array_add (source->deps, dep);

if (id_from != virtual_id_from) {
/* We need that for settings id propagation */
vsource = g_ptr_array_index (cache->items_by_id, virtual_id_from);
dep = rspamd_mempool_alloc (cache->static_pool, sizeof (*dep));
dep->vid = id_from;
dep->id = -1;
dep->sym = rspamd_mempool_strdup (cache->static_pool, to);
/* Will be filled later */
dep->item = NULL;
g_ptr_array_add (vsource->deps, dep);
}
}

void

+ 2
- 1
src/libserver/rspamd_symcache.h View File

@@ -224,7 +224,8 @@ void rspamd_symcache_inc_frequency (struct rspamd_symcache *cache,
* @param to destination name
*/
void rspamd_symcache_add_dependency (struct rspamd_symcache *cache,
gint id_from, const gchar *to);
gint id_from, const gchar *to,
gint virtual_id_from);

/**
* Add delayed dependency that is resolved on cache post-load routine

+ 2
- 1
src/lua/lua_config.c View File

@@ -2206,7 +2206,8 @@ lua_config_register_dependency (lua_State * L)

if (child_id > 0 && parent != NULL) {

rspamd_symcache_add_dependency (cfg->cache, child_id, parent);
rspamd_symcache_add_dependency (cfg->cache, child_id, parent,
child_id);
}
}
else {

+ 2
- 2
src/plugins/surbl.c View File

@@ -868,7 +868,7 @@ surbl_module_parse_rule (const ucl_object_t* value, struct rspamd_config* cfg)
1,
1);
rspamd_symcache_add_dependency (cfg->cache, cb_id,
SURBL_REDIRECTOR_CALLBACK);
SURBL_REDIRECTOR_CALLBACK, cb_id);
/* Failure symbol */
g_string_append (sym, "_FAIL");
rspamd_symcache_add_symbol (cfg->cache, sym->str,
@@ -1205,7 +1205,7 @@ surbl_module_config (struct rspamd_config *cfg)

if (cur_suffix->options & SURBL_OPTION_CHECKDKIM) {
rspamd_symcache_add_dependency (cfg->cache,
cur_suffix->callback_id, "DKIM_TRACE");
cur_suffix->callback_id, "DKIM_TRACE", cur_suffix->callback_id);
}

cur_opt = g_list_next (cur_opt);

Loading…
Cancel
Save