struct rspamd_map *m;
if ((m = rspamd_map_add_from_ucl (cfg, ctx->skip_map,
- "Skip hashes", rspamd_kv_list_read, rspamd_kv_list_fin,
+ "Skip hashes",
+ rspamd_kv_list_read,
+ rspamd_kv_list_fin,
+ rspamd_kv_list_dtor,
(void **)&ctx->skip_hashes)) == NULL) {
msg_warn_config ("cannot load hashes list from %s",
ucl_object_tostring (ctx->skip_map));
struct map_cb_data *data,
gboolean final);
static void rspamd_ucl_fin_cb (struct map_cb_data *data);
+static void rspamd_ucl_dtor_cb (struct map_cb_data *data);
guint rspamd_config_log_id = (guint)-1;
RSPAMD_CONSTRUCTOR(rspamd_config_log_init)
"ucl include",
rspamd_ucl_read_cb,
rspamd_ucl_fin_cb,
- (void **)pcbdata);
+ rspamd_ucl_dtor_cb,
+ (void **)pcbdata) != NULL;
}
/*
}
}
+static void
+rspamd_ucl_dtor_cb (struct map_cb_data *data)
+{
+ struct rspamd_ucl_map_cbdata *cbdata = data->cur_data;
+
+ if (cbdata != NULL) {
+ if (cbdata->buf != NULL) {
+ g_string_free (cbdata->buf, TRUE);
+ }
+ g_free (cbdata);
+ }
+}
+
gboolean
rspamd_check_module (struct rspamd_config *cfg, module_t *mod)
{
if (rspamd_map_is_map (str)) {
if (rspamd_map_add_from_ucl (cfg, cur_elt,
- description, rspamd_radix_read, rspamd_radix_fin,
+ description,
+ rspamd_radix_read,
+ rspamd_radix_fin,
+ rspamd_radix_dtor,
(void **)target) == NULL) {
g_set_error (err, g_quark_from_static_string ("rspamd-config"),
EINVAL, "bad map definition %s for %s", str,
case UCL_OBJECT:
/* Should be a map description */
if (rspamd_map_add_from_ucl (cfg, cur_elt,
- description, rspamd_radix_read, rspamd_radix_fin,
+ description,
+ rspamd_radix_read,
+ rspamd_radix_fin,
+ rspamd_radix_dtor,
(void **)target) == NULL) {
g_set_error (err, g_quark_from_static_string ("rspamd-config"),
EINVAL, "bad map object for %s", ucl_object_key (obj));
jb->cfg->current_dynamic_conf = top;
}
+static void
+json_config_dtor_cb (struct map_cb_data *data)
+{
+ struct config_json_buf *jb;
+
+ if (data->cur_data) {
+ jb = data->cur_data;
+ /* Clean prev data */
+ if (jb->buf) {
+ g_string_free (jb->buf, TRUE);
+ }
+
+ g_free (jb);
+ }
+}
+
/**
* Init dynamic configuration using map logic and specific configuration
* @param cfg config file
*pjb = jb;
cfg->current_dynamic_conf = ucl_object_typed_new (UCL_ARRAY);
- if (!rspamd_map_add (cfg, cfg->dynamic_conf, "Dynamic configuration map",
- json_config_read_cb, json_config_fin_cb, (void **)pjb)) {
+ if (!rspamd_map_add (cfg,
+ cfg->dynamic_conf,
+ "Dynamic configuration map",
+ json_config_read_cb,
+ json_config_fin_cb,
+ json_config_dtor_cb,
+ (void **)pjb)) {
msg_err ("cannot add map for configuration %s", cfg->dynamic_conf);
}
}
{
GList *cur;
struct event *events;
- struct rspamd_map *map;
/* Remove all events */
cur = worker->accept_events;
#endif
/* Cleanup maps */
- for (cur = worker->srv->cfg->maps; cur != NULL; cur = g_list_next (cur)) {
- map = cur->data;
-
- if (map->dtor) {
- map->dtor (map->dtor_data);
- }
-
- map->dtor = NULL;
- }
+ rspamd_map_remove_all (worker->srv->cfg);
}
static rspamd_fstring_t *
static void rspamd_map_schedule_periodic (struct rspamd_map *map, gboolean locked,
gboolean initial, gboolean errored);
-struct rspamd_http_map_cached_cbdata {
- struct event timeout;
- struct rspamd_storage_shmem *shm;
- struct rspamd_map *map;
- struct http_map_data *data;
- guint64 gen;
- time_t last_checked;
-};
-
guint rspamd_map_log_id = (guint)-1;
RSPAMD_CONSTRUCTOR(rspamd_map_log_init)
{
static void
free_http_cbdata (struct http_callback_data *cbd)
{
- cbd->map->dtor = NULL;
- cbd->map->dtor_data = NULL;
+ cbd->map->tmp_dtor = NULL;
+ cbd->map->tmp_dtor_data = NULL;
free_http_cbdata_common (cbd, TRUE);
}
event_add (&cache_cbd->timeout, &tv);
}
else {
+ map->cur_cache_cbd = NULL;
g_atomic_int_set (&map->cache->available, 0);
MAP_RELEASE (cache_cbd->shm, "rspamd_http_map_cached_cbdata");
msg_info_map ("cached data is now expired for %s", map->name);
cbd->periodic->cur_backend = 0;
/* Reset cache, old cached data will be cleaned on timeout */
g_atomic_int_set (&map->cache->available, 0);
+ map->cur_cache_cbd = NULL;
rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic);
MAP_RELEASE (cbd, "http_callback_data");
cache_cbd);
event_base_set (cbd->ev_base, &cache_cbd->timeout);
event_add (&cache_cbd->timeout, &tv);
+ map->cur_cache_cbd = cache_cbd;
if (map->next_check) {
rspamd_http_date_format (next_check_date, sizeof (next_check_date),
MAP_RETAIN (cbd, "http_callback_data");
}
- map->dtor = free_http_cbdata_dtor;
- map->dtor_data = cbd;
+ map->tmp_dtor = free_http_cbdata_dtor;
+ map->tmp_dtor_data = cbd;
}
else {
msg_warn_map ("cannot load map: DNS resolver is not initialized");
struct rspamd_map *map;
GList *cur;
struct rspamd_map_backend *bk;
+ struct map_cb_data cbdata;
guint i;
for (cur = cfg->maps; cur != NULL; cur = g_list_next (cur)) {
}
if (g_atomic_int_compare_and_exchange (&map->cache->available, 1, 0)) {
+ if (map->cur_cache_cbd) {
+ MAP_RELEASE (map->cur_cache_cbd->shm, "rspamd_http_map_cached_cbdata");
+ event_del (&map->cur_cache_cbd->timeout);
+ g_free (map->cur_cache_cbd);
+ map->cur_cache_cbd = NULL;
+ }
+
unlink (map->cache->shmem_name);
}
+ if (map->tmp_dtor) {
+ map->tmp_dtor (map->tmp_dtor_data);
+ }
+
if (map->dtor) {
- map->dtor (map->dtor_data);
+ cbdata.prev_data = NULL;
+ cbdata.map = map;
+ cbdata.cur_data = *map->user_data;
+
+ map->dtor (&cbdata);
+ *map->user_data = NULL;
}
}
struct rspamd_map *
rspamd_map_add (struct rspamd_config *cfg,
- const gchar *map_line,
- const gchar *description,
- map_cb_t read_callback,
- map_fin_cb_t fin_callback,
- void **user_data)
+ const gchar *map_line,
+ const gchar *description,
+ map_cb_t read_callback,
+ map_fin_cb_t fin_callback,
+ map_dtor_t dtor,
+ void **user_data)
{
struct rspamd_map *map;
struct rspamd_map_backend *bk;
map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_map));
map->read_callback = read_callback;
map->fin_callback = fin_callback;
+ map->dtor = dtor;
map->user_data = user_data;
map->cfg = cfg;
map->id = rspamd_random_uint64_fast ();
struct rspamd_map*
rspamd_map_add_from_ucl (struct rspamd_config *cfg,
- const ucl_object_t *obj,
- const gchar *description,
- map_cb_t read_callback,
- map_fin_cb_t fin_callback,
- void **user_data)
+ const ucl_object_t *obj,
+ const gchar *description,
+ map_cb_t read_callback,
+ map_fin_cb_t fin_callback,
+ map_dtor_t dtor,
+ void **user_data)
{
ucl_object_iter_t it = NULL;
const ucl_object_t *cur, *elt;
if (ucl_object_type (obj) == UCL_STRING) {
/* Just a plain string */
return rspamd_map_add (cfg, ucl_object_tostring (obj), description,
- read_callback, fin_callback, user_data);
+ read_callback, fin_callback, dtor, user_data);
}
map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_map));
map->read_callback = read_callback;
map->fin_callback = fin_callback;
+ map->dtor = dtor;
map->user_data = user_data;
map->cfg = cfg;
map->id = rspamd_random_uint64_fast ();
typedef gchar * (*map_cb_t)(gchar *chunk, gint len,
struct map_cb_data *data, gboolean final);
typedef void (*map_fin_cb_t)(struct map_cb_data *data);
+typedef void (*map_dtor_t)(struct map_cb_data *data);
typedef gboolean (*rspamd_map_traverse_cb)(gconstpointer key,
gconstpointer value, gsize hits, gpointer ud);
* Add map from line
*/
struct rspamd_map* rspamd_map_add (struct rspamd_config *cfg,
- const gchar *map_line,
- const gchar *description,
- map_cb_t read_callback,
- map_fin_cb_t fin_callback,
- void **user_data);
+ const gchar *map_line,
+ const gchar *description,
+ map_cb_t read_callback,
+ map_fin_cb_t fin_callback,
+ map_dtor_t dtor,
+ void **user_data);
/**
* Add map from ucl
*/
struct rspamd_map* rspamd_map_add_from_ucl (struct rspamd_config *cfg,
- const ucl_object_t *obj,
- const gchar *description,
- map_cb_t read_callback,
- map_fin_cb_t fin_callback,
- void **user_data);
+ const ucl_object_t *obj,
+ const gchar *description,
+ map_cb_t read_callback,
+ map_fin_cb_t fin_callback,
+ map_dtor_t dtor,
+ void **user_data);
/**
* Start watching of maps by adding events to libevent event loop
}
}
+void
+rspamd_kv_list_dtor (struct map_cb_data *data)
+{
+ struct rspamd_hash_map_helper *htb;
+
+ if (data->cur_data) {
+ htb = (struct rspamd_hash_map_helper *)data->cur_data;
+ rspamd_map_helper_destroy_hash (htb);
+ }
+}
+
gchar *
rspamd_radix_read (
gchar * chunk,
}
}
+void
+rspamd_radix_dtor (struct map_cb_data *data)
+{
+ struct rspamd_radix_map_helper *r;
+
+ if (data->cur_data) {
+ r = (struct rspamd_radix_map_helper *)data->cur_data;
+ rspamd_map_helper_destroy_radix (r);
+ }
+}
+
static void
rspamd_re_map_finalize (struct rspamd_regexp_map_helper *re_map)
{
data->map->digest = rspamd_cryptobox_fast_hash_final (&re_map->hst);
}
}
+void
+rspamd_regexp_list_dtor (struct map_cb_data *data)
+{
+ if (data->cur_data) {
+ rspamd_map_helper_destroy_regexp (data->cur_data);
+ }
+}
#ifdef WITH_HYPERSCAN
static int
struct map_cb_data *data,
gboolean final);
void rspamd_radix_fin (struct map_cb_data *data);
-
+void rspamd_radix_dtor (struct map_cb_data *data);
/**
* Kv list is an ordinal list of keys and values separated by whitespace
struct map_cb_data *data,
gboolean final);
void rspamd_kv_list_fin (struct map_cb_data *data);
+void rspamd_kv_list_dtor (struct map_cb_data *data);
/**
* Regexp list is a list of regular expressions
struct map_cb_data *data,
gboolean final);
void rspamd_regexp_list_fin (struct map_cb_data *data);
+void rspamd_regexp_list_dtor (struct map_cb_data *data);
/**
* FSM for lists parsing (support comments, blank lines and partial replies)
#include "map.h"
#include "ref.h"
-typedef void (*rspamd_map_dtor) (gpointer p);
+typedef void (*rspamd_map_tmp_dtor) (gpointer p);
extern guint rspamd_map_log_id;
#define msg_err_map(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \
"map", map->tag, \
ref_entry_t ref;
};
+struct rspamd_http_map_cached_cbdata {
+ struct event timeout;
+ struct rspamd_storage_shmem *shm;
+ struct rspamd_map *map;
+ struct http_map_data *data;
+ guint64 gen;
+ time_t last_checked;
+};
+
struct rspamd_map_cachepoint {
gint available;
gsize len;
GPtrArray *backends;
map_cb_t read_callback;
map_fin_cb_t fin_callback;
+ map_dtor_t dtor;
void **user_data;
struct event_base *ev_base;
gchar *description;
gchar *name;
guint32 id;
gboolean scheduled_check;
- rspamd_map_dtor dtor;
- gpointer dtor_data;
+ rspamd_map_tmp_dtor tmp_dtor;
+ gpointer tmp_dtor_data;
rspamd_map_traverse_function traverse_function;
gpointer lua_map;
gsize nelts;
gint *locked;
/* Shared cache data */
struct rspamd_map_cachepoint *cache;
+ /* Non-shared for cache owner, used to cleanup cache */
+ struct rspamd_http_map_cached_cbdata *cur_cache_cbd;
gchar tag[MEMPOOL_UID_LEN];
};
if ((m = rspamd_map_add (cfg, map_line, description,
rspamd_radix_read,
rspamd_radix_fin,
+ rspamd_radix_dtor,
(void **)&map->data.radix)) == NULL) {
msg_warn_config ("invalid radix map %s", map_line);
lua_pushnil (L);
if ((m = rspamd_map_add_from_ucl (cfg, fake_obj, "static radix map",
rspamd_radix_read,
rspamd_radix_fin,
+ rspamd_radix_dtor,
(void **)&map->data.radix)) == NULL) {
msg_err_config ("invalid radix map static");
lua_pushnil (L);
if ((m = rspamd_map_add_from_ucl (cfg, fake_obj, "static radix map",
rspamd_radix_read,
rspamd_radix_fin,
+ rspamd_radix_dtor,
(void **)&map->data.radix)) == NULL) {
msg_err_config ("invalid radix map static");
lua_pushnil (L);
if ((m = rspamd_map_add (cfg, map_line, description,
rspamd_kv_list_read,
rspamd_kv_list_fin,
+ rspamd_kv_list_dtor,
(void **)&map->data.hash)) == NULL) {
msg_warn_config ("invalid set map %s", map_line);
lua_pushnil (L);
if ((m = rspamd_map_add (cfg, map_line, description,
rspamd_kv_list_read,
rspamd_kv_list_fin,
+ rspamd_kv_list_dtor,
(void **)&map->data.hash)) == NULL) {
msg_warn_config ("invalid hash map %s", map_line);
lua_pushnil (L);
cbdata->data = rspamd_fstring_assign (cbdata->data, "", 0);
}
+static void
+lua_map_dtor (struct map_cb_data *data)
+{
+ struct lua_map_callback_data *cbdata;
+
+ if (data->cur_data) {
+ cbdata = (struct lua_map_callback_data *)data->cur_data;
+ if (cbdata->ref != -1) {
+ luaL_unref (cbdata->L, LUA_REGISTRYINDEX, cbdata->ref);
+ }
+
+ if (cbdata->data) {
+ rspamd_fstring_free (cbdata->data);
+ }
+ }
+}
+
gint
lua_config_add_map (lua_State *L)
{
cbdata->ref = cbidx;
if ((m = rspamd_map_add_from_ucl (cfg, map_obj, description,
- lua_map_read, lua_map_fin,
+ lua_map_read,
+ lua_map_fin,
+ lua_map_dtor,
(void **)&map->data.cbdata)) == NULL) {
if (cbidx != -1) {
if ((m = rspamd_map_add_from_ucl (cfg, map_obj, description,
rspamd_kv_list_read,
rspamd_kv_list_fin,
+ rspamd_kv_list_dtor,
(void **)&map->data.hash)) == NULL) {
lua_pushnil (L);
ucl_object_unref (map_obj);
if ((m = rspamd_map_add_from_ucl (cfg, map_obj, description,
rspamd_kv_list_read,
rspamd_kv_list_fin,
+ rspamd_kv_list_dtor,
(void **)&map->data.hash)) == NULL) {
lua_pushnil (L);
ucl_object_unref (map_obj);
if ((m = rspamd_map_add_from_ucl (cfg, map_obj, description,
rspamd_radix_read,
rspamd_radix_fin,
+ rspamd_radix_dtor,
(void **)&map->data.radix)) == NULL) {
lua_pushnil (L);
ucl_object_unref (map_obj);
if ((m = rspamd_map_add_from_ucl (cfg, map_obj, description,
rspamd_regexp_list_read_single,
rspamd_regexp_list_fin,
+ rspamd_regexp_list_dtor,
(void **) &map->data.re_map)) == NULL) {
lua_pushnil (L);
ucl_object_unref (map_obj);
if ((m = rspamd_map_add_from_ucl (cfg, map_obj, description,
rspamd_regexp_list_read_multiple,
rspamd_regexp_list_fin,
+ rspamd_regexp_list_dtor,
(void **) &map->data.re_map)) == NULL) {
lua_pushnil (L);
ucl_object_unref (map_obj);
if ((m = rspamd_map_add_from_ucl (cfg, map_obj, description,
rspamd_glob_list_read_single,
rspamd_regexp_list_fin,
+ rspamd_regexp_list_dtor,
(void **) &map->data.re_map)) == NULL) {
lua_pushnil (L);
ucl_object_unref (map_obj);
if ((value =
rspamd_config_get_module_opt (cfg, "dkim", "domains")) != NULL) {
if (!rspamd_map_add_from_ucl (cfg, value,
- "DKIM domains", rspamd_kv_list_read, rspamd_kv_list_fin,
- (void **)&dkim_module_ctx->dkim_domains)) {
+ "DKIM domains",
+ rspamd_kv_list_read,
+ rspamd_kv_list_fin,
+ rspamd_kv_list_dtor,
+ (void **)&dkim_module_ctx->dkim_domains)) {
msg_warn_config ("cannot load dkim domains list from %s",
ucl_object_tostring (value));
}
if (!got_trusted && (value =
rspamd_config_get_module_opt (cfg, "dkim", "trusted_domains")) != NULL) {
if (!rspamd_map_add_from_ucl (cfg, value,
- "DKIM domains", rspamd_kv_list_read, rspamd_kv_list_fin,
+ "DKIM domains",
+ rspamd_kv_list_read,
+ rspamd_kv_list_fin,
+ rspamd_kv_list_dtor,
(void **)&dkim_module_ctx->dkim_domains)) {
msg_warn_config ("cannot load dkim domains list from %s",
ucl_object_tostring (value));
if ((value = ucl_object_lookup (obj, "skip_hashes")) != NULL) {
rspamd_map_add_from_ucl (cfg, value,
- "Fuzzy hashes whitelist", rspamd_kv_list_read, rspamd_kv_list_fin,
- (void **)&rule->skip_map);
+ "Fuzzy hashes whitelist",
+ rspamd_kv_list_read,
+ rspamd_kv_list_fin,
+ rspamd_kv_list_dtor,
+ (void **)&rule->skip_map);
rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool,
(rspamd_mempool_destruct_t)rspamd_map_helper_destroy_radix,
rule->skip_map);
}
}
+static void
+dtor_exceptions_list (struct map_cb_data *data)
+{
+ GHashTable **t;
+ gint i;
+
+ if (data->cur_data) {
+ t = data->cur_data;
+ for (i = 0; i < MAX_LEVELS; i++) {
+ if (t[i] != NULL) {
+ g_hash_table_destroy (t[i]);
+ }
+ t[i] = NULL;
+ }
+ }
+}
+
static void
redirector_insert (gpointer st, gconstpointer key, gconstpointer value)
{
surbl_module_ctx->redirector_tlds = tld_hash;
}
+void
+dtor_redirectors_list (struct map_cb_data *data)
+{
+ GHashTable *tld_hash;
+
+ if (data->cur_data) {
+ tld_hash = data->cur_data;
+
+ g_hash_table_unref (tld_hash);
+ }
+}
+
gint
surbl_module_init (struct rspamd_config *cfg, struct module_ctx **ctx)
{
rspamd_config_get_module_opt (cfg, "surbl",
"redirector_hosts_map")) != NULL) {
if (!rspamd_map_add_from_ucl (cfg, value,
- "SURBL redirectors list", read_redirectors_list, fin_redirectors_list,
- (void **)&surbl_module_ctx->redirector_map_data)) {
+ "SURBL redirectors list",
+ read_redirectors_list,
+ fin_redirectors_list,
+ dtor_redirectors_list,
+ (void **)&surbl_module_ctx->redirector_map_data)) {
msg_warn_config ("bad redirectors map definition: %s",
ucl_obj_tostring (value));
rspamd_config_get_module_opt (cfg, "surbl", "exceptions")) != NULL) {
rspamd_map_add_from_ucl (cfg, value,
"SURBL exceptions list",
- read_exceptions_list, fin_exceptions_list,
+ read_exceptions_list,
+ fin_exceptions_list,
+ dtor_exceptions_list,
(void **)&surbl_module_ctx->exceptions);
}
if ((value =
rspamd_config_get_module_opt (cfg, "surbl", "whitelist")) != NULL) {
rspamd_map_add_from_ucl (cfg, value,
- "SURBL whitelist", rspamd_kv_list_read, rspamd_kv_list_fin,
+ "SURBL whitelist",
+ rspamd_kv_list_read,
+ rspamd_kv_list_fin,
+ rspamd_kv_list_dtor,
(void **)&surbl_module_ctx->whitelist);
}