uint16_t master_port;
};
+typedef double (*statfile_normalize_func)(double score, void *params);
+
/**
* Statfile config definition
*/
GList *sections; /**< list of sections in statfile */
struct statfile_autolearn_params *autolearn; /**< autolearn params */
struct statfile_binlog_params *binlog; /**< binlog params */
+ statfile_normalize_func normalizer; /**< function that is used as normaliser */
+ void *normalizer_data; /**< normalizer function params */
};
/**
GHashTable* c_modules; /**< hash of c modules indexed by module name */
GHashTable* composite_symbols; /**< hash of composite symbols indexed by its name */
GList *classifiers; /**< list of all classifiers defined */
+ GList *statfiles; /**< list of all statfiles in config file order */
GHashTable *classifiers_symbols; /**< hashtable indexed by symbol name of classifiers */
GHashTable* cfg_params; /**< all cfg params indexed by its name in this structure */
int clock_res; /**< resolution of clock used */
GList* parse_comma_list (memory_pool_t *pool, char *line);
struct classifier_config* check_classifier_cfg (struct config_file *cfg, struct classifier_config *c);
struct worker_conf* check_worker_conf (struct config_file *cfg, struct worker_conf *c);
+gboolean parse_normalizer (struct config_file *cfg, struct statfile *st, const char *line);
int yylex (void);
int yyparse (void);
<classifier_lex_state>binlog return BINLOG;
<classifier_lex_state>binlog_master return BINLOG_MASTER;
<classifier_lex_state>binlog_rotate return BINLOG_ROTATE;
+<classifier_lex_state>normalizer return NORMALIZER;
<classifier_lex_state>[0-9]+ yylval.number=strtol(yytext, NULL, 10); return NUMBER;
<classifier_lex_state>-?[0-9]+\.?[0-9]* yylval.fract=strtod(yytext, NULL); return FRACT;
<classifier_lex_state>[0-9]+[kKmMgG]? yylval.limit=parse_limit(yytext); return SIZELIMIT;
%token VIEW IP FROM SYMBOLS CLIENT_IP
%token AUTOLEARN MIN_MARK MAX_MARK MAXFILES MAXCORE
%token SETTINGS USER_SETTINGS DOMAIN_SETTINGS SYMBOL PATH SKIP_CHECK GROW_FACTOR
-%token LOG_BUFFER DEBUG_IP
+%token LOG_BUFFER DEBUG_IP NORMALIZER
%type <string> STRING
%type <string> VARIABLE
}
cur_classifier = check_classifier_cfg (cfg, cur_classifier);
cur_classifier->statfiles = g_list_prepend (cur_classifier->statfiles, cur_statfile);
+ cfg->statfiles = g_list_prepend (cfg->statfiles, cur_statfile);
cur_statfile = NULL;
}
;
| statfilebinlog
| statfilebinlogrotate
| statfilebinlogmaster
+ | statfilenormalizer
;
statfilesymbol:
}
;
+statfilenormalizer:
+ NORMALIZER EQSIGN QUOTEDSTRING {
+ if (!parse_normalizer (cfg, cur_statfile, $3)) {
+ yyerror ("cannot parse normalizer string: %s", $3);
+ YYERROR;
+ }
+ }
+ ;
+
statfile_pool_size:
STATFILE_POOL_SIZE EQSIGN SIZELIMIT {
#include "filter.h"
#include "settings.h"
#include "classifiers/classifiers.h"
+#ifdef WITH_LUA
+#include "lua/lua_common.h"
+#endif
#define DEFAULT_SCORE 10.0
return c;
}
+
+static double
+internal_normalizer_func (double score, void *data)
+{
+ double max = *(double *)data;
+
+ if (score < 0) {
+ return score;
+ }
+ else if (score > 0.001 && score > 1) {
+ return 1;
+ }
+ else if (score > 1 && score < max / 2.) {
+ return MIN(max, score * score);
+ }
+ else if (score < max) {
+ return score;
+ }
+ else if (score > max) {
+ return max;
+ }
+
+ return score;
+}
+
+static gboolean
+parse_internal_normalizer (struct config_file *cfg, struct statfile *st, const char *line)
+{
+ double *max;
+ char *err;
+
+ /* Line contains maximum value for internal normalizer */
+ max = memory_pool_alloc (cfg->cfg_pool, sizeof (double));
+
+ errno = 0;
+ *max = strtod (line, &err);
+
+ if (errno != 0 || *err != '\0') {
+ msg_err ("cannot parse max number for internal normalizer");
+ return FALSE;
+ }
+
+ st->normalizer = internal_normalizer_func;
+ st->normalizer_data = (void *)max;
+ return TRUE;
+}
+
+#ifdef WITH_LUA
+static gboolean
+parse_lua_normalizer (struct config_file *cfg, struct statfile *st, const char *line)
+{
+ char *code_begin;
+ GList *params = NULL;
+ int len;
+
+ code_begin = strchr (line, ':');
+
+ if (code_begin == NULL) {
+ /* Just function name without code */
+ params = g_list_prepend (g_list_prepend (NULL, NULL), memory_pool_strdup (cfg->cfg_pool, line));
+ }
+ else {
+ /* Postpone actual code load as lua libraries are not loaded */
+ /* Put code to list */
+ params = g_list_prepend (NULL, code_begin + 1);
+ /* Put function name */
+ len = code_begin - line;
+ code_begin = memory_pool_alloc (cfg->cfg_pool, len + 1);
+ g_strlcpy (code_begin, line, len + 1);
+ params = g_list_prepend (params, code_begin);
+ }
+ memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_list_free, params);
+ st->normalizer = lua_normalizer_func;
+ st->normalizer_data = params;
+ return TRUE;
+}
+#endif
+
+
+gboolean
+parse_normalizer (struct config_file *cfg, struct statfile *st, const char *line)
+{
+ char *params_begin;
+
+ params_begin = strchr (line, ':');
+ if (params_begin == NULL) {
+ msg_err ("no parameters are specified for normalizer %s", line);
+ return FALSE;
+ }
+
+ /* Try to guess normalizer */
+ if (g_ascii_strncasecmp (line, "internal", sizeof ("points")) == 0) {
+ return parse_internal_normalizer (cfg, st, params_begin + 1);
+ }
+#ifdef WITH_LUA
+ else if (g_ascii_strncasecmp (line, "points", sizeof ("points")) == 0) {
+ return parse_lua_normalizer (cfg, st, params_begin + 1);
+ }
+#endif
+
+ msg_err ("unknown normalizer %s", line);
+ return FALSE;
+}
+
/*
* vi:ts=4
*/
}
}
+
+
void
init_lua_filters (struct config_file *cfg)
{
struct config_file **pcfg;
- GList *cur;
+ GList *cur, *tmp;
struct script_module *module;
+ struct statfile *st;
init_lua ();
cur = g_list_first (cfg->script_modules);
}
cur = g_list_next (cur);
}
+ /* Init statfiles normalizers */
+ cur = g_list_first (cfg->statfiles);
+ while (cur) {
+ st = cur->data;
+ if (st->normalizer == lua_normalizer_func) {
+ tmp = st->normalizer_data;
+ if (tmp && (tmp = g_list_next (tmp))) {
+ if (tmp->data) {
+ /* Code must be loaded from data */
+ if (luaL_loadstring (L, tmp->data) != 0) {
+ msg_info ("cannot load normalizer code %s", tmp->data);
+ }
+ }
+ }
+ }
+ cur = g_list_next (cur);
+ }
}
/* Callback functions */
lua_pop (L, 1); /* pop error message from the stack */
}
}
+
+double
+lua_normalizer_func (double score, void *params)
+{
+ GList *p = params;
+ double res = score;
+
+ /* Call specified function and put input score on stack */
+ if (!p->data) {
+ msg_info ("bad function name while calling normalizer");
+ return score;
+ }
+
+ lua_getglobal (L, p->data);
+ lua_pushnumber (L, score);
+
+ if (lua_pcall (L, 1, 1, 0) != 0) {
+ msg_info ("call to %s failed", p->data);
+ }
+
+ /* retrieve result */
+ if (!lua_isnumber (L, -1)) {
+ msg_info ("function %s must return a number", p->data);
+ }
+ res = lua_tonumber (L, -1);
+
+ return res;
+}
GList *call_classifier_pre_callbacks (struct classifier_config *ccf, struct worker_task *task);
double call_classifier_post_callbacks (struct classifier_config *ccf, struct worker_task *task, double in);
+double lua_normalizer_func (double score, void *params);
+
#endif /* WITH_LUA */
#endif /* RSPAMD_LUA_H */
if (additional != NULL) {
/* We have additional parameter defined, so ignore type of regexp expression and use it for parsing */
- if (g_regex_match_full (regexp, additional, strlen (additional), 0, 0, NULL, NULL) == TRUE) {
+ if (g_regex_match_full (re->regexp, additional, strlen (additional), 0, 0, NULL, NULL) == TRUE) {
task_cache_add (task, re, 1);
return 1;
}