diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-04-21 16:25:51 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-04-21 16:25:51 +0100 |
commit | 61555065f3d1c8badcc9573691232f1b6e42988c (patch) | |
tree | 563d5b7cb8c468530f7e79c4da0a75267b1184e1 /src/cfg_utils.c | |
parent | ad5bf825b7f33bc10311673991f0cc888e69c0b1 (diff) | |
download | rspamd-61555065f3d1c8badcc9573691232f1b6e42988c.tar.gz rspamd-61555065f3d1c8badcc9573691232f1b6e42988c.zip |
Rework project structure, remove trash files.
Diffstat (limited to 'src/cfg_utils.c')
-rw-r--r-- | src/cfg_utils.c | 969 |
1 files changed, 0 insertions, 969 deletions
diff --git a/src/cfg_utils.c b/src/cfg_utils.c deleted file mode 100644 index 2ca846ebd..000000000 --- a/src/cfg_utils.c +++ /dev/null @@ -1,969 +0,0 @@ -/* - * Copyright (c) 2009-2012, Vsevolod Stakhov - * 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 AUTHOR ''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 AUTHOR 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. - */ - - -#include "config.h" - -#include "cfg_file.h" -#include "main.h" -#include "filter.h" -#include "settings.h" -#include "classifiers/classifiers.h" -#include "lua/lua_common.h" -#include "kvstorage_config.h" -#include "map.h" -#include "dynamic_cfg.h" - -#define DEFAULT_SCORE 10.0 - -#define DEFAULT_RLIMIT_NOFILE 2048 -#define DEFAULT_RLIMIT_MAXCORE 0 -#define DEFAULT_MAP_TIMEOUT 10 - -struct rspamd_ucl_map_cbdata { - struct config_file *cfg; - GString *buf; -}; -static gchar* rspamd_ucl_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data); -static void rspamd_ucl_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data); - -static gboolean -parse_host_port_priority_strv (rspamd_mempool_t *pool, gchar **tokens, - gchar **addr, guint16 *port, guint *priority, guint default_port) -{ - gchar *err_str, portbuf[8]; - const gchar *cur_tok, *cur_port; - struct addrinfo hints, *res; - guint port_parsed, priority_parsed, saved_errno = errno; - gint r; - union { - struct sockaddr_in v4; - struct sockaddr_in6 v6; - } addr_holder; - - /* Now try to parse host and write address to ina */ - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; /* Type of the socket */ - hints.ai_flags = AI_NUMERICSERV; - - cur_tok = tokens[0]; - - if (strcmp (cur_tok, "*v6") == 0) { - hints.ai_family = AF_INET6; - hints.ai_flags |= AI_PASSIVE; - cur_tok = NULL; - } - else if (strcmp (cur_tok, "*v4") == 0) { - hints.ai_family = AF_INET; - hints.ai_flags |= AI_PASSIVE; - cur_tok = NULL; - } - else { - hints.ai_family = AF_UNSPEC; - } - - if (tokens[1] != NULL) { - /* Port part */ - rspamd_strlcpy (portbuf, tokens[1], sizeof (portbuf)); - cur_port = portbuf; - if (port != NULL) { - errno = 0; - port_parsed = strtoul (tokens[1], &err_str, 10); - if (*err_str != '\0' || errno != 0) { - msg_warn ("cannot parse port: %s, at symbol %c, error: %s", tokens[1], *err_str, strerror (errno)); - hints.ai_flags ^= AI_NUMERICSERV; - } - else if (port_parsed > G_MAXUINT16) { - errno = ERANGE; - msg_warn ("cannot parse port: %s, error: %s", tokens[1], *err_str, strerror (errno)); - hints.ai_flags ^= AI_NUMERICSERV; - } - else { - *port = port_parsed; - } - } - if (priority != NULL) { - if (port != NULL) { - cur_tok = tokens[2]; - } - else { - cur_tok = tokens[1]; - } - if (cur_tok != NULL) { - /* Priority part */ - errno = 0; - priority_parsed = strtoul (cur_tok, &err_str, 10); - if (*err_str != '\0' || errno != 0) { - msg_warn ("cannot parse priority: %s, at symbol %c, error: %s", tokens[1], *err_str, strerror (errno)); - } - else { - *priority = priority_parsed; - } - } - } - } - else if (default_port != 0) { - rspamd_snprintf (portbuf, sizeof (portbuf), "%ud", default_port); - cur_port = portbuf; - } - else { - cur_port = NULL; - } - - if ((r = getaddrinfo (cur_tok, cur_port, &hints, &res)) == 0) { - memcpy (&addr_holder, res->ai_addr, MIN (sizeof (addr_holder), res->ai_addrlen)); - if (res->ai_family == AF_INET) { - if (pool != NULL) { - *addr = rspamd_mempool_alloc (pool, INET_ADDRSTRLEN + 1); - } - inet_ntop (res->ai_family, &addr_holder.v4.sin_addr, *addr, INET_ADDRSTRLEN + 1); - } - else { - if (pool != NULL) { - *addr = rspamd_mempool_alloc (pool, INET6_ADDRSTRLEN + 1); - } - inet_ntop (res->ai_family, &addr_holder.v6.sin6_addr, *addr, INET6_ADDRSTRLEN + 1); - } - freeaddrinfo (res); - } - else { - msg_err ("address resolution for %s failed: %s", tokens[0], gai_strerror (r)); - goto err; - } - - /* Restore errno */ - errno = saved_errno; - return TRUE; - -err: - errno = saved_errno; - return FALSE; -} - -gboolean -parse_host_port_priority (rspamd_mempool_t *pool, const gchar *str, gchar **addr, guint16 *port, guint *priority) -{ - gchar **tokens; - gboolean ret; - - tokens = g_strsplit_set (str, ":", 0); - if (!tokens || !tokens[0]) { - return FALSE; - } - - ret = parse_host_port_priority_strv (pool, tokens, addr, port, priority, 0); - - g_strfreev (tokens); - - return ret; -} - -gboolean -parse_host_port (rspamd_mempool_t *pool, const gchar *str, gchar **addr, guint16 *port) -{ - return parse_host_port_priority (pool, str, addr, port, NULL); -} - -gboolean -parse_host_priority (rspamd_mempool_t *pool, const gchar *str, gchar **addr, guint *priority) -{ - return parse_host_port_priority (pool, str, addr, NULL, priority); -} - -gboolean -parse_bind_line (struct config_file *cfg, struct worker_conf *cf, const gchar *str) -{ - struct rspamd_worker_bind_conf *cnf; - gchar **tokens, *tmp, *err; - gboolean ret = TRUE; - - if (str == NULL) { - return FALSE; - } - - tokens = g_strsplit_set (str, ":", 0); - if (!tokens || !tokens[0]) { - return FALSE; - } - - cnf = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_worker_bind_conf)); - cnf->bind_port = DEFAULT_BIND_PORT; - cnf->bind_host = rspamd_mempool_strdup (cfg->cfg_pool, str); - cnf->ai = AF_UNSPEC; - - if (*tokens[0] == '/' || *tokens[0] == '.') { - cnf->ai = AF_UNIX; - LL_PREPEND (cf->bind_conf, cnf); - return TRUE; - } - else if (strcmp (tokens[0], "*") == 0) { - /* We need to add two listen entries: one for ipv4 and one for ipv6 */ - tmp = tokens[0]; - tokens[0] = "*v4"; - cnf->ai = AF_INET; - if ((ret = parse_host_port_priority_strv (cfg->cfg_pool, tokens, - &cnf->bind_host, &cnf->bind_port, NULL, DEFAULT_BIND_PORT))) { - LL_PREPEND (cf->bind_conf, cnf); - } - cnf = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_worker_bind_conf)); - cnf->bind_port = DEFAULT_BIND_PORT; - cnf->bind_host = rspamd_mempool_strdup (cfg->cfg_pool, str); - cnf->ai = AF_INET6; - tokens[0] = "*v6"; - if ((ret &= parse_host_port_priority_strv (cfg->cfg_pool, tokens, - &cnf->bind_host, &cnf->bind_port, NULL, DEFAULT_BIND_PORT))) { - LL_PREPEND (cf->bind_conf, cnf); - } - tokens[0] = tmp; - } - else if (strcmp (tokens[0], "systemd") == 0) { - /* The actual socket will be passed by systemd environment */ - cnf->bind_host = rspamd_mempool_strdup (cfg->cfg_pool, str); - cnf->ai = strtoul (tokens[1], &err, 10); - cnf->is_systemd = TRUE; - if (err == NULL || *err == '\0') { - LL_PREPEND (cf->bind_conf, cnf); - } - } - else { - if ((ret = parse_host_port_priority_strv (cfg->cfg_pool, tokens, - &cnf->bind_host, &cnf->bind_port, NULL, DEFAULT_BIND_PORT))) { - LL_PREPEND (cf->bind_conf, cnf); - } - } - - g_strfreev (tokens); - - return ret; -} - -void -init_defaults (struct config_file *cfg) -{ - - cfg->memcached_error_time = DEFAULT_UPSTREAM_ERROR_TIME; - cfg->memcached_dead_time = DEFAULT_UPSTREAM_DEAD_TIME; - cfg->memcached_maxerrors = DEFAULT_UPSTREAM_MAXERRORS; - cfg->memcached_protocol = TCP_TEXT; - - cfg->dns_timeout = 1000; - cfg->dns_retransmits = 5; - /* After 20 errors do throttling for 10 seconds */ - cfg->dns_throttling_errors = 20; - cfg->dns_throttling_time = 10000; - /* 16 sockets per DNS server */ - cfg->dns_io_per_server = 16; - - cfg->statfile_sync_interval = 60000; - cfg->statfile_sync_timeout = 20000; - - /* 20 Kb */ - cfg->max_diff = 20480; - - cfg->metrics = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - cfg->c_modules = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - cfg->composite_symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - cfg->classifiers_symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - cfg->cfg_params = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - cfg->metrics_symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - - cfg->map_timeout = DEFAULT_MAP_TIMEOUT; - - cfg->log_level = G_LOG_LEVEL_WARNING; - cfg->log_extended = TRUE; - - init_settings (cfg); - -} - -void -free_config (struct config_file *cfg) -{ - GList *cur; - struct symbols_group *gr; - - remove_all_maps (cfg); - ucl_obj_unref (cfg->rcl_obj); - g_hash_table_remove_all (cfg->metrics); - g_hash_table_unref (cfg->metrics); - g_hash_table_remove_all (cfg->c_modules); - g_hash_table_unref (cfg->c_modules); - g_hash_table_remove_all (cfg->composite_symbols); - g_hash_table_unref (cfg->composite_symbols); - g_hash_table_remove_all (cfg->cfg_params); - g_hash_table_unref (cfg->cfg_params); - g_hash_table_destroy (cfg->metrics_symbols); - g_hash_table_destroy (cfg->classifiers_symbols); - /* Free symbols groups */ - cur = cfg->symbols_groups; - while (cur) { - gr = cur->data; - if (gr->symbols) { - g_list_free (gr->symbols); - } - cur = g_list_next (cur); - } - if (cfg->symbols_groups) { - g_list_free (cfg->symbols_groups); - } - - if (cfg->checksum) { - g_free (cfg->checksum); - } - g_list_free (cfg->classifiers); - g_list_free (cfg->metrics_list); - rspamd_mempool_delete (cfg->cfg_pool); -} - -const ucl_object_t * -get_module_opt (struct config_file *cfg, const gchar *module_name, const gchar *opt_name) -{ - const ucl_object_t *res = NULL, *sec; - - sec = ucl_obj_get_key (cfg->rcl_obj, module_name); - if (sec != NULL) { - res = ucl_obj_get_key (sec, opt_name); - } - - return res; -} - -guint64 -parse_limit (const gchar *limit, guint len) -{ - guint64 result = 0; - const gchar *err_str; - - if (!limit || *limit == '\0' || len == 0) { - return 0; - } - - errno = 0; - result = strtoull (limit, (gchar **)&err_str, 10); - - if (*err_str != '\0') { - /* Megabytes */ - if (*err_str == 'm' || *err_str == 'M') { - result *= 1048576L; - } - /* Kilobytes */ - else if (*err_str == 'k' || *err_str == 'K') { - result *= 1024; - } - /* Gigabytes */ - else if (*err_str == 'g' || *err_str == 'G') { - result *= 1073741824L; - } - else if (len > 0 && err_str - limit != (gint)len) { - msg_warn ("invalid limit value '%s' at position '%s'", limit, err_str); - result = 0; - } - } - - return result; -} - -gchar -parse_flag (const gchar *str) -{ - guint len; - gchar c; - - if (!str || !*str) { - return -1; - } - - len = strlen (str); - - switch (len) { - case 1: - c = g_ascii_tolower (*str); - if (c == 'y' || c == '1') { - return 1; - } - else if (c == 'n' || c == '0') { - return 0; - } - break; - case 2: - if (g_ascii_strncasecmp (str, "no", len) == 0) { - return 0; - } - else if (g_ascii_strncasecmp (str, "on", len) == 0) { - return 1; - } - break; - case 3: - if (g_ascii_strncasecmp (str, "yes", len) == 0) { - return 1; - } - else if (g_ascii_strncasecmp (str, "off", len) == 0) { - return 0; - } - break; - case 4: - if (g_ascii_strncasecmp (str, "true", len) == 0) { - return 1; - } - break; - case 5: - if (g_ascii_strncasecmp (str, "false", len) == 0) { - return 0; - } - break; - } - - return -1; -} - -gboolean -get_config_checksum (struct config_file *cfg) -{ - gint fd; - void *map; - struct stat st; - - /* Compute checksum for config file that should be used by xml dumper */ - if ((fd = open (cfg->cfg_name, O_RDONLY)) == -1) { - msg_err ("config file %s is no longer available, cannot calculate checksum"); - return FALSE; - } - if (stat (cfg->cfg_name, &st) == -1) { - msg_err ("cannot stat %s: %s", cfg->cfg_name, strerror (errno)); - return FALSE; - } - - /* Now mmap this file to simplify reading process */ - if ((map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { - msg_err ("cannot mmap %s: %s", cfg->cfg_name, strerror (errno)); - close (fd); - return FALSE; - } - close (fd); - - /* Get checksum for a file */ - cfg->checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, map, st.st_size); - munmap (map, st.st_size); - - return TRUE; -} -/* - * Perform post load actions - */ -void -post_load_config (struct config_file *cfg) -{ -#ifdef HAVE_CLOCK_GETTIME - struct timespec ts; -#endif - struct metric *def_metric; - -#ifdef HAVE_CLOCK_GETTIME -#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID - clock_getres (CLOCK_PROCESS_CPUTIME_ID, &ts); -# elif defined(HAVE_CLOCK_VIRTUAL) - clock_getres (CLOCK_VIRTUAL, &ts); -# else - clock_getres (CLOCK_REALTIME, &ts); -# endif - - cfg->clock_res = (gint)log10 (1000000 / ts.tv_nsec); - if (cfg->clock_res < 0) { - cfg->clock_res = 0; - } - if (cfg->clock_res > 3) { - cfg->clock_res = 3; - } -#else - /* For gettimeofday */ - cfg->clock_res = 1; -#endif - - if ((def_metric = g_hash_table_lookup (cfg->metrics, DEFAULT_METRIC)) == NULL) { - def_metric = check_metric_conf (cfg, NULL); - def_metric->name = DEFAULT_METRIC; - def_metric->actions[METRIC_ACTION_REJECT].score = DEFAULT_SCORE; - cfg->metrics_list = g_list_prepend (cfg->metrics_list, def_metric); - g_hash_table_insert (cfg->metrics, DEFAULT_METRIC, def_metric); - } - - cfg->default_metric = def_metric; - - /* Lua options */ - (void)lua_post_load_config (cfg); - init_dynamic_config (cfg); -} - -#if 0 -void -parse_err (const gchar *fmt, ...) -{ - va_list aq; - gchar logbuf[BUFSIZ], readbuf[32]; - gint r; - - va_start (aq, fmt); - rspamd_strlcpy (readbuf, yytext, sizeof (readbuf)); - - r = snprintf (logbuf, sizeof (logbuf), "config file parse error! line: %d, text: %s, reason: ", yylineno, readbuf); - r += vsnprintf (logbuf + r, sizeof (logbuf) - r, fmt, aq); - - va_end (aq); - g_critical ("%s", logbuf); -} - -void -parse_warn (const gchar *fmt, ...) -{ - va_list aq; - gchar logbuf[BUFSIZ], readbuf[32]; - gint r; - - va_start (aq, fmt); - rspamd_strlcpy (readbuf, yytext, sizeof (readbuf)); - - r = snprintf (logbuf, sizeof (logbuf), "config file parse warning! line: %d, text: %s, reason: ", yylineno, readbuf); - r += vsnprintf (logbuf + r, sizeof (logbuf) - r, fmt, aq); - - va_end (aq); - g_warning ("%s", logbuf); -} -#endif - -void -unescape_quotes (gchar *line) -{ - gchar *c = line, *t; - - while (*c) { - if (*c == '\\' && *(c + 1) == '"') { - t = c; - while (*t) { - *t = *(t + 1); - t++; - } - } - c++; - } -} - -GList * -parse_comma_list (rspamd_mempool_t * pool, const gchar *line) -{ - GList *res = NULL; - const gchar *c, *p; - gchar *str; - - c = line; - p = c; - - while (*p) { - if (*p == ',' && *c != *p) { - str = rspamd_mempool_alloc (pool, p - c + 1); - rspamd_strlcpy (str, c, p - c + 1); - res = g_list_prepend (res, str); - /* Skip spaces */ - while (g_ascii_isspace (*(++p))); - c = p; - continue; - } - p++; - } - if (res != NULL) { - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_list_free, res); - } - - return res; -} - -struct classifier_config * -check_classifier_conf (struct config_file *cfg, struct classifier_config *c) -{ - if (c == NULL) { - c = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct classifier_config)); - } - if (c->opts == NULL) { - c->opts = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, c->opts); - } - if (c->labels == NULL) { - c->labels = g_hash_table_new_full (rspamd_str_hash, rspamd_str_equal, NULL, (GDestroyNotify)g_list_free); - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, c->labels); - } - - return c; -} - -struct statfile* -check_statfile_conf (struct config_file *cfg, struct statfile *c) -{ - if (c == NULL) { - c = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct statfile)); - } - - return c; -} - -struct metric * -check_metric_conf (struct config_file *cfg, struct metric *c) -{ - int i; - if (c == NULL) { - c = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct metric)); - c->grow_factor = 1.0; - c->symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - c->descriptions = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { - c->actions[i].score = -1.0; - } - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, c->symbols); - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, c->descriptions); - } - - return c; -} - -struct worker_conf * -check_worker_conf (struct config_file *cfg, struct worker_conf *c) -{ - if (c == NULL) { - c = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct worker_conf)); - c->params = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - c->active_workers = g_queue_new (); - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)g_hash_table_destroy, c->params); - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)g_queue_free, c->active_workers); -#ifdef HAVE_SC_NPROCESSORS_ONLN - c->count = sysconf (_SC_NPROCESSORS_ONLN); -#else - c->count = DEFAULT_WORKERS_NUM; -#endif - c->rlimit_nofile = DEFAULT_RLIMIT_NOFILE; - c->rlimit_maxcore = DEFAULT_RLIMIT_MAXCORE; - } - - return c; -} - - -static bool -rspamd_include_map_handler (const guchar *data, gsize len, void* ud) -{ - struct config_file *cfg = (struct config_file *)ud; - struct rspamd_ucl_map_cbdata *cbdata, **pcbdata; - gchar *map_line; - - map_line = rspamd_mempool_alloc (cfg->cfg_pool, len + 1); - rspamd_strlcpy (map_line, data, len + 1); - - cbdata = g_malloc (sizeof (struct rspamd_ucl_map_cbdata)); - pcbdata = g_malloc (sizeof (struct rspamd_ucl_map_cbdata *)); - cbdata->buf = NULL; - cbdata->cfg = cfg; - *pcbdata = cbdata; - - return add_map (cfg, map_line, "ucl include", rspamd_ucl_read_cb, rspamd_ucl_fin_cb, (void **)pcbdata); -} - -/* - * Variables: - * $CONFDIR - configuration directory - * $RUNDIR - local states directory - * $DBDIR - databases dir - * $LOGDIR - logs dir - * $PLUGINSDIR - pluggins dir - * $PREFIX - installation prefix - * $VERSION - rspamd version - */ - -#define RSPAMD_CONFDIR_MACRO "CONFDIR" -#define RSPAMD_RUNDIR_MACRO "RUNDIR" -#define RSPAMD_DBDIR_MACRO "DBDIR" -#define RSPAMD_LOGDIR_MACRO "LOGDIR" -#define RSPAMD_PLUGINSDIR_MACRO "PLUGINSDIR" -#define RSPAMD_PREFIX_MACRO "PREFIX" -#define RSPAMD_VERSION_MACRO "VERSION" - -static void -rspamd_ucl_add_conf_variables (struct ucl_parser *parser) -{ - ucl_parser_register_variable (parser, RSPAMD_CONFDIR_MACRO, RSPAMD_CONFDIR); - ucl_parser_register_variable (parser, RSPAMD_RUNDIR_MACRO, RSPAMD_RUNDIR); - ucl_parser_register_variable (parser, RSPAMD_DBDIR_MACRO, RSPAMD_DBDIR); - ucl_parser_register_variable (parser, RSPAMD_LOGDIR_MACRO, RSPAMD_LOGDIR); - ucl_parser_register_variable (parser, RSPAMD_PLUGINSDIR_MACRO, RSPAMD_PLUGINSDIR); - ucl_parser_register_variable (parser, RSPAMD_PREFIX_MACRO, RSPAMD_PREFIX); - ucl_parser_register_variable (parser, RSPAMD_VERSION_MACRO, RVERSION); -} - -static void -rspamd_ucl_add_conf_macros (struct ucl_parser *parser, struct config_file *cfg) -{ - ucl_parser_register_macro (parser, "include_map", rspamd_include_map_handler, cfg); -} - -gboolean -read_rspamd_config (struct config_file *cfg, const gchar *filename, - const gchar *convert_to, rspamd_rcl_section_fin_t logger_fin, - gpointer logger_ud) -{ - struct stat st; - gint fd; - gchar *data; - GError *err = NULL; - struct rspamd_rcl_section *top, *logger; - gboolean res; - struct ucl_parser *parser; - - if (stat (filename, &st) == -1) { - msg_err ("cannot stat %s: %s", filename, strerror (errno)); - return FALSE; - } - if ((fd = open (filename, O_RDONLY)) == -1) { - msg_err ("cannot open %s: %s", filename, strerror (errno)); - return FALSE; - - } - /* Now mmap this file to simplify reading process */ - if ((data = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { - msg_err ("cannot mmap %s: %s", filename, strerror (errno)); - close (fd); - return FALSE; - } - close (fd); - - parser = ucl_parser_new (0); - rspamd_ucl_add_conf_variables (parser); - rspamd_ucl_add_conf_macros (parser, cfg); - if (!ucl_parser_add_chunk (parser, data, st.st_size)) { - msg_err ("ucl parser error: %s", ucl_parser_get_error (parser)); - ucl_parser_free (parser); - munmap (data, st.st_size); - return FALSE; - } - munmap (data, st.st_size); - cfg->rcl_obj = ucl_parser_get_object (parser); - ucl_parser_free (parser); - res = TRUE; - - if (!res) { - return FALSE; - } - - top = rspamd_rcl_config_init (); - err = NULL; - - HASH_FIND_STR(top, "logging", logger); - if (logger != NULL) { - logger->fin = logger_fin; - logger->fin_ud = logger_ud; - } - - if (!rspamd_read_rcl_config (top, cfg, cfg->rcl_obj, &err)) { - msg_err ("rcl parse error: %s", err->message); - return FALSE; - } - - return TRUE; -} - -static void -symbols_classifiers_callback (gpointer key, gpointer value, gpointer ud) -{ - struct config_file *cfg = ud; - - register_virtual_symbol (&cfg->cache, key, 1.0); -} - -void -insert_classifier_symbols (struct config_file *cfg) -{ - g_hash_table_foreach (cfg->classifiers_symbols, symbols_classifiers_callback, cfg); -} - -struct classifier_config* -find_classifier_conf (struct config_file *cfg, const gchar *name) -{ - GList *cur; - struct classifier_config *cf; - - if (name == NULL) { - return NULL; - } - - cur = cfg->classifiers; - while (cur) { - cf = cur->data; - - if (g_ascii_strcasecmp (cf->classifier->name, name) == 0) { - return cf; - } - - cur = g_list_next (cur); - } - - return NULL; -} - -gboolean -check_classifier_statfiles (struct classifier_config *cf) -{ - struct statfile *st; - gboolean has_other = FALSE, res = FALSE, cur_class; - GList *cur; - - /* First check classes directly */ - cur = cf->statfiles; - while (cur) { - st = cur->data; - if (!has_other) { - cur_class = st->is_spam; - has_other = TRUE; - } - else { - if (cur_class != st->is_spam) { - return TRUE; - } - } - - cur = g_list_next (cur); - } - - if (!has_other) { - /* We have only one statfile */ - return FALSE; - } - /* We have not detected any statfile that has different class, so turn on euristic based on symbol's name */ - has_other = FALSE; - cur = cf->statfiles; - while (cur) { - st = cur->data; - if (rspamd_strncasestr (st->symbol, "spam", -1) != NULL) { - st->is_spam = TRUE; - } - else if (rspamd_strncasestr (st->symbol, "ham", -1) != NULL) { - st->is_spam = FALSE; - } - - if (!has_other) { - cur_class = st->is_spam; - has_other = TRUE; - } - else { - if (cur_class != st->is_spam) { - res = TRUE; - } - } - - cur = g_list_next (cur); - } - - return res; -} - -static gchar* -rspamd_ucl_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) -{ - struct rspamd_ucl_map_cbdata *cbdata = data->cur_data, *prev; - - if (cbdata == NULL) { - cbdata = g_malloc (sizeof (struct rspamd_ucl_map_cbdata)); - prev = data->prev_data; - cbdata->buf = g_string_sized_new (BUFSIZ); - cbdata->cfg = prev->cfg; - data->cur_data = cbdata; - } - g_string_append_len (cbdata->buf, chunk, len); - - /* Say not to copy any part of this buffer */ - return NULL; -} - -static void -rspamd_ucl_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) -{ - struct rspamd_ucl_map_cbdata *cbdata = data->cur_data, *prev = data->prev_data; - ucl_object_t *obj; - struct ucl_parser *parser; - guint32 checksum; - - if (prev != NULL) { - if (prev->buf != NULL) { - g_string_free (prev->buf, TRUE); - } - g_free (prev); - } - - if (cbdata == NULL) { - msg_err ("map fin error: new data is NULL"); - return; - } - - checksum = murmur32_hash (cbdata->buf->str, cbdata->buf->len); - if (data->map->checksum != checksum) { - /* New data available */ - parser = ucl_parser_new (0); - if (!ucl_parser_add_chunk (parser, cbdata->buf->str, cbdata->buf->len)) { - msg_err ("cannot parse map %s: %s", data->map->uri, ucl_parser_get_error (parser)); - ucl_parser_free (parser); - } - else { - obj = ucl_parser_get_object (parser); - ucl_parser_free (parser); - /* XXX: add replace objects code */ - ucl_object_unref (obj); - data->map->checksum = checksum; - } - } - else { - msg_info ("do not reload map %s, checksum is the same: %d", data->map->uri, checksum); - } -} - -gboolean -rspamd_parse_ip_list (const gchar *ip_list, radix_tree_t **tree) -{ - gchar **strvec, **cur; - struct in_addr ina; - guint32 mask; - - strvec = g_strsplit_set (ip_list, ",", 0); - cur = strvec; - - while (*cur != NULL) { - /* XXX: handle only ipv4 addresses */ - if (parse_ipmask_v4 (*cur, &ina, &mask)) { - if (*tree == NULL) { - *tree = radix_tree_create (); - } - radix32tree_add (*tree, htonl (ina.s_addr), mask, 1); - } - cur ++; - } - - return (*tree != NULL); -} - -/* - * vi:ts=4 - */ |