From 85b3f42f215e5736d90a803835f506673538bbd0 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 12 Feb 2016 14:44:35 +0000 Subject: [PATCH] Initial support for dynamic modules and workers --- src/libserver/cfg_file.h | 2 + src/libserver/cfg_utils.c | 93 ++++++++++++++++++++++++++++++++++--- src/libserver/worker_util.c | 29 +++++++++--- src/plugins/regexp.c | 3 +- src/plugins/spf.c | 3 +- src/rspamd.c | 1 + src/rspamd.h | 25 ++++++++-- 7 files changed, 139 insertions(+), 17 deletions(-) diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h index 7b49e4866..44e838dd6 100644 --- a/src/libserver/cfg_file.h +++ b/src/libserver/cfg_file.h @@ -341,6 +341,8 @@ struct rspamd_config { GList *classify_headers; /**< list of headers using for statistics */ struct module_s **compiled_modules; /**< list of compiled C modules */ struct worker_s **compiled_workers; /**< list of compiled C modules */ + GList *dynamic_modules; /**< list of dynamic C modules */ + GList *dynamic_workers; /**< list of dynamic C modules */ struct rspamd_log_format *log_format; /**< parsed log format */ gchar *log_format_str; /**< raw log format string */ diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c index 66a67fe13..bd2aac89b 100644 --- a/src/libserver/cfg_utils.c +++ b/src/libserver/cfg_utils.c @@ -1129,6 +1129,64 @@ rspamd_ucl_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) } } +gboolean +rspamd_check_module (struct rspamd_config *cfg, module_t *mod) +{ + gboolean ret = TRUE; + + if (mod != NULL) { + if (mod->module_version != RSPAMD_CUR_MODULE_VERSION) { + msg_err_config ("module %s has incorrect version %xd (%xd expected)", + mod->name, mod->module_version, RSPAMD_CUR_MODULE_VERSION); + ret = FALSE; + } + if (ret && mod->rspamd_version != RSPAMD_VERSION_NUM) { + msg_err_config ("module %s has incorrect rspamd version %xd (%xd expected)", + mod->name, mod->rspamd_version, RSPAMD_VERSION_NUM); + ret = FALSE; + } + if (ret && strcmp (mod->rspamd_features, RSPAMD_FEATURES) != 0) { + msg_err_config ("module %s has incorrect rspamd features '%s' ('%s' expected)", + mod->name, mod->rspamd_features, RSPAMD_FEATURES); + ret = FALSE; + } + } + else { + ret = FALSE; + } + + return ret; +} + +gboolean +rspamd_check_worker (struct rspamd_config *cfg, worker_t *wrk) +{ + gboolean ret = TRUE; + + if (wrk != NULL) { + if (wrk->worker_version != RSPAMD_CUR_WORKER_VERSION) { + msg_err_config ("worker %s has incorrect version %xd (%xd expected)", + wrk->name, wrk->worker_version, RSPAMD_CUR_WORKER_VERSION); + ret = FALSE; + } + if (ret && wrk->rspamd_version != RSPAMD_VERSION_NUM) { + msg_err_config ("worker %s has incorrect rspamd version %xd (%xd expected)", + wrk->name, wrk->rspamd_version, RSPAMD_VERSION_NUM); + ret = FALSE; + } + if (ret && strcmp (wrk->rspamd_features, RSPAMD_FEATURES) != 0) { + msg_err_config ("worker %s has incorrect rspamd features '%s' ('%s' expected)", + wrk->name, wrk->rspamd_features, RSPAMD_FEATURES); + ret = FALSE; + } + } + else { + ret = FALSE; + } + + return ret; +} + gboolean rspamd_init_filters (struct rspamd_config *cfg, bool reconfig) { @@ -1140,17 +1198,40 @@ rspamd_init_filters (struct rspamd_config *cfg, bool reconfig) if (!reconfig) { for (pmod = cfg->compiled_modules; pmod != NULL && *pmod != NULL; pmod ++) { mod = *pmod; - mod_ctx = g_slice_alloc0 (sizeof (struct module_ctx)); - if (mod->module_init_func (cfg, &mod_ctx) == 0) { - g_hash_table_insert (cfg->c_modules, - (gpointer) mod->name, - mod_ctx); - mod_ctx->mod = mod; + if (rspamd_check_module (cfg, mod)) { + mod_ctx = g_slice_alloc0 (sizeof (struct module_ctx)); + + if (mod->module_init_func (cfg, &mod_ctx) == 0) { + g_hash_table_insert (cfg->c_modules, + (gpointer) mod->name, + mod_ctx); + mod_ctx->mod = mod; + } } } + + cur = g_list_first (cfg->dynamic_modules); + + while (cur) { + mod = cur->data; + + if (rspamd_check_module (cfg, mod)) { + mod_ctx = g_slice_alloc0 (sizeof (struct module_ctx)); + + if (mod->module_init_func (cfg, &mod_ctx) == 0) { + g_hash_table_insert (cfg->c_modules, + (gpointer) mod->name, + mod_ctx); + mod_ctx->mod = mod; + } + } + + cur = g_list_next (cur); + } } + /* Now check what's enabled */ cur = g_list_first (cfg->filters); while (cur) { diff --git a/src/libserver/worker_util.c b/src/libserver/worker_util.c index 8bda8d709..b18c36ec9 100644 --- a/src/libserver/worker_util.c +++ b/src/libserver/worker_util.c @@ -49,14 +49,31 @@ worker_t * rspamd_get_worker_by_type (struct rspamd_config *cfg, GQuark type) { - worker_t **cur; + worker_t **pwrk, *wrk; + GList *cur; - cur = cfg->compiled_workers; - while (cur && *cur) { - if (g_quark_from_string ((*cur)->name) == type) { - return *cur; + pwrk = cfg->compiled_workers; + while (pwrk && *pwrk) { + if (rspamd_check_worker (cfg, *pwrk)) { + if (g_quark_from_string ((*pwrk)->name) == type) { + return *pwrk; + } } - cur++; + + pwrk++; + } + + cur = g_list_first (cfg->dynamic_workers); + while (cur) { + wrk = cur->data; + + if (rspamd_check_worker (cfg, wrk)) { + if (g_quark_from_string (wrk->name) == type) { + return wrk; + } + } + + cur = g_list_next (cur); } return NULL; diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index 7273d87d7..fbe612fbc 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -52,7 +52,8 @@ module_t regexp_module = { regexp_module_init, regexp_module_config, regexp_module_reconfig, - NULL + NULL, + RSPAMD_MODULE_VER }; /* Process regexp expression */ diff --git a/src/plugins/spf.c b/src/plugins/spf.c index a73c06c71..a02dcc002 100644 --- a/src/plugins/spf.c +++ b/src/plugins/spf.c @@ -64,7 +64,8 @@ module_t spf_module = { spf_module_init, spf_module_config, spf_module_reconfig, - NULL + NULL, + RSPAMD_MODULE_VER }; static GQuark diff --git a/src/rspamd.c b/src/rspamd.c index a7cf68a20..abbce74a0 100644 --- a/src/rspamd.c +++ b/src/rspamd.c @@ -459,6 +459,7 @@ spawn_workers (struct rspamd_main *rspamd_main, struct event_base *ev_base) gboolean listen_ok = FALSE, seen_hs_helper = FALSE; GQuark qtype; + /* Special hack for hs_helper if it's not defined in a config */ qtype = g_quark_try_string ("hs_helper"); cur = rspamd_main->cfg->workers; diff --git a/src/rspamd.h b/src/rspamd.h index e5c7bb4db..0c7668bfa 100644 --- a/src/rspamd.h +++ b/src/rspamd.h @@ -117,17 +117,20 @@ struct module_ctx { #define RSPAMD_FEATURE_SNOWBALL "1" #endif +#define RSPAMD_CUR_MODULE_VERSION 0x1 +#define RSPAMD_CUR_WORKER_VERSION 0x1 + #define RSPAMD_FEATURES \ RSPAMD_FEATURE_HYPERSCAN RSPAMD_FEATURE_PCRE2 \ RSPAMD_FEATURE_FANN RSPAMD_FEATURE_SNOWBALL #define RSPAMD_MODULE_VER \ - 0x1, /* Module version */ \ + RSPAMD_CUR_MODULE_VERSION, /* Module version */ \ RSPAMD_VERSION_NUM, /* Rspamd version */ \ RSPAMD_FEATURES /* Compilation features */ \ #define RSPAMD_WORKER_VER \ - 0x1, /* Worker version */ \ + RSPAMD_CUR_WORKER_VERSION, /* Worker version */ \ RSPAMD_VERSION_NUM, /* Rspamd version */ \ RSPAMD_FEATURES /* Compilation features */ \ /** @@ -154,11 +157,27 @@ typedef struct worker_s { gboolean threaded; gboolean killable; gint listen_type; - guint module_version; + guint worker_version; guint64 rspamd_version; const gchar *rspamd_features; } worker_t; +/** + * Check if loaded worker is compatible with rspamd + * @param cfg + * @param wrk + * @return + */ +gboolean rspamd_check_worker (struct rspamd_config *cfg, worker_t *wrk); + +/** + * Check if loaded module is compatible with rspamd + * @param cfg + * @param wrk + * @return + */ +gboolean rspamd_check_module (struct rspamd_config *cfg, module_t *wrk); + struct pidfh; struct rspamd_config; struct tokenizer; -- 2.39.5