Browse Source

[Project] More steps to flexible actions

tags/1.9.0
Vsevolod Stakhov 5 years ago
parent
commit
96986ba7f7
3 changed files with 152 additions and 39 deletions
  1. 11
    2
      src/libserver/cfg_file.h
  2. 106
    29
      src/libserver/cfg_utils.c
  3. 35
    8
      src/lua/lua_config.c

+ 11
- 2
src/libserver/cfg_file.h View File

@@ -29,7 +29,6 @@
#include "libutil/radix.h"
#include "monitored.h"
#include "redis_pool.h"
#include "contrib/uthash/uthash.h"

#define DEFAULT_BIND_PORT 11333
#define DEFAULT_CONTROL_PORT 11334
@@ -280,6 +279,7 @@ enum rspamd_action_flags {
RSPAMD_ACTION_HAM = (1u << 2),
};

struct UT_hash_handle;
/**
* Action config definition
*/
@@ -290,7 +290,7 @@ struct rspamd_action {
gint lua_handler_ref; /* If special handling is needed */
gdouble threshold;
gchar *name;
UT_hash_handle hh; /* Index by name */
struct UT_hash_handle hh; /* Index by name */
};

struct rspamd_config_post_load_script {
@@ -699,6 +699,15 @@ gboolean rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
struct rspamd_radix_map_helper **target,
GError **err);

/**
* Returns action object by name
* @param cfg
* @param name
* @return
*/
struct rspamd_action * rspamd_config_get_action (struct rspamd_config *cfg,
const gchar *name);

#define msg_err_config(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \
cfg->cfg_pool->tag.tagname, cfg->checksum, \
G_STRFUNC, \

+ 106
- 29
src/libserver/cfg_utils.c View File

@@ -17,6 +17,8 @@

#include "cfg_file.h"
#include "rspamd.h"
#include "../../contrib/mumhash/mum.h"
#define HASH_CASELESS
#include "uthash_strcase.h"
#include "filter.h"
#include "lua/lua_common.h"
@@ -1038,12 +1040,6 @@ rspamd_config_init_metric (struct rspamd_config *cfg)
cfg->symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
cfg->groups = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);

for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) {
cfg->actions[i].score = NAN;
cfg->actions[i].action = i;
cfg->actions[i].priority = 0;
}

cfg->subject = SPAM_SUBJECT;
rspamd_mempool_add_destructor (cfg->cfg_pool,
(rspamd_mempool_destruct_t) g_hash_table_unref,
@@ -1912,6 +1908,72 @@ rspamd_config_is_module_enabled (struct rspamd_config *cfg,
return TRUE;
}

static gboolean
rspamd_config_action_from_ucl (struct rspamd_config *cfg,
struct rspamd_action *act,
const ucl_object_t *obj,
guint priority)
{
const ucl_object_t *elt;
gdouble threshold = NAN;
guint flags = 0, std_act;

elt = ucl_object_lookup_any (obj, "score", "threshold", NULL);

if (elt) {
threshold = ucl_object_todouble (elt);
}

elt = ucl_object_lookup_any (obj, "flags");

if (elt && ucl_object_type (elt) == UCL_ARRAY) {
const ucl_object_t *cur;
ucl_object_iter_t it = NULL;

while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
if (ucl_object_type (cur) == UCL_STRING) {
const gchar *fl_str = ucl_object_tostring (cur);

if (g_ascii_strcasecmp (fl_str, "no_threshold") == 0) {
flags |= RSPAMD_ACTION_NO_THRESHOLD;
}
else if (g_ascii_strcasecmp (fl_str, "threshold_only") == 0) {
flags |= RSPAMD_ACTION_THRESHOLD_ONLY;
}
else if (g_ascii_strcasecmp (fl_str, "ham") == 0) {
flags |= RSPAMD_ACTION_HAM;
}
else {
msg_warn_config ("unknown action flag: %s", fl_str);
}
}
}
}

/* TODO: add lua references support */

if (isnan (threshold) && !(flags & RSPAMD_ACTION_NO_THRESHOLD)) {
msg_err_config ("action %s has no threshold being set and it is not"
" a no threshold action", act->name);

return FALSE;
}

act->threshold = threshold;
act->flags = flags;

if (rspamd_action_from_str (act->name, &std_act)) {
act->action = std_act;
}
else {
act->action = METRIC_ACTION_CUSTOM;
}

rspamd_actions_sort (cfg);

return TRUE;
}

