]> source.dussan.org Git - rspamd.git/commitdiff
* Introduce new common system of map files, that can be used for different types...
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Mon, 20 Jul 2009 15:33:48 +0000 (19:33 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Mon, 20 Jul 2009 15:33:48 +0000 (19:33 +0400)
  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
src/map.c [new file with mode: 0644]
src/map.h [new file with mode: 0644]
src/plugins/emails.c
src/plugins/surbl.c
src/util.c
src/util.h
src/view.c
src/worker.c

index 4c4dcbb728f534539b7b01750571bcca637e278f..2a76296d8973ca6062bda0339b3931d762cfd764 100644 (file)
@@ -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 (file)
index 0000000..a1ba525
--- /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 (file)
index 0000000..dfd63a0
--- /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
index ef886ecf5282b9c8d4029fb0acf777cf15ad0dae..e08d3ff8fe64f4380e11ca5aa7c9ec82c801fbc5 100644 (file)
@@ -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);
 
index 15bdc149bde6c323cb3fa6196467f135efd5700d..452f8749a32797a127a05017464513c60244e8ef 100644 (file)
@@ -30,6 +30,7 @@
 #include "../util.h"
 #include "../message.h"
 #include "../view.h"
+#include "../map.h"
 #include <evdns.h>
 
 #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;
index 86be3c65e27d7ad1e7c8ed35b599358205aa310a..8001fcb1891f788db29e7c7e299292d268542d40 100644 (file)
 #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;
 }
 
 
index 91de0a291ca8faadb2add43c40f81fcbcf873076..aa08bcc3ac1dc74f9f0d64639e45bd0f52d9179b 100644 (file)
@@ -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
index 0a03d4304e2fee16171a23852051ffb30799ccf4..ec10eb120aba8fc1b0cb00f91b8df2c3a96dd96d 100644 (file)
@@ -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;
-
 }
 
 
index 01732135c89c3ebd5f13dc03a7f950d8f344aa9a..726f7fe001f3fa8d300d4154bc84589654eb7651 100644 (file)
@@ -35,6 +35,7 @@
 #include "url.h"
 #include "modules.h"
 #include "message.h"
+#include "map.h"
 
 #include <evdns.h>
 
@@ -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);