From f86068d197719b8758fc0a2aeb8556526b2331f8 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 20 Jul 2009 19:33:48 +0400 Subject: [PATCH] * Introduce new common system of map files, that can be used for different types of maps. This includes new logic of callbacks and callbacks calling, files are monitored with evtimers with jittering. HTTP support would be included soon as well. --- CMakeLists.txt | 3 +- src/map.c | 365 +++++++++++++++++++++++++++++++++++++++++++ src/map.h | 55 +++++++ src/plugins/emails.c | 9 +- src/plugins/surbl.c | 25 +-- src/util.c | 185 +--------------------- src/util.h | 6 +- src/view.c | 20 +-- src/worker.c | 4 + 9 files changed, 451 insertions(+), 221 deletions(-) create mode 100644 src/map.c create mode 100644 src/map.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c4dcbb72..2a76296d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(rspamd C) SET(RSPAMD_VERSION_MAJOR 0) SET(RSPAMD_VERSION_MINOR 2) -SET(RSPAMD_VERSION_PATCH 4) +SET(RSPAMD_VERSION_PATCH 5) SET(RSPAMD_VERSION "${RSPAMD_VERSION_MAJOR}.${RSPAMD_VERSION_MINOR}.${RSPAMD_VERSION_PATCH}") SET(RSPAMD_MASTER_SITE_URL "http://cebka.pp.ru/hg/rspamd") @@ -321,6 +321,7 @@ SET(RSPAMDSRC src/modules.c src/lmtp_proto.c src/radix.c src/view.c + src/map.c src/symbols_cache.c) IF(ENABLE_PERL MATCHES "ON") diff --git a/src/map.c b/src/map.c new file mode 100644 index 000000000..a1ba5251d --- /dev/null +++ b/src/map.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2009, Rambler media + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY Rambler media ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Rambler BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Implementation of map files handling + */ +#include "config.h" +#include "map.h" +#include "main.h" +#include "util.h" +#include "mem_pool.h" + +static memory_pool_t *map_pool = NULL; + +static GList *maps = NULL; +static char *hash_fill = "1"; + +/* Value in seconds after whitch we would try to do stat on list file */ +#define MON_TIMEOUT 10 + +static void +read_map_file (struct rspamd_map *map, struct file_map_data *data) +{ + struct map_cb_data cbdata; + char buf[BUFSIZ]; + ssize_t r; + int fd; + + if (map->read_callback == NULL || map->fin_callback == NULL) { + msg_err ("read_map_file: bad callback for reading map file"); + return; + } + + if ((fd = open (data->filename, O_RDONLY)) == -1) { + msg_warn ("read_map_file: cannot open file '%s': %s", data->filename, strerror (errno)); + return; + } + + cbdata.state = 0; + cbdata.prev_data = *map->user_data; + cbdata.cur_data = NULL; + + while ((r = read (fd, buf, sizeof (buf) - 1)) > 0) { + buf[r ++] = '\0'; + map->read_callback (map->pool, buf, r, &cbdata); + } + + close (fd); + + map->fin_callback (map->pool, &cbdata); + *map->user_data = cbdata.cur_data; +} + +gboolean +add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data) +{ + struct rspamd_map *new_map; + enum fetch_proto proto; + const char *def, *p; + struct file_map_data *fdata; + struct http_map_data *hdata; + char portbuf[6]; + int i, s, fd; + struct hostent *hent; + + /* First of all detect protocol line */ + if (strncmp (map_line, "http://", sizeof ("http://") - 1) == 0) { + proto = PROTO_HTTP; + def = map_line + sizeof ("http://") - 1; + } + else if (strncmp (map_line, "file://", sizeof ("file://") - 1) == 0) { + proto = PROTO_FILE; + def = map_line + sizeof ("file://") - 1; + } + else { + msg_err ("add_map: invalid map fetching protocol: %s", map_line); + return FALSE; + } + /* Constant pool */ + if (map_pool == NULL) { + map_pool = memory_pool_new (memory_pool_get_size ()); + } + new_map = memory_pool_alloc (map_pool, sizeof (struct rspamd_map)); + new_map->read_callback = read_callback; + new_map->fin_callback = fin_callback; + new_map->user_data = user_data; + new_map->protocol = proto; + + /* Now check for each proto separately */ + if (proto == PROTO_FILE) { + if ((fd = open (def, O_RDONLY)) == -1) { + msg_warn ("add_map: cannot open file '%s': %s", def, strerror (errno)); + return FALSE; + } + fdata = memory_pool_alloc (map_pool, sizeof (struct file_map_data)); + fdata->filename = memory_pool_strdup (map_pool, def); + fstat (fd, &fdata->st); + new_map->map_data = fdata; + } + else if (proto == PROTO_HTTP) { + hdata = memory_pool_alloc (map_pool, sizeof (struct http_map_data)); + /* Try to search port */ + if ((p = strchr (def, ':')) != NULL) { + i = 0; + while (g_ascii_isdigit (*p) && i < sizeof (portbuf) - 1) { + portbuf[i ++] = *p ++; + } + if (*p != '/') { + msg_info ("add_map: bad http map definition: %s", def); + return FALSE; + } + portbuf[i] = '\0'; + hdata->port = atoi (portbuf); + } + else { + /* Default http port */ + hdata->port = 80; + /* Now separate host from path */ + if ((p = strchr (def, '/')) == NULL) { + msg_info ("add_map: bad http map definition: %s", def); + return FALSE; + } + } + hdata->host = memory_pool_alloc (map_pool, p - def + 1); + g_strlcpy (hdata->host, def, p - def + 1); + hdata->path = memory_pool_strdup (map_pool, p); + /* Now try to resolve */ + if (!inet_aton (hdata->host, &hdata->addr)) { + /* Resolve using dns */ + hent = gethostbyname (hdata->host); + if (hent == NULL) { + msg_info ("add_map: cannot resolve: %s", hdata->host); + return FALSE; + } + else { + memcpy (&hdata->addr, hent->h_addr, sizeof(struct in_addr)); + } + } + /* Now try to connect */ + if ((s = make_tcp_socket (&hdata->addr, hdata->port, FALSE)) == -1) { + msg_info ("add_map: cannot connect to http server %s: %d, %s", hdata->host, errno, strerror (errno)); + return FALSE; + } + close (s); + new_map->map_data = hdata; + } + /* Temp pool */ + new_map->pool = memory_pool_new (memory_pool_get_size ()); + + maps = g_list_prepend (maps, new_map); + + return TRUE; +} + +typedef void (*insert_func)(gpointer st, gconstpointer key, gpointer value); + +static gboolean +abstract_parse_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data, insert_func func) +{ + u_char *s, *p, *str; + + p = chunk; + + str = g_malloc (len + 1); + s = str; + + while (*p) { + switch (data->state) { + /* READ_SYMBOL */ + case 0: + if (*p == '#') { + if (s != str) { + *s = '\0'; + s = memory_pool_strdup (pool, str); + func (data->cur_data, s, hash_fill); + s = str; + } + data->state = 1; + } + else if (*p == '\r' || *p == '\n') { + if (s != str) { + *s = '\0'; + s = memory_pool_strdup (pool, str); + func (data->cur_data, s, hash_fill); + s = str; + } + while (*p == '\r' || *p == '\n') { + p ++; + } + } + else if (g_ascii_isspace (*p)) { + p ++; + } + else { + *s = *p; + s ++; + p ++; + } + break; + /* SKIP_COMMENT */ + case 1: + if (*p == '\r' || *p == '\n') { + while (*p == '\r' || *p == '\n') { + p ++; + } + s = str; + data->state = 0; + } + else { + p ++; + } + break; + } + } + + g_free (str); + + return TRUE; +} + +static void +radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value) +{ + radix_tree_t *tree = st; + + uint32_t mask = 0xFFFFFFFF; + uint32_t ip; + char *token, *ipnet; + struct in_addr ina; + int k; + + k = strlen ((char *)key) + 1; + ipnet = alloca (k); + g_strlcpy (ipnet, key, k); + token = strsep (&ipnet, "/"); + + if (ipnet != NULL) { + k = atoi (ipnet); + if (k > 32 || k < 0) { + msg_warn ("radix_tree_insert_helper: invalid netmask value: %d", k); + k = 32; + } + k = 32 - k; + mask = mask << k; + } + + if (inet_aton (token, &ina) == 0) { + msg_err ("radix_tree_insert_helper: invalid ip address: %s", token); + return; + } + + ip = ntohl ((uint32_t)ina.s_addr); + k = radix32tree_insert (tree, ip, mask, 1); + if (k == -1) { + msg_warn ("radix_tree_insert_helper: cannot insert ip to tree: %s, mask %X", inet_ntoa (ina), mask); + } + else if (k == 1) { + msg_warn ("add_ip_radix: ip %s, mask %X, value already exists", inet_ntoa (ina), mask); + } +} + +void +read_host_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data) +{ + if (data->cur_data == NULL) { + data->cur_data = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); + } + (void)abstract_parse_list (pool, chunk, len, data, (insert_func)g_hash_table_insert); +} + +void +fin_host_list (memory_pool_t *pool, struct map_cb_data *data) +{ + if (data->prev_data) { + g_hash_table_destroy (data->prev_data); + } +} + +void +read_radix_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data) +{ + if (data->cur_data == NULL) { + data->cur_data = radix_tree_create (); + } + (void)abstract_parse_list (pool, chunk, len, data, (insert_func)radix_tree_insert_helper); +} + +void +fin_radix_list (memory_pool_t *pool, struct map_cb_data *data) +{ + if (data->prev_data) { + radix_tree_free (data->prev_data); + } +} + +static void +file_callback (int fd, short what, void *ud) +{ + struct rspamd_map *map = ud; + struct file_map_data *data = map->map_data; + struct stat st; + + /* Plan event again with jitter */ + evtimer_del (&map->ev); + map->tv.tv_sec = MON_TIMEOUT + MON_TIMEOUT * g_random_double (); + map->tv.tv_usec = 0; + evtimer_add (&map->ev, &map->tv); + + if (stat (data->filename, &st) != -1 && st.st_mtime > data->st.st_mtime) { + memcpy (&data->st, &st, sizeof (struct stat)); + } + else { + return; + } + + msg_info ("rereading map file %s", data->filename); + read_map_file (map, data); +} + +/* Start watching event for all maps */ +void +start_map_watch (void) +{ + GList *cur = maps; + struct rspamd_map *map; + + /* First of all do synced read of data */ + while (cur) { + map = cur->data; + if (map->protocol == PROTO_FILE) { + evtimer_set (&map->ev, file_callback, map); + /* Read initial data */ + read_map_file (map, map->map_data); + /* Plan event with jitter */ + map->tv.tv_sec = MON_TIMEOUT + MON_TIMEOUT * g_random_double (); + map->tv.tv_usec = 0; + evtimer_add (&map->ev, &map->tv); + } + else { + /* XXX */ + } + cur = g_list_next (cur); + } +} diff --git a/src/map.h b/src/map.h new file mode 100644 index 000000000..dfd63a06d --- /dev/null +++ b/src/map.h @@ -0,0 +1,55 @@ +#ifndef RSPAMD_MAP_H +#define RSPAMD_MAP_H + +#include "config.h" +#include "mem_pool.h" +#include "radix.h" + +enum fetch_proto { + PROTO_FILE, + PROTO_HTTP, +}; + +struct map_cb_data { + int state; + void *prev_data; + void *cur_data; +}; + +struct file_map_data { + const char *filename; + struct stat st; +}; + +struct http_map_data { + struct in_addr addr; + uint16_t port; + char *path; + char *host; + time_t last_checked; +}; + +typedef void (*map_cb_t)(memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data); +typedef void (*map_fin_cb_t)(memory_pool_t *pool, struct map_cb_data *data); + +struct rspamd_map { + memory_pool_t *pool; + enum fetch_proto protocol; + map_cb_t read_callback; + map_fin_cb_t fin_callback; + void **user_data; + struct event ev; + struct timeval tv; + void *map_data; +}; + +gboolean add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data); +void start_map_watch (void); + +/* Common callbacks */ +void read_radix_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data); +void fin_radix_list (memory_pool_t *pool, struct map_cb_data *data); +void read_host_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data); +void fin_host_list (memory_pool_t *pool, struct map_cb_data *data); + +#endif diff --git a/src/plugins/emails.c b/src/plugins/emails.c index ef886ecf5..e08d3ff8f 100644 --- a/src/plugins/emails.c +++ b/src/plugins/emails.c @@ -34,6 +34,7 @@ #include "../expressions.h" #include "../util.h" #include "../view.h" +#include "../map.h" #define DEFAULT_SYMBOL "R_BAD_EMAIL" @@ -100,10 +101,8 @@ emails_module_config (struct config_file *cfg) email_module_ctx->symbol = DEFAULT_SYMBOL; } if ((value = get_module_opt (cfg, "emails", "blacklist")) != NULL) { - if (g_ascii_strncasecmp (value, "file://", sizeof ("file://") - 1) == 0) { - if (parse_host_list (email_module_ctx->email_pool, email_module_ctx->blacklist, value + sizeof ("file://") - 1)) { - email_module_ctx->blacklist_file = memory_pool_strdup (email_module_ctx->email_pool, value + sizeof ("file://") - 1); - } + if (add_map (value, read_host_list, fin_host_list, (void **)&email_module_ctx->blacklist)) { + email_module_ctx->blacklist_file = memory_pool_strdup (email_module_ctx->email_pool, value + sizeof ("file://") - 1); } } @@ -216,9 +215,9 @@ emails_symbol_callback (struct worker_task *task, void *unused) { GList *emails, *cur; - emails = extract_emails (task); if (check_view (task->cfg->views, email_module_ctx->symbol, task)) { + emails = extract_emails (task); if (email_module_ctx->blacklist && emails) { cur = g_list_first (emails); diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c index 15bdc149b..452f8749a 100644 --- a/src/plugins/surbl.c +++ b/src/plugins/surbl.c @@ -30,6 +30,7 @@ #include "../util.h" #include "../message.h" #include "../view.h" +#include "../map.h" #include #include "surbl.h" @@ -65,11 +66,11 @@ surbl_module_init (struct config_file *cfg, struct module_ctx **ctx) surbl_module_ctx->tld2_file = NULL; surbl_module_ctx->whitelist_file = NULL; - surbl_module_ctx->tld2 = g_hash_table_new (g_str_hash, g_str_equal); + surbl_module_ctx->tld2 = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); /* Register destructors */ memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func)g_hash_table_remove_all, surbl_module_ctx->tld2); - surbl_module_ctx->whitelist = g_hash_table_new (g_str_hash, g_str_equal); + surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); /* Register destructors */ memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func)g_hash_table_remove_all, surbl_module_ctx->whitelist); @@ -158,17 +159,13 @@ surbl_module_config (struct config_file *cfg) surbl_module_ctx->metric = DEFAULT_METRIC; } if ((value = get_module_opt (cfg, "surbl", "2tld")) != NULL) { - if (g_ascii_strncasecmp (value, "file://", sizeof ("file://") - 1) == 0) { - if (parse_host_list (surbl_module_ctx->surbl_pool, surbl_module_ctx->tld2, value + sizeof ("file://") - 1)) { - surbl_module_ctx->tld2_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1); - } + if (add_map (value, read_host_list, fin_host_list, (void **)&surbl_module_ctx->tld2)) { + surbl_module_ctx->tld2_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1); } } if ((value = get_module_opt (cfg, "surbl", "whitelist")) != NULL) { - if (g_ascii_strncasecmp (value, "file://", sizeof ("file://") - 1) == 0) { - if (parse_host_list (surbl_module_ctx->surbl_pool, surbl_module_ctx->whitelist, value + sizeof ("file://") - 1)) { - surbl_module_ctx->whitelist_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1); - } + if (add_map (value, read_host_list, fin_host_list, (void **)&surbl_module_ctx->whitelist)) { + surbl_module_ctx->whitelist_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1); } } @@ -766,14 +763,6 @@ surbl_test_url (struct worker_task *task, void *user_data) struct redirector_param param; struct suffix_item *suffix = user_data; - /* Try to check lists */ - if (surbl_module_ctx->tld2_file) { - maybe_parse_host_list (surbl_module_ctx->surbl_pool, surbl_module_ctx->tld2, surbl_module_ctx->tld2_file); - } - if (surbl_module_ctx->whitelist_file) { - maybe_parse_host_list (surbl_module_ctx->surbl_pool, surbl_module_ctx->whitelist, surbl_module_ctx->whitelist_file); - } - url_tree = g_tree_new ((GCompareFunc)g_ascii_strcasecmp); param.tree = url_tree; diff --git a/src/util.c b/src/util.c index 86be3c65e..8001fcb18 100644 --- a/src/util.c +++ b/src/util.c @@ -28,25 +28,15 @@ #include "cfg_file.h" #include "main.h" -/* Value in seconds after whitch we would try to do stat on list file */ -#define MON_TIMEOUT 10 sig_atomic_t do_reopen_log = 0; extern rspamd_hash_t *counters; -static char *hash_fill = "1"; - -struct list_file { - char *filename; - struct stat st; -}; struct logger_params { GLogFunc log_func; struct config_file *cfg; }; - -static GHashTable *listfiles = NULL; static struct logger_params log_params; int @@ -880,181 +870,18 @@ set_counter (const char *name, long int value) return cd->value; } -typedef void (*insert_func)(gpointer st, gconstpointer key, gpointer value); - -static gboolean -abstract_parse_list (memory_pool_t *pool, void *arg, insert_func func, const char *filename) -{ - int fd; - char buf[BUFSIZ], str[BUFSIZ], *s, *p; - ssize_t r; - enum { - READ_SYMBOL, - SKIP_COMMENT, - } state = READ_SYMBOL; - - struct list_file *new_file; - - if (listfiles == NULL) { - listfiles = g_hash_table_new (g_str_hash, g_str_equal); - } - - if ((fd = open (filename, O_RDONLY)) == -1) { - msg_warn ("parse_host_list: cannot open file '%s': %s", filename, strerror (errno)); - return FALSE; - } - - new_file = memory_pool_alloc (pool, sizeof (struct list_file)); - new_file->filename = memory_pool_strdup (pool, filename); - fstat (fd, &new_file->st); - g_hash_table_insert (listfiles, new_file->filename, new_file); - - s = str; - - while ((r = read (fd, buf, sizeof (buf) - 1)) > 0) { - buf[r] = '\0'; - p = buf; - while (*p) { - switch (state) { - case READ_SYMBOL: - if (*p == '#') { - if (s != str) { - *s = '\0'; - s = memory_pool_strdup (pool, str); - func (arg, s, hash_fill); - s = str; - } - state = SKIP_COMMENT; - } - else if (*p == '\r' || *p == '\n') { - if (s != str) { - *s = '\0'; - s = memory_pool_strdup (pool, str); - func (arg, s, hash_fill); - s = str; - } - while (*p == '\r' || *p == '\n') { - p ++; - } - } - else if (g_ascii_isspace (*p)) { - p ++; - } - else { - *s = *p; - s ++; - p ++; - } - break; - case SKIP_COMMENT: - if (*p == '\r' || *p == '\n') { - while (*p == '\r' || *p == '\n') { - p ++; - } - s = str; - state = READ_SYMBOL; - } - else { - p ++; - } - break; - } - } - } - - close (fd); - - return TRUE; -} - -static void -radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value) -{ - radix_tree_t *tree = st; - - uint32_t mask = 0xFFFFFFFF; - uint32_t ip; - char *token, *ipnet; - struct in_addr ina; - int k; - - k = strlen ((char *)key) + 1; - ipnet = alloca (k); - g_strlcpy (ipnet, key, k); - token = strsep (&ipnet, "/"); - - if (ipnet != NULL) { - k = atoi (ipnet); - if (k > 32 || k < 0) { - msg_warn ("radix_tree_insert_helper: invalid netmask value: %d", k); - k = 32; - } - k = 32 - k; - mask = mask << k; - } - - if (inet_aton (token, &ina) == 0) { - msg_err ("radix_tree_insert_helper: invalid ip address: %s", token); - return; - } - - ip = ntohl ((uint32_t)ina.s_addr); - k = radix32tree_insert (tree, ip, mask, 1); - if (k == -1) { - msg_warn ("radix_tree_insert_helper: cannot insert ip to tree: %s, mask %X", inet_ntoa (ina), mask); - } - else if (k == 1) { - msg_warn ("add_ip_radix: ip %s, mask %X, value already exists", inet_ntoa (ina), mask); - } -} - -gboolean -parse_host_list (memory_pool_t *pool, GHashTable *tbl, const char *filename) -{ - return abstract_parse_list (pool, (void *)tbl, (insert_func)g_hash_table_insert, filename); -} - -gboolean -parse_radix_list (memory_pool_t *pool, radix_tree_t *tree, const char *filename) -{ - return abstract_parse_list (pool, (void *)tree, (insert_func)radix_tree_insert_helper, filename); -} - -gboolean -maybe_parse_host_list (memory_pool_t *pool, GHashTable *tbl, const char *filename) -{ - struct list_file *lf; - struct stat cur_st; - time_t cur_time = time (NULL); - - if (listfiles == NULL || (lf = g_hash_table_lookup (listfiles, filename)) == NULL) { - /* Do not try to parse unknown files */ - return FALSE; - } - - if (cur_time - lf->st.st_mtime > MON_TIMEOUT) { - /* Try to stat */ - if (stat (lf->filename, &cur_st) != -1) { - if (cur_st.st_mtime > lf->st.st_mtime) { - g_hash_table_remove (listfiles, lf->filename); - g_hash_table_remove_all (tbl); - msg_info ("maybe_parse_host_list: file %s was modified and rereaded", filename); - return parse_host_list (pool, tbl, filename); - } - } - } - - return TRUE; -} - #ifndef g_tolower #define g_tolower(x) (((x) >= 'A' && (x) <= 'Z') ? (x) - 'A' + 'a' : (x)) #endif -gint +gboolean rspamd_strcase_equal (gconstpointer v, gconstpointer v2) { - return g_ascii_strcasecmp ((const char *) v, (const char *) v2); + if (g_ascii_strcasecmp ((const char *) v, (const char *) v2) == 0) { + return TRUE; + } + + return FALSE; } diff --git a/src/util.h b/src/util.h index 91de0a291..aa08bcc3a 100644 --- a/src/util.h +++ b/src/util.h @@ -64,12 +64,8 @@ const char* calculate_check_time (struct timespec *begin, int resolution); double set_counter (const char *name, long int value); -gboolean parse_host_list (memory_pool_t *pool, GHashTable *tbl, const char *filename); -gboolean maybe_parse_host_list (memory_pool_t *pool, GHashTable *tbl, const char *filename); -gboolean parse_radix_list (memory_pool_t *pool, radix_tree_t *tree, const char *filename); - guint rspamd_strcase_hash (gconstpointer key); -gint rspamd_strcase_equal (gconstpointer v, gconstpointer v2); +gboolean rspamd_strcase_equal (gconstpointer v, gconstpointer v2); #endif diff --git a/src/view.c b/src/view.c index 0a03d4304..ec10eb120 100644 --- a/src/view.c +++ b/src/view.c @@ -28,6 +28,7 @@ #include "view.h" #include "expressions.h" #include "cfg_file.h" +#include "map.h" struct rspamd_view* init_view (memory_pool_t *pool) @@ -51,10 +52,8 @@ add_view_from (struct rspamd_view *view, char *line) { struct rspamd_regexp *re = NULL; - if (g_ascii_strncasecmp (line, "file://", sizeof ("file://") - 1) == 0) { - if (parse_host_list (view->pool, view->from_hash, line + sizeof ("file://") - 1)) { - return TRUE; - } + if (add_map (line, read_host_list, fin_host_list, (void **)&view->from_hash)) { + return TRUE; } else if ((re = parse_regexp (view->pool, line, TRUE)) != NULL) { view->from_re_list = g_list_prepend (view->from_re_list, re); @@ -70,10 +69,8 @@ add_view_symbols (struct rspamd_view *view, char *line) struct rspamd_regexp *re = NULL; GList *symbols; - if (g_ascii_strncasecmp (line, "file://", sizeof ("file://") - 1) == 0) { - if (parse_host_list (view->pool, view->symbols_hash, line + sizeof ("file://") - 1)) { - return TRUE; - } + if (add_map (line, read_host_list, fin_host_list, (void **)&view->symbols_hash)) { + return TRUE; } else if ((re = parse_regexp (view->pool, line, TRUE)) != NULL) { view->symbols_re_list = g_list_prepend (view->symbols_re_list, re); @@ -96,14 +93,11 @@ add_view_symbols (struct rspamd_view *view, char *line) gboolean add_view_ip (struct rspamd_view *view, char *line) { - if (g_ascii_strncasecmp (line, "file://", sizeof ("file://") - 1) == 0) { - if (parse_radix_list (view->pool, view->ip_tree, line + sizeof ("file://") - 1)) { - return TRUE; - } + if (add_map (line, read_radix_list, fin_radix_list, (void **)&view->symbols_hash)) { + return TRUE; } return FALSE; - } diff --git a/src/worker.c b/src/worker.c index 01732135c..726f7fe00 100644 --- a/src/worker.c +++ b/src/worker.c @@ -35,6 +35,7 @@ #include "url.h" #include "modules.h" #include "message.h" +#include "map.h" #include @@ -367,6 +368,9 @@ start_worker (struct rspamd_worker *worker) event_set(&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_socket, (void *)worker); event_add(&worker->bind_ev, NULL); + /* Maps events */ + start_map_watch (); + /* Send SIGUSR2 to parent */ kill (getppid (), SIGUSR2); -- 2.39.5