gboolean
rspamd_config_set_action_score (struct rspamd_config *cfg,
const gchar *action_name,
@@ -1919,52 +1981,67 @@ rspamd_config_set_action_score (struct rspamd_config *cfg,
{
struct rspamd_action *act;
const ucl_object_t *elt;
guint priority = ucl_object_get_priority (obj);

g_assert (cfg != NULL);
g_assert (action_name != NULL);

elt = ucl_object_lookup (obj, "priority");

if (elt) {
priority = ucl_object_toint (elt);
}

HASH_FIND_STR (cfg->actions, action_name, act);

if (act) {
/* Existing element */
}
else {
/* Add new element */
act = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*act));
}
act = &cfg->actions[act_num];

if (isnan (act->threshold)) {
act->score = score;
act->priority = priority;
}
else {
if (act->priority > priority) {
if (act->priority <= priority) {
/* We can replace data */
msg_info_config ("action %s has been already registered with "
"priority %ud, do not override (new priority: %ud)",
"priority %ud, override it with new priority: %ud, "
"old score: %.2f, new score: %.2f",
action_name,
act->priority,
priority);
return FALSE;
priority,
act->threshold,
ucl_object_todouble (
ucl_object_lookup_any (obj, "score", "threshold", NULL)));
return rspamd_config_action_from_ucl (cfg, act, obj, priority);
}
else {
msg_info_config ("action %s has been already registered with "
"priority %ud, override it with new priority: %ud, "
"old score: %.2f, new score: %.2f",
"priority %ud, do not override (new priority: %ud)",
action_name,
act->priority,
priority,
act->threshold,
score);
priority);
}
}
else {
/* Add new element */
act = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*act));
act->name = rspamd_mempool_strdup (cfg->cfg_pool, action_name);

act->score = score;
act->priority = priority;
if (rspamd_config_action_from_ucl (cfg, act, obj, priority)) {
HASH_ADD_STR (cfg->actions, name, act);
}
else {
return FALSE;
}
}

return TRUE;
}

struct rspamd_action *
rspamd_config_get_action (struct rspamd_config *cfg, const gchar *name)
{
struct rspamd_action *res = NULL;

HASH_FIND_STR (cfg->actions, name, res);

return res;
}

gboolean
rspamd_config_radix_from_ucl (struct rspamd_config *cfg,

+ 35
- 8
src/lua/lua_config.c View File

@@ -2127,9 +2127,10 @@ lua_config_set_metric_action (lua_State * L)
LUA_TRACE_POINT;
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *name = NULL;
double weight;
double threshold = NAN;
GError *err = NULL;
gdouble priority = 0.0;
ucl_object_t *obj_tbl = NULL;

if (cfg) {

@@ -2137,7 +2138,7 @@ lua_config_set_metric_action (lua_State * L)
if (!rspamd_lua_parse_table_arguments (L, 2, &err,
"*action=S;score=N;"
"priority=N",
&name, &weight,
&name, &threshold,
&priority)) {
msg_err_config ("bad arguments: %e", err);
g_error_free (err);
@@ -2145,12 +2146,36 @@ lua_config_set_metric_action (lua_State * L)
return 0;
}
}
else if (lua_type (L, 2) == LUA_TSTRING && lua_type (L, 3) == LUA_TTABLE) {
name = lua_tostring (L, 2);
obj_tbl = ucl_object_lua_import (L, 3);

if (obj_tbl) {
if (name) {
rspamd_config_set_action_score (cfg, name, obj_tbl);
ucl_object_unref (obj_tbl);
}
else {
ucl_object_unref (obj_tbl);
return luaL_error (L, "invalid first argument, action name expected");
}
}
else {
return luaL_error (L, "invalid second argument, table expected");
}
}
else {
return luaL_error (L, "invalid arguments, table expected");
}

if (name != NULL && weight != 0) {
rspamd_config_set_action_score (cfg, name, weight, (guint)priority);
if (name != NULL && !isnan (threshold) && threshold != 0) {
obj_tbl = ucl_object_typed_new (UCL_OBJECT);
ucl_object_insert_key (obj_tbl, ucl_object_fromdouble (threshold),
"score", 0, false);
ucl_object_insert_key (obj_tbl, ucl_object_fromdouble (priority),
"priority", 0, false);
rspamd_config_set_action_score (cfg, name, obj_tbl);
ucl_object_unref (obj_tbl);
}
}
else {
@@ -2166,12 +2191,14 @@ lua_config_get_metric_action (lua_State * L)
LUA_TRACE_POINT;
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *act_name = luaL_checkstring (L, 2);
gint act = 0;
struct rspamd_action *act;

if (cfg && act_name) {
if (rspamd_action_from_str (act_name, &act)) {
if (!isnan (cfg->actions[act].threshold)) {
lua_pushnumber (L, cfg->actions[act].threshold);
act = rspamd_config_get_action (cfg, act_name);

if (act) {
if (!isnan (act->threshold)) {
lua_pushnumber (L, act->threshold);
}
else {
lua_pushnil (L);

Loading…
Cancel
Save