summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2010-12-03 21:57:38 +0300
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2010-12-03 21:57:38 +0300
commit618e3f4887b61c69915f1c641ea47044695d6e7f (patch)
treec36d6f2bcbc17c8590ad6b2088a6f909bbb7af98
parent426963bff9e01d7d2f48d0e9eb232ccc11b33808 (diff)
downloadrspamd-618e3f4887b61c69915f1c641ea47044695d6e7f.tar.gz
rspamd-618e3f4887b61c69915f1c641ea47044695d6e7f.zip
* Start new rspamd 0.3.4
* Add ability to manage per-module, per-worker and per-classifier options in XML parser
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/cfg_xml.c252
-rw-r--r--src/cfg_xml.h27
-rw-r--r--src/controller.c36
-rw-r--r--src/fuzzy_storage.c133
-rw-r--r--src/fuzzy_storage.h1
-rw-r--r--src/logger.c25
-rw-r--r--src/logger.h12
-rw-r--r--src/main.c44
-rw-r--r--src/main.h10
-rw-r--r--src/smtp.c95
-rw-r--r--src/smtp.h9
-rw-r--r--src/util.c54
-rw-r--r--src/util.h30
-rw-r--r--src/worker.c121
15 files changed, 561 insertions, 291 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cfaa95ed3..7945ae059 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ PROJECT(rspamd C)
SET(RSPAMD_VERSION_MAJOR 0)
SET(RSPAMD_VERSION_MINOR 3)
-SET(RSPAMD_VERSION_PATCH 3)
+SET(RSPAMD_VERSION_PATCH 4)
SET(RSPAMD_VERSION "${RSPAMD_VERSION_MAJOR}.${RSPAMD_VERSION_MINOR}.${RSPAMD_VERSION_PATCH}")
@@ -486,6 +486,7 @@ IF(NOT DESTDIR)
ENDIF(NOT DESTDIR)
# Try to detect tip version from hg
+UNSET(ID CACHE)
SET(ID "unknown")
FIND_PROGRAM(HG "hg")
diff --git a/src/cfg_xml.c b/src/cfg_xml.c
index 67523c845..ddf995481 100644
--- a/src/cfg_xml.c
+++ b/src/cfg_xml.c
@@ -51,6 +51,13 @@
NULL \
} \
+#define NULL_DEF_ATTR \
+{ \
+ NULL, \
+ 0, \
+ NULL \
+} \
+
enum xml_config_section {
XML_SECTION_MAIN,
XML_SECTION_LOGGING,
@@ -64,16 +71,22 @@ enum xml_config_section {
};
struct xml_config_param {
- const gchar *name;
- element_handler_func handler;
- gint offset;
- gpointer user_data;
+ const gchar *name;
+ element_handler_func handler;
+ gint offset;
+ gpointer user_data;
+};
+
+struct xml_default_config_param {
+ element_default_handler_func handler;
+ gint offset;
+ gpointer user_data;
};
struct xml_parser_rule {
enum xml_config_section section;
struct xml_config_param params[MAX_PARAM];
- struct xml_config_param default_param;
+ struct xml_default_config_param default_param;
};
/* Here we describes our basic grammar */
@@ -165,7 +178,7 @@ static struct xml_parser_rule grammar[] = {
},
NULL_ATTR
},
- NULL_ATTR
+ NULL_DEF_ATTR
},
{ XML_SECTION_LOGGING, {
{
@@ -206,7 +219,7 @@ static struct xml_parser_rule grammar[] = {
},
NULL_ATTR
},
- NULL_ATTR
+ NULL_DEF_ATTR
},
{ XML_SECTION_WORKER, {
{
@@ -242,7 +255,6 @@ static struct xml_parser_rule grammar[] = {
NULL_ATTR
},
{
- NULL,
worker_handle_param,
0,
NULL
@@ -287,7 +299,7 @@ static struct xml_parser_rule grammar[] = {
},
NULL_ATTR
},
- NULL_ATTR
+ NULL_DEF_ATTR
},
{ XML_SECTION_CLASSIFIER, {
{
@@ -302,15 +314,13 @@ static struct xml_parser_rule grammar[] = {
0,
NULL
},
- {
- "option",
- handle_classifier_opt,
- 0,
- NULL
- },
NULL_ATTR
},
- NULL_ATTR
+ {
+ handle_classifier_opt,
+ 0,
+ NULL
+ }
},
{ XML_SECTION_STATFILE, {
{
@@ -357,13 +367,12 @@ static struct xml_parser_rule grammar[] = {
},
NULL_ATTR
},
- NULL_ATTR
+ NULL_DEF_ATTR
},
{ XML_SECTION_MODULE, {
NULL_ATTR
},
{
- NULL,
handle_module_opt,
0,
NULL
@@ -378,7 +387,7 @@ static struct xml_parser_rule grammar[] = {
},
NULL_ATTR
},
- NULL_ATTR
+ NULL_DEF_ATTR
},
{ XML_SECTION_VIEW, {
{
@@ -419,10 +428,14 @@ static struct xml_parser_rule grammar[] = {
},
NULL_ATTR
},
- NULL_ATTR
+ NULL_DEF_ATTR
},
};
+static GHashTable *module_options = NULL,
+ *worker_options = NULL,
+ *classifier_options = NULL;
+
GQuark
xml_error_quark (void)
{
@@ -510,9 +523,8 @@ call_param_handler (struct rspamd_xml_userdata *ctx, const gchar *name, gchar *v
param ++;
}
if (rule->default_param.handler != NULL) {
- param = &rule->default_param;
/* Call default handler */
- return param->handler (ctx->cfg, ctx, ctx->cur_attrs, value, param->user_data, dest_struct, param->offset);
+ return rule->default_param.handler (ctx->cfg, ctx, name, ctx->cur_attrs, value, param->user_data, dest_struct, param->offset);
}
}
}
@@ -625,17 +637,32 @@ handle_log_level (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHas
/* Worker section */
gboolean
-worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
+worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
{
struct worker_conf *wrk = ctx->section_pointer;
- gchar *name;
+ const gchar *name;
+ struct xml_config_param *cparam;
+ GHashTable *worker_config;
- if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
- msg_err ("worker param tag must have \"name\" attribute");
- return FALSE;
+ if (g_ascii_strcasecmp (tag, "option") == 0 || g_ascii_strcasecmp (tag, "param") == 0) {
+ if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
+ msg_err ("worker param tag must have \"name\" attribute");
+ return FALSE;
+ }
+ }
+ else {
+ name = tag;
}
- g_hash_table_insert (wrk->params, name, memory_pool_strdup (cfg->cfg_pool, data));
+ if (!worker_options ||
+ (worker_config = g_hash_table_lookup (worker_options, &wrk->type)) == NULL ||
+ (cparam = g_hash_table_lookup (worker_config, name)) == NULL) {
+ msg_warn ("unregistered worker attribute '%s' for worker %s", name, process_to_str (wrk->type));
+ g_hash_table_insert (wrk->params, (char *)name, memory_pool_strdup (cfg->cfg_pool, data));
+ }
+ else {
+ return cparam->handler (cfg, ctx, attrs, data, NULL, cparam->user_data, cparam->offset);
+ }
return TRUE;
}
@@ -765,27 +792,36 @@ handle_metric_symbol (struct config_file *cfg, struct rspamd_xml_userdata *ctx,
/* Modules section */
gboolean
-handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
+handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
{
- gchar *name, *val;
+ gchar *val;
struct module_opt *cur;
gboolean is_lua = FALSE;
-
- if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
- msg_err ("param tag must have \"name\" attribute");
- return FALSE;
+ const gchar *name;
+
+ if (g_ascii_strcasecmp (tag, "option") == 0 || g_ascii_strcasecmp (tag, "param") == 0) {
+ if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
+ msg_err ("worker param tag must have \"name\" attribute");
+ return FALSE;
+ }
}
-
+ else {
+ name = tag;
+ }
+
/* Check for lua */
if ((val = g_hash_table_lookup (attrs, "lua")) != NULL) {
if (g_ascii_strcasecmp (val, "yes") == 0) {
is_lua = TRUE;
}
}
+ /* XXX: in fact we cannot check for lua modules and need to do it in post-config procedure
+ * so just insert any options provided and try to handle them in further process
+ */
/* Insert option */
cur = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct module_opt));
- cur->param = name;
+ cur->param = (char *)name;
cur->value = data;
cur->is_lua = is_lua;
ctx->section_pointer = g_list_prepend (ctx->section_pointer, cur);
@@ -1048,17 +1084,33 @@ handle_classifier_tokenizer (struct config_file *cfg, struct rspamd_xml_userdata
}
gboolean
-handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
+handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
{
- struct classifier_config *ccf = ctx->section_pointer;
- gchar *val;
-
- if ((val = g_hash_table_lookup (attrs, "name")) == NULL) {
- msg_err ("'name' attribute is required for tag 'option'");
- return FALSE;
+ struct classifier_config *ccf = ctx->section_pointer;
+ const gchar *name;
+ struct xml_config_param *cparam;
+ GHashTable *classifier_config;
+
+ if (g_ascii_strcasecmp (tag, "option") == 0 || g_ascii_strcasecmp (tag, "param") == 0) {
+ if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
+ msg_err ("worker param tag must have \"name\" attribute");
+ return FALSE;
+ }
+ }
+ else {
+ name = tag;
+ }
+
+ if (!classifier_options ||
+ (classifier_config = g_hash_table_lookup (classifier_options, ccf->classifier->name)) == NULL ||
+ (cparam = g_hash_table_lookup (classifier_config, name)) == NULL) {
+ msg_warn ("unregistered classifier attribute '%s' for classifier %s", name, ccf->classifier->name);
+ g_hash_table_insert (ccf->opts, (char *)name, memory_pool_strdup (cfg->cfg_pool, data));
+ }
+ else {
+ return cparam->handler (cfg, ctx, attrs, data, NULL, cparam->user_data, cparam->offset);
}
- g_hash_table_insert (ccf->opts, val, memory_pool_strdup (cfg->cfg_pool, data));
return TRUE;
}
@@ -1633,6 +1685,118 @@ rspamd_xml_error (GMarkupParseContext *context, GError *error, gpointer user_dat
msg_err ("xml parser error: %s, at state \"%s\"", error->message, xml_state_to_string (ud));
}
+/* Register handlers for specific parts of config */
+/* Register new module option */
+void
+register_module_opt (const gchar *mname, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset)
+{
+ struct xml_config_param *param;
+ GHashTable *module;
+
+ if (module_options == NULL) {
+ module_options = g_hash_table_new (g_str_hash, g_str_equal);
+ }
+ if ((module = g_hash_table_lookup (module_options, mname)) == NULL) {
+ module = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (module_options, (char *)mname, module);
+ }
+ if ((param = g_hash_table_lookup (module, optname)) == NULL) {
+ /* Register new param */
+ param = g_malloc (sizeof (struct xml_config_param));
+ param->handler = func;
+ param->user_data = dest_struct;
+ param->offset = offset;
+ param->name = optname;
+ g_hash_table_insert (module, (char *)optname, param);
+ }
+ else {
+ /* Param already exists replace it */
+ msg_warn ("replace old handler for param '%s'", optname);
+ g_free (param);
+ param = g_malloc (sizeof (struct xml_config_param));
+ param->handler = func;
+ param->user_data = dest_struct;
+ param->offset = offset;
+ param->name = optname;
+ g_hash_table_insert (module, (char *)optname, param);
+ }
+}
+
+/* Register new worker's options */
+void
+register_worker_opt (gint wtype, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset)
+{
+ struct xml_config_param *param;
+ GHashTable *worker;
+ gint *new_key;
+
+ if (worker_options == NULL) {
+ worker_options = g_hash_table_new (g_int_hash, g_int_equal);
+ }
+ if ((worker = g_hash_table_lookup (worker_options, &wtype)) == NULL) {
+ worker = g_hash_table_new (g_str_hash, g_str_equal);
+ new_key = g_malloc (sizeof (gint));
+ *new_key = wtype;
+ g_hash_table_insert (worker_options, new_key, worker);
+ }
+ if ((param = g_hash_table_lookup (worker, optname)) == NULL) {
+ /* Register new param */
+ param = g_malloc (sizeof (struct xml_config_param));
+ param->handler = func;
+ param->user_data = dest_struct;
+ param->offset = offset;
+ param->name = optname;
+ g_hash_table_insert (worker, (char *)optname, param);
+ }
+ else {
+ /* Param already exists replace it */
+ msg_warn ("replace old handler for param '%s'", optname);
+ g_free (param);
+ param = g_malloc (sizeof (struct xml_config_param));
+ param->handler = func;
+ param->user_data = dest_struct;
+ param->offset = offset;
+ param->name = optname;
+ g_hash_table_insert (worker, (char *)optname, param);
+ }
+}
+
+/* Register new classifier option */
+void
+register_classifier_opt (const gchar *ctype, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset)
+{
+ struct xml_config_param *param;
+ GHashTable *classifier;
+
+ if (classifier_options == NULL) {
+ classifier_options = g_hash_table_new (g_str_hash, g_str_equal);
+ }
+ if ((classifier = g_hash_table_lookup (classifier_options, ctype)) == NULL) {
+ classifier = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (classifier_options, (char *)ctype, classifier);
+ }
+ if ((param = g_hash_table_lookup (classifier, optname)) == NULL) {
+ /* Register new param */
+ param = g_malloc (sizeof (struct xml_config_param));
+ param->handler = func;
+ param->user_data = dest_struct;
+ param->offset = offset;
+ param->name = optname;
+ g_hash_table_insert (classifier, (char *)optname, param);
+ }
+ else {
+ /* Param already exists replace it */
+ msg_warn ("replace old handler for param '%s'", optname);
+ g_free (param);
+ param = g_malloc (sizeof (struct xml_config_param));
+ param->handler = func;
+ param->user_data = dest_struct;
+ param->offset = offset;
+ param->name = optname;
+ g_hash_table_insert (classifier, (char *)optname, param);
+ }
+}
+
/* Dumper part */
diff --git a/src/cfg_xml.h b/src/cfg_xml.h
index 456d37fa8..dc55d2c86 100644
--- a/src/cfg_xml.h
+++ b/src/cfg_xml.h
@@ -39,6 +39,7 @@ struct rspamd_xml_userdata {
/* Text is NULL terminated here */
typedef gboolean (*element_handler_func) (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+typedef gboolean (*element_default_handler_func) (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
/* Callbacks */
@@ -88,42 +89,62 @@ gboolean xml_handle_uint16 (struct config_file *cfg, struct rspamd_xml_userdata
gboolean xml_handle_boolean (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
/* Specific params */
-gboolean worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle workers param */
+gboolean worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean worker_handle_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean worker_handle_bind (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle metric symbol */
gboolean handle_metric_symbol (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
-gboolean handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle common module option */
+gboolean handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle loging params */
gboolean handle_log_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_log_level (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle lua include */
gboolean handle_lua (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle path to modules */
gboolean handle_module_path (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle variables and composites */
gboolean handle_variable (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_composite (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle views */
gboolean handle_view_ip (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_view_client_ip (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_view_from (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_view_rcpt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_view_symbols (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle settings */
gboolean handle_user_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_domain_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle classifier */
gboolean handle_classifier_tokenizer (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
-gboolean handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+gboolean handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle statfile */
gboolean handle_statfile_normalizer (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_statfile_binlog (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_statfile_binlog_rotate (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
gboolean handle_statfile_binlog_master (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Register new module option */
+void register_module_opt (const gchar *mname, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset);
+
+/* Register new worker's options */
+void register_worker_opt (gint wtype, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset);
+
+/* Register new classifier option */
+void register_classifier_opt (const gchar *ctype, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset);
+
/* Dumper functions */
gboolean xml_dump_config (struct config_file *cfg, const gchar *filename);
diff --git a/src/controller.c b/src/controller.c
index 42c034013..617821bf6 100644
--- a/src/controller.c
+++ b/src/controller.c
@@ -29,6 +29,7 @@
#include "protocol.h"
#include "upstream.h"
#include "cfg_file.h"
+#include "cfg_xml.h"
#include "modules.h"
#include "tokenizers/tokenizers.h"
#include "classifiers/classifiers.h"
@@ -67,6 +68,11 @@ struct custom_controller_command {
controller_func_t handler;
};
+struct rspamd_controller_ctx {
+ char *password;
+ guint32 timeout;
+};
+
static struct controller_command commands[] = {
{"password", FALSE, COMMAND_PASSWORD},
{"quit", FALSE, COMMAND_QUIT},
@@ -421,9 +427,9 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
gchar out_buf[BUFSIZ], *arg, *err_str;
gint r = 0, days, hours, minutes;
time_t uptime;
- guint32 size = 0;
+ guint32 size = 0;
struct classifier_config *cl;
- gchar *password = g_hash_table_lookup (session->worker->cf->params, "password");
+ struct rspamd_controller_ctx *ctx = session->worker->ctx;
switch (cmd->type) {
case COMMAND_PASSWORD:
@@ -436,14 +442,14 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
}
return TRUE;
}
- if (password == NULL) {
+ if (ctx->password == NULL) {
r = rspamd_snprintf (out_buf, sizeof (out_buf), "password command disabled in config, authorized access unallowed" CRLF);
if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
return FALSE;
}
return TRUE;
}
- if (strncmp (arg, password, strlen (arg)) == 0) {
+ if (strncmp (arg, ctx->password, strlen (arg)) == 0) {
session->authorized = 1;
r = rspamd_snprintf (out_buf, sizeof (out_buf), "password accepted" CRLF);
if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
@@ -1023,6 +1029,9 @@ accept_socket (gint fd, short what, void *arg)
struct timeval *io_tv;
socklen_t addrlen = sizeof (ss);
gint nfd;
+ struct rspamd_controller_ctx *ctx;
+
+ ctx = worker->ctx;
if ((nfd = accept_from_socket (fd, (struct sockaddr *)&ss, &addrlen)) == -1) {
msg_warn ("accept failed: %s", strerror (errno));
@@ -1044,8 +1053,8 @@ accept_socket (gint fd, short what, void *arg)
/* Set up dispatcher */
io_tv = memory_pool_alloc (new_session->session_pool, sizeof (struct timeval));
- io_tv->tv_sec = CONTROLLER_IO_TIMEOUT;
- io_tv->tv_usec = 0;
+ io_tv->tv_sec = ctx->timeout / 1000;
+ io_tv->tv_usec = ctx->timeout - io_tv->tv_sec * 1000;
new_session->s = new_async_session (new_session->session_pool, free_session, new_session);
@@ -1055,6 +1064,21 @@ accept_socket (gint fd, short what, void *arg)
}
}
+gpointer
+init_controller (void)
+{
+ struct rspamd_controller_ctx *ctx;
+
+ ctx = g_malloc0 (sizeof (struct rspamd_controller_ctx));
+
+ ctx->timeout = CONTROLLER_IO_TIMEOUT * 1000;
+
+ register_worker_opt (TYPE_CONTROLLER, "password", xml_handle_string, ctx, G_STRUCT_OFFSET (struct rspamd_controller_ctx, password));
+ register_worker_opt (TYPE_CONTROLLER, "timeout", xml_handle_seconds, ctx, G_STRUCT_OFFSET (struct rspamd_controller_ctx, timeout));
+
+ return ctx;
+}
+
void
start_controller (struct rspamd_worker *worker)
{
diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c
index dc18a694d..f8d4a855a 100644
--- a/src/fuzzy_storage.c
+++ b/src/fuzzy_storage.c
@@ -32,6 +32,7 @@
#include "protocol.h"
#include "upstream.h"
#include "cfg_file.h"
+#include "cfg_xml.h"
#include "url.h"
#include "modules.h"
#include "message.h"
@@ -66,20 +67,24 @@ static GQueue *hashes[BUCKETS];
static GQueue *frequent;
#ifdef WITH_JUDY
static gpointer jtree;
-static gboolean use_judy = FALSE;
#endif
static bloom_filter_t *bf;
/* Number of cache modifications */
static guint32 mods = 0;
-static guint32 max_mods = DEFAULT_MOD_LIMIT;
-/* Frequent score number */
-static guint32 frequent_score = DEFAULT_FREQUENT_SCORE;
/* For evtimer */
static struct timeval tmv;
static struct event tev;
static struct rspamd_stat *server_stat;
+struct rspamd_fuzzy_storage_ctx {
+ gboolean use_judy;
+ char *hashfile;
+ guint32 expire;
+ guint32 frequent_score;
+ guint32 max_mods;
+};
+
struct rspamd_fuzzy_node {
gint32 value;
gint32 flag;
@@ -120,32 +125,27 @@ static void
sync_cache (struct rspamd_worker *wrk)
{
gint fd, i;
- gchar *filename, *exp_str, header[4];
+ gchar *filename, header[4];
GList *cur, *tmp;
struct rspamd_fuzzy_node *node;
guint64 expire, now;
+ struct rspamd_fuzzy_storage_ctx *ctx = wrk->ctx;
#ifdef WITH_JUDY
PPvoid_t pvalue;
gchar indexbuf[1024], tmpindex[1024];
#endif
/* Check for modifications */
- if (mods < max_mods) {
+ if (mods < ctx->max_mods) {
return;
}
msg_info ("syncing fuzzy hash storage");
- filename = g_hash_table_lookup (wrk->cf->params, "hashfile");
+ filename = ctx->hashfile;
if (filename == NULL) {
return;
}
- exp_str = g_hash_table_lookup (wrk->cf->params, "expire");
- if (exp_str != NULL) {
- expire = parse_seconds (exp_str) / 1000;
- }
- else {
- expire = DEFAULT_EXPIRE;
- }
+ expire = ctx->expire;
if ((fd = open (filename, O_WRONLY | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) == -1) {
msg_err ("cannot create hash file %s: %s", filename, strerror (errno));
@@ -165,7 +165,7 @@ sync_cache (struct rspamd_worker *wrk)
}
#ifdef WITH_JUDY
- if (use_judy) {
+ if (ctx->use_judy) {
indexbuf[0] = '\0';
pvalue = JudySLFirst (jtree, indexbuf, PJE0);
while (pvalue) {
@@ -234,12 +234,14 @@ static void
sigterm_handler (gint fd, short what, void *arg)
{
struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ struct rspamd_fuzzy_storage_ctx *ctx;
static struct timeval tv = {
.tv_sec = 0,
.tv_usec = 0
};
- mods = max_mods + 1;
+ ctx = worker->ctx;
+ mods = ctx->max_mods + 1;
sync_cache (worker);
close (worker->cf->listen_sock);
(void)event_loopexit (&tv);
@@ -254,7 +256,9 @@ sigusr_handler (gint fd, short what, void *arg)
struct rspamd_worker *worker = (struct rspamd_worker *)arg;
/* Do not accept new connections, preparing to end worker's process */
struct timeval tv;
+ struct rspamd_fuzzy_storage_ctx *ctx;
+ ctx = worker->ctx;
tv.tv_sec = SOFT_SHUTDOWN_TIME;
tv.tv_usec = 0;
event_del (&worker->sig_ev);
@@ -263,7 +267,7 @@ sigusr_handler (gint fd, short what, void *arg)
do_reopen_log = 1;
msg_info ("worker's shutdown is pending in %d sec", SOFT_SHUTDOWN_TIME);
event_loopexit (&tv);
- mods = max_mods + 1;
+ mods = ctx->max_mods + 1;
sync_cache (worker);
return;
}
@@ -276,6 +280,7 @@ read_hashes_file (struct rspamd_worker *wrk)
gchar *filename, header[4];
gboolean touch_stat = TRUE;
struct rspamd_fuzzy_node *node;
+ struct rspamd_fuzzy_storage_ctx *ctx = wrk->ctx;
struct {
gint32 value;
guint64 time;
@@ -288,7 +293,7 @@ read_hashes_file (struct rspamd_worker *wrk)
touch_stat = FALSE;
}
- if (use_judy) {
+ if (ctx->use_judy) {
jtree = NULL;
}
else {
@@ -301,7 +306,7 @@ read_hashes_file (struct rspamd_worker *wrk)
}
#endif
- filename = g_hash_table_lookup (wrk->cf->params, "hashfile");
+ filename = ctx->hashfile;
if (filename == NULL) {
return FALSE;
}
@@ -354,13 +359,13 @@ read_hashes_file (struct rspamd_worker *wrk)
}
}
#ifdef WITH_JUDY
- if (use_judy) {
+ if (ctx->use_judy) {
pvalue = JudySLIns (&jtree, node->h.hash_pipe, PJE0);
*pvalue = node;
}
else {
#endif
- if (node->value > frequent_score) {
+ if (node->value > ctx->frequent_score) {
g_queue_push_head (frequent, node);
}
else {
@@ -376,7 +381,7 @@ read_hashes_file (struct rspamd_worker *wrk)
}
#ifdef WITH_JUDY
- if (!use_judy) {
+ if (!ctx->use_judy) {
#endif
/* Sort everything */
g_queue_sort (frequent, compare_nodes, NULL);
@@ -402,7 +407,7 @@ read_hashes_file (struct rspamd_worker *wrk)
}
static inline struct rspamd_fuzzy_node *
-check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value)
+check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value, struct rspamd_fuzzy_storage_ctx *ctx)
{
GList *cur;
struct rspamd_fuzzy_node *h;
@@ -410,7 +415,7 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value)
#ifdef WITH_JUDY
PPvoid_t pvalue;
- if (use_judy) {
+ if (ctx->use_judy) {
pvalue = JudySLGet (jtree, s->hash_pipe, PJE0);
if (pvalue != NULL) {
h = *((struct rspamd_fuzzy_node **)pvalue);
@@ -449,7 +454,7 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value)
h->value += update_value;
msg_info ("new hash weight: %d", h->value);
}
- if (h->value > frequent_score) {
+ if (h->value > ctx->frequent_score) {
g_queue_unlink (hash, cur);
g_queue_push_head_link (frequent, cur);
msg_info ("moved hash to frequent list");
@@ -466,11 +471,12 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value)
}
static gint
-process_check_command (struct fuzzy_cmd *cmd, gint *flag)
+process_check_command (struct fuzzy_cmd *cmd, gint *flag, struct rspamd_fuzzy_storage_ctx *ctx)
{
fuzzy_hash_t s;
struct rspamd_fuzzy_node *h;
+
if (!bloom_check (bf, cmd->hash)) {
return 0;
}
@@ -478,7 +484,7 @@ process_check_command (struct fuzzy_cmd *cmd, gint *flag)
memcpy (s.hash_pipe, cmd->hash, sizeof (s.hash_pipe));
s.block_size = cmd->blocksize;
- h = check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, 0);
+ h = check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, 0, ctx);
if (h == NULL) {
return 0;
@@ -490,7 +496,7 @@ process_check_command (struct fuzzy_cmd *cmd, gint *flag)
}
static gboolean
-update_hash (struct fuzzy_cmd *cmd)
+update_hash (struct fuzzy_cmd *cmd, struct rspamd_fuzzy_storage_ctx *ctx)
{
fuzzy_hash_t s;
@@ -498,11 +504,11 @@ update_hash (struct fuzzy_cmd *cmd)
s.block_size = cmd->blocksize;
mods ++;
- return check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, cmd->value) != NULL;
+ return check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, cmd->value, ctx) != NULL;
}
static gboolean
-process_write_command (struct fuzzy_cmd *cmd)
+process_write_command (struct fuzzy_cmd *cmd, struct rspamd_fuzzy_storage_ctx *ctx)
{
struct rspamd_fuzzy_node *h;
#ifdef WITH_JUDY
@@ -510,7 +516,7 @@ process_write_command (struct fuzzy_cmd *cmd)
#endif
if (bloom_check (bf, cmd->hash)) {
- if (update_hash (cmd)) {
+ if (update_hash (cmd, ctx)) {
return TRUE;
}
}
@@ -522,7 +528,7 @@ process_write_command (struct fuzzy_cmd *cmd)
h->value = cmd->value;
h->flag = cmd->flag;
#ifdef WITH_JUDY
- if (use_judy) {
+ if (ctx->use_judy) {
pvalue = JudySLIns (&jtree, h->h.hash_pipe, PJE0);
*pvalue = h;
}
@@ -542,7 +548,7 @@ process_write_command (struct fuzzy_cmd *cmd)
}
static gboolean
-delete_hash (GQueue *hash, fuzzy_hash_t *s)
+delete_hash (GQueue *hash, fuzzy_hash_t *s, struct rspamd_fuzzy_storage_ctx *ctx)
{
GList *cur, *tmp;
struct rspamd_fuzzy_node *h;
@@ -551,7 +557,7 @@ delete_hash (GQueue *hash, fuzzy_hash_t *s)
PPvoid_t pvalue;
gpointer data;
- if (use_judy) {
+ if (ctx->use_judy) {
pvalue = JudySLGet (jtree, s->hash_pipe, PJE0);
if (pvalue) {
data = *pvalue;
@@ -593,7 +599,7 @@ delete_hash (GQueue *hash, fuzzy_hash_t *s)
}
static gboolean
-process_delete_command (struct fuzzy_cmd *cmd)
+process_delete_command (struct fuzzy_cmd *cmd, struct rspamd_fuzzy_storage_ctx *ctx)
{
fuzzy_hash_t s;
gboolean res = FALSE;
@@ -605,17 +611,17 @@ process_delete_command (struct fuzzy_cmd *cmd)
memcpy (s.hash_pipe, cmd->hash, sizeof (s.hash_pipe));
s.block_size = cmd->blocksize;
#ifdef WITH_JUDY
- if (use_judy) {
- return delete_hash (NULL, &s);
+ if (ctx->use_judy) {
+ return delete_hash (NULL, &s, ctx);
}
else {
#endif
- res = delete_hash (frequent, &s);
+ res = delete_hash (frequent, &s, ctx);
if (!res) {
- res = delete_hash (hashes[cmd->blocksize % BUCKETS], &s);
+ res = delete_hash (hashes[cmd->blocksize % BUCKETS], &s, ctx);
}
else {
- (void)delete_hash (hashes[cmd->blocksize % BUCKETS], &s);
+ (void)delete_hash (hashes[cmd->blocksize % BUCKETS], &s, ctx);
}
#ifdef WITH_JUDY
}
@@ -626,7 +632,7 @@ process_delete_command (struct fuzzy_cmd *cmd)
#define CMD_PROCESS(x) \
do { \
-if (process_##x##_command (&session->cmd)) { \
+if (process_##x##_command (&session->cmd, session->worker->ctx)) { \
if (sendto (session->fd, "OK" CRLF, sizeof ("OK" CRLF) - 1, 0, (struct sockaddr *)&session->sa, session->salen) == -1) { \
msg_err ("error while writing reply: %s", strerror (errno)); \
} \
@@ -646,7 +652,7 @@ process_fuzzy_command (struct fuzzy_session *session)
switch (session->cmd.cmd) {
case FUZZY_CHECK:
- r = process_check_command (&session->cmd, &flag);
+ r = process_check_command (&session->cmd, &flag, session->worker->ctx);
if (r != 0) {
r = rspamd_snprintf (buf, sizeof (buf), "OK %d %d" CRLF, r, flag);
if (sendto (session->fd, buf, r, 0, (struct sockaddr *)&session->sa, session->salen) == -1) {
@@ -687,8 +693,8 @@ accept_fuzzy_socket (gint fd, short what, void *arg)
ssize_t r;
struct {
u_char cmd;
- guint32 blocksize;
- gint32 value;
+ guint32 blocksize;
+ gint32 value;
u_char hash[FUZZY_HASHLEN];
} legacy_cmd;
@@ -739,6 +745,28 @@ sync_callback (gint fd, short what, void *arg)
sync_cache (worker);
}
+gpointer
+init_fuzzy_storage (void)
+{
+ struct rspamd_fuzzy_storage_ctx *ctx;
+
+ ctx = g_malloc0 (sizeof (struct rspamd_fuzzy_storage_ctx));
+
+ ctx->max_mods = DEFAULT_MOD_LIMIT;
+ ctx->frequent_score = DEFAULT_FREQUENT_SCORE;
+
+ register_worker_opt (TYPE_FUZZY, "hashfile", xml_handle_string, ctx,
+ G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, hashfile));
+ register_worker_opt (TYPE_FUZZY, "max_mods", xml_handle_uint32, ctx,
+ G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, max_mods));
+ register_worker_opt (TYPE_FUZZY, "frequent_score", xml_handle_uint32, ctx,
+ G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, frequent_score));
+ register_worker_opt (TYPE_FUZZY, "use_judy", xml_handle_boolean, ctx,
+ G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, use_judy));
+
+ return ctx;
+}
+
/*
* Start worker process
*/
@@ -748,7 +776,6 @@ start_fuzzy_storage (struct rspamd_worker *worker)
struct sigaction signals;
struct event sev;
gint retries = 0;
- gchar *value;
worker->srv->pid = getpid ();
worker->srv->type = TYPE_FUZZY;
@@ -765,20 +792,6 @@ start_fuzzy_storage (struct rspamd_worker *worker)
signal_add (&worker->sig_ev, NULL);
signal_set (&sev, SIGTERM, sigterm_handler, (void *)worker);
signal_add (&sev, NULL);
- /* Get params */
- if ((value = g_hash_table_lookup (worker->cf->params, "frequent_score")) != NULL) {
- frequent_score = strtol (value, NULL, 10);
- }
- if ((value = g_hash_table_lookup (worker->cf->params, "max_mods")) != NULL) {
- max_mods = strtol (value, NULL, 10);
- }
- if ((value = g_hash_table_lookup (worker->cf->params, "use_judy")) != NULL) {
-#ifdef WITH_JUDY
- use_judy = TRUE;
-#else
- msg_err ("cannot use judy storage as judy support is not compiled in");
-#endif
- }
/* Listen event */
while ((worker->cf->listen_sock = make_udp_socket (&worker->cf->bind_addr, worker->cf->bind_port, TRUE, TRUE)) == -1) {
@@ -802,13 +815,11 @@ start_fuzzy_storage (struct rspamd_worker *worker)
tmv.tv_usec = 0;
evtimer_add (&tev, &tmv);
-
event_set (&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_fuzzy_socket, (void *)worker);
event_add (&worker->bind_ev, NULL);
gperf_profiler_init (worker->srv->cfg, "fuzzy");
-
event_loop (0);
exit (EXIT_SUCCESS);
}
diff --git a/src/fuzzy_storage.h b/src/fuzzy_storage.h
index 5a02d4871..f5196b1d6 100644
--- a/src/fuzzy_storage.h
+++ b/src/fuzzy_storage.h
@@ -27,6 +27,7 @@ struct fuzzy_session {
struct sockaddr_storage sa;
};
+gpointer init_fuzzy_storage (void);
void start_fuzzy_storage (struct rspamd_worker *worker);
#endif
diff --git a/src/logger.c b/src/logger.c
index eda67f161..85bd2fc90 100644
--- a/src/logger.c
+++ b/src/logger.c
@@ -542,29 +542,8 @@ file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFla
tms = localtime (&now);
strftime (timebuf, sizeof (timebuf), "%F %H:%M:%S", tms);
- switch (rspamd_log->process_type) {
- case TYPE_MAIN:
- cptype = "main";
- break;
- case TYPE_WORKER:
- cptype = "worker";
- break;
- case TYPE_CONTROLLER:
- cptype = "controller";
- break;
- case TYPE_LMTP:
- cptype = "lmtp";
- break;
- case TYPE_SMTP:
- cptype = "smtp";
- break;
- case TYPE_FUZZY:
- cptype = "fuzzy";
- break;
- case TYPE_GREYLIST:
- cptype = "greylist";
- break;
- }
+ cptype = process_to_str (rspamd_log->process_type);
+
if (function == NULL) {
r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%s #%P(%s) ", timebuf, rspamd_log->pid, cptype);
}
diff --git a/src/logger.h b/src/logger.h
index f2adf65c6..7a3fade7c 100644
--- a/src/logger.h
+++ b/src/logger.h
@@ -6,18 +6,6 @@
#include "radix.h"
#include "util.h"
-/**
- * Process type: main or worker
- */
-enum process_type {
- TYPE_MAIN,
- TYPE_WORKER,
- TYPE_CONTROLLER,
- TYPE_LMTP,
- TYPE_SMTP,
- TYPE_FUZZY,
- TYPE_GREYLIST
-};
typedef void (*rspamd_log_func_t)(const gchar * log_domain, const gchar *function,
GLogLevelFlags log_level, const gchar * message,
diff --git a/src/main.c b/src/main.c
index 591dd6183..0fcd4e89a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -339,6 +339,7 @@ fork_worker (struct rspamd_main *rspamd, struct worker_conf *cf)
cur->type = cf->type;
cur->pid = fork ();
cur->cf = g_malloc (sizeof (struct worker_conf));
+ cur->ctx = rspamd->workers_ctx[cf->type];
memcpy (cur->cf, cf, sizeof (struct worker_conf));
cur->pending = FALSE;
switch (cur->pid) {
@@ -564,29 +565,6 @@ spawn_workers (struct rspamd_main *rspamd)
}
}
-static const gchar *
-get_process_type (enum process_type type)
-{
- switch (type) {
- case TYPE_MAIN:
- return "main";
- case TYPE_WORKER:
- return "worker";
- case TYPE_FUZZY:
- return "fuzzy";
- case TYPE_GREYLIST:
- return "greylist";
- case TYPE_CONTROLLER:
- return "controller";
- case TYPE_LMTP:
- return "lmtp";
- case TYPE_SMTP:
- return "smtp";
- }
-
- return NULL;
-}
-
static void
kill_old_workers (gpointer key, gpointer value, gpointer unused)
{
@@ -604,7 +582,7 @@ wait_for_workers (gpointer key, gpointer value, gpointer unused)
waitpid (w->pid, &res, 0);
- msg_debug ("%s process %P terminated", get_process_type (w->type), w->pid);
+ msg_debug ("%s process %P terminated", process_to_str (w->type), w->pid);
g_free (w->cf);
g_free (w);
@@ -755,6 +733,15 @@ print_symbols_cache (struct config_file *cfg)
}
}
+static void
+init_workers_ctx (struct rspamd_main *main)
+{
+ main->workers_ctx[TYPE_WORKER] = init_worker ();
+ main->workers_ctx[TYPE_CONTROLLER] = init_controller ();
+ main->workers_ctx[TYPE_FUZZY] = init_fuzzy_storage ();
+ main->workers_ctx[TYPE_SMTP] = init_smtp_worker ();
+}
+
gint
main (gint argc, gchar **argv, gchar **env)
{
@@ -829,6 +816,9 @@ main (gint argc, gchar **argv, gchar **env)
/* Init listen sockets hash */
listen_sockets = g_hash_table_new (g_direct_hash, g_direct_equal);
+ /* Init contextes */
+ init_workers_ctx (rspamd);
+
if (! load_rspamd_config (rspamd->cfg, TRUE)) {
exit (EXIT_FAILURE);
}
@@ -958,14 +948,14 @@ main (gint argc, gchar **argv, gchar **env)
if (WIFEXITED (res) && WEXITSTATUS (res) == 0) {
/* Normal worker termination, do not fork one more */
- msg_info ("%s process %P terminated normally", get_process_type (cur->type), cur->pid);
+ msg_info ("%s process %P terminated normally", process_to_str (cur->type), cur->pid);
}
else {
if (WIFSIGNALED (res)) {
- msg_warn ("%s process %P terminated abnormally by signal: %d", get_process_type (cur->type), cur->pid, WTERMSIG (res));
+ msg_warn ("%s process %P terminated abnormally by signal: %d", process_to_str (cur->type), cur->pid, WTERMSIG (res));
}
else {
- msg_warn ("%s process %P terminated abnormally", get_process_type (cur->type), cur->pid);
+ msg_warn ("%s process %P terminated abnormally", process_to_str (cur->type), cur->pid);
}
/* Fork another worker in replace of dead one */
delay_fork (cur->cf);
diff --git a/src/main.h b/src/main.h
index a482cb1b1..b934ae31e 100644
--- a/src/main.h
+++ b/src/main.h
@@ -41,8 +41,6 @@
#define CR '\r'
#define LF '\n'
-
-
/**
* Worker process structure
*/
@@ -91,9 +89,11 @@ struct rspamd_main {
/* Pid file structure */
struct pidfh *pfh; /**< struct pidfh for pidfile */
enum process_type type; /**< process type */
- guint ev_initialized; /**< is event system is initialized */
+ guint ev_initialized; /**< is event system is initialized */
struct rspamd_stat *stat; /**< pointer to statistics */
+ gpointer workers_ctx[TYPE_MAX]; /** Array of workers' contexts */
+
memory_pool_t *server_pool; /**< server's memory pool */
statfile_pool_t *statfile_pool; /**< shared statfiles pool */
GHashTable *workers; /**< workers pool indexed by pid */
@@ -245,8 +245,12 @@ struct c_module {
struct module_ctx *ctx; /**< pointer to context */
};
+/* Workers' initialization and start functions */
+gpointer init_worker (void);
void start_worker (struct rspamd_worker *worker);
+gpointer init_controller (void);
void start_controller (struct rspamd_worker *worker);
+gpointer init_greylist (void);
void start_greylist_storage (struct rspamd_worker *worker);
/**
diff --git a/src/smtp.c b/src/smtp.c
index a76858547..d1bef023a 100644
--- a/src/smtp.c
+++ b/src/smtp.c
@@ -25,6 +25,7 @@
#include "config.h"
#include "main.h"
#include "cfg_file.h"
+#include "cfg_xml.h"
#include "util.h"
#include "smtp.h"
#include "smtp_proto.h"
@@ -895,25 +896,59 @@ make_capabilities (struct smtp_worker_ctx *ctx, const gchar *line)
g_strfreev (strv);
}
-
-static gboolean
-config_smtp_worker (struct rspamd_worker *worker)
+gpointer
+init_smtp_worker (void)
{
struct smtp_worker_ctx *ctx;
- gchar *value;
- guint32 timeout;
ctx = g_malloc0 (sizeof (struct smtp_worker_ctx));
ctx->pool = memory_pool_new (memory_pool_get_size ());
/* Set default values */
- ctx->smtp_timeout.tv_sec = 300;
- ctx->smtp_timeout.tv_usec = 0;
+ ctx->smtp_timeout_raw = 300000;
ctx->smtp_delay = 0;
ctx->smtp_banner = "220 ESMTP Ready." CRLF;
bzero (ctx->smtp_filters, sizeof (GList *) * SMTP_STAGE_MAX);
+ ctx->max_errors = DEFAULT_MAX_ERRORS;
+ ctx->reject_message = DEFAULT_REJECT_MESSAGE;
+
+ register_worker_opt (TYPE_SMTP, "upstreams", xml_handle_string, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, upstreams_str));
+ register_worker_opt (TYPE_SMTP, "banner", xml_handle_string, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_banner_str));
+ register_worker_opt (TYPE_SMTP, "timeout", xml_handle_seconds, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_timeout_raw));
+ register_worker_opt (TYPE_SMTP, "delay", xml_handle_seconds, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_delay));
+ register_worker_opt (TYPE_SMTP, "jitter", xml_handle_seconds, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, delay_jitter));
+ register_worker_opt (TYPE_SMTP, "capabilities", xml_handle_string, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_capabilities_str));
+ register_worker_opt (TYPE_SMTP, "xclient", xml_handle_boolean, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, use_xclient));
+ register_worker_opt (TYPE_SMTP, "reject_message", xml_handle_string, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, reject_message));
+ register_worker_opt (TYPE_SMTP, "max_errors", xml_handle_uint32, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, max_errors));
+ register_worker_opt (TYPE_SMTP, "max_size", xml_handle_size, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, max_size));
+
+ return ctx;
+}
- if ((value = g_hash_table_lookup (worker->cf->params, "upstreams")) != NULL) {
+/* Make post-init configuration */
+static gboolean
+config_smtp_worker (struct rspamd_worker *worker)
+{
+ struct smtp_worker_ctx *ctx = worker->ctx;
+ gchar *value;
+
+ /* Init timeval */
+ ctx->smtp_timeout.tv_sec = ctx->smtp_timeout_raw / 1000;
+ ctx->smtp_timeout.tv_usec = (ctx->smtp_timeout_raw - ctx->smtp_timeout.tv_sec * 1000) * 1000;
+
+ /* Init upstreams */
+ if ((value = ctx->upstreams_str) != NULL) {
if (!parse_upstreams_line (ctx, value)) {
return FALSE;
}
@@ -922,53 +957,19 @@ config_smtp_worker (struct rspamd_worker *worker)
msg_err ("no upstreams defined, don't know what to do");
return FALSE;
}
- if ((value = g_hash_table_lookup (worker->cf->params, "smtp_banner")) != NULL) {
+ /* Create smtp banner */
+ if ((ctx->smtp_banner_str) != NULL) {
parse_smtp_banner (ctx, value);
}
- if ((value = g_hash_table_lookup (worker->cf->params, "smtp_timeout")) != NULL) {
- errno = 0;
- timeout = parse_seconds (value);
- ctx->smtp_timeout.tv_sec = timeout / 1000;
- ctx->smtp_timeout.tv_usec = (timeout - ctx->smtp_timeout.tv_sec * 1000) * 1000;
- }
- if ((value = g_hash_table_lookup (worker->cf->params, "smtp_delay")) != NULL) {
- ctx->smtp_delay = parse_seconds (value);
- }
- if ((value = g_hash_table_lookup (worker->cf->params, "smtp_jitter")) != NULL) {
- ctx->delay_jitter = parse_seconds (value);
- }
- if ((value = g_hash_table_lookup (worker->cf->params, "smtp_capabilities")) != NULL) {
+
+ /* Parse capabilities */
+ if ((value = ctx->smtp_capabilities_str) != NULL) {
make_capabilities (ctx, value);
}
- if ((value = g_hash_table_lookup (worker->cf->params, "smtp_use_xclient")) != NULL) {
- ctx->use_xclient = parse_flag (value);
- }
- if ((value = g_hash_table_lookup (worker->cf->params, "smtp_metric")) != NULL) {
- ctx->metric = memory_pool_strdup (ctx->pool, value);
- }
- else {
- ctx->metric = DEFAULT_METRIC;
- }
- if ((value = g_hash_table_lookup (worker->cf->params, "smtp_max_errors")) != NULL) {
- ctx->max_errors = strtoul (value, NULL, 10);
- }
- else {
- ctx->max_errors = DEFAULT_MAX_ERRORS;
- }
- if ((value = g_hash_table_lookup (worker->cf->params, "smtp_reject_message")) != NULL) {
- ctx->reject_message = memory_pool_strdup (ctx->pool, value);
- }
- else {
- ctx->reject_message = DEFAULT_REJECT_MESSAGE;
- }
ctx->resolver = dns_resolver_init (worker->srv->cfg);
-
- /* Set ctx */
- worker->ctx = ctx;
return TRUE;
-
}
diff --git a/src/smtp.h b/src/smtp.h
index 1933376c3..ddb302487 100644
--- a/src/smtp.h
+++ b/src/smtp.h
@@ -31,19 +31,23 @@ enum rspamd_smtp_stage {
struct smtp_worker_ctx {
struct smtp_upstream upstreams[MAX_UPSTREAM];
size_t upstream_num;
+ gchar *upstreams_str;
memory_pool_t *pool;
gchar *smtp_banner;
+ gchar *smtp_banner_str;
guint32 smtp_delay;
guint32 delay_jitter;
+ guint32 smtp_timeout_raw;
struct timeval smtp_timeout;
gboolean use_xclient;
gboolean helo_required;
gchar *smtp_capabilities;
+ gchar *smtp_capabilities_str;
gchar *reject_message;
- size_t max_size;
- guint max_errors;
+ gsize max_size;
+ guint32 max_errors;
gchar *metric;
GList *smtp_filters[SMTP_STAGE_MAX];
struct rspamd_dns_resolver *resolver;
@@ -115,6 +119,7 @@ struct smtp_filter {
gpointer filter_data;
};
+gpointer init_smtp_worker (void);
void start_smtp_worker (struct rspamd_worker *worker);
void register_smtp_filter (struct smtp_worker_ctx *ctx, enum rspamd_smtp_stage stage, smtp_filter_t filter, gpointer filter_data);
diff --git a/src/util.c b/src/util.c
index 78be8cbaf..a420493dc 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1641,6 +1641,60 @@ rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz)
return (s - src - 1); /* count does not include NUL */
}
+/* Convert process type to its name */
+const gchar *
+process_to_str (enum process_type type)
+{
+ switch (type) {
+ case TYPE_MAIN:
+ return "main";
+ case TYPE_WORKER:
+ return "worker";
+ case TYPE_FUZZY:
+ return "fuzzy";
+ case TYPE_GREYLIST:
+ return "greylist";
+ case TYPE_CONTROLLER:
+ return "controller";
+ case TYPE_LMTP:
+ return "lmtp";
+ case TYPE_SMTP:
+ return "smtp";
+ default:
+ return "unknown";
+ }
+
+ return NULL;
+}
+/* Convert string to process type */
+enum process_type
+str_to_process (const gchar *str)
+{
+ if (g_ascii_strcasecmp (str, "main") == 0) {
+ return TYPE_MAIN;
+ }
+ else if (g_ascii_strcasecmp (str, "worker") == 0) {
+ return TYPE_WORKER;
+ }
+ else if (g_ascii_strcasecmp (str, "fuzzy") == 0) {
+ return TYPE_FUZZY;
+ }
+ else if (g_ascii_strcasecmp (str, "greylist") == 0) {
+ return TYPE_GREYLIST;
+ }
+ else if (g_ascii_strcasecmp (str, "controller") == 0) {
+ return TYPE_CONTROLLER;
+ }
+ else if (g_ascii_strcasecmp (str, "smtp") == 0) {
+ return TYPE_SMTP;
+ }
+ else if (g_ascii_strcasecmp (str, "lmtp") == 0) {
+ return TYPE_LMTP;
+ }
+
+ return TYPE_UNKNOWN;
+}
+
/*
* vi:ts=4
*/
diff --git a/src/util.h b/src/util.h
index 36d650877..2ba01d05e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -12,6 +12,21 @@ struct workq;
struct statfile;
struct classifier_config;
+/**
+ * Process type: main or worker
+ */
+enum process_type {
+ TYPE_UNKNOWN=-1,
+ TYPE_MAIN,
+ TYPE_WORKER,
+ TYPE_CONTROLLER,
+ TYPE_LMTP,
+ TYPE_SMTP,
+ TYPE_FUZZY,
+ TYPE_GREYLIST,
+ TYPE_MAX=255
+};
+
/* Create socket and bind or connect it to specified address and port */
gint make_tcp_socket (struct in_addr *, u_short, gboolean is_server, gboolean async);
/* Create socket and bind or connect it to specified address and port */
@@ -143,4 +158,19 @@ gsize rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz);
*/
gchar * rspamd_escape_string (gchar *dst, const gchar *src, gsize len);
+/*
+ * Convert process type to its name
+ *
+ * @param type numeric type
+ * @return string representation of type
+ */
+const gchar * process_to_str (enum process_type type);
+/*
+ * Convert string to process type
+ *
+ * @param type numeric type
+ * @return string representation of type
+ */
+enum process_type str_to_process (const gchar *str);
+
#endif
diff --git a/src/worker.c b/src/worker.c
index 80c7dc48c..d6112ff9d 100644
--- a/src/worker.c
+++ b/src/worker.c
@@ -32,6 +32,7 @@
#include "protocol.h"
#include "upstream.h"
#include "cfg_file.h"
+#include "cfg_xml.h"
#include "url.h"
#include "modules.h"
#include "message.h"
@@ -261,54 +262,54 @@ parse_line_custom (struct worker_task *task, f_str_t * in)
void
free_task (struct worker_task *task, gboolean is_soft)
{
- GList *part;
- struct mime_part *p;
+ GList *part;
+ struct mime_part *p;
- if (task)
- {
- debug_task ("free pointer %p", task);
- while ((part = g_list_first (task->parts)))
- {
- task->parts = g_list_remove_link (task->parts, part);
- p = (struct mime_part *) part->data;
- g_byte_array_free (p->content, TRUE);
- g_list_free_1 (part);
- }
- if (task->text_parts)
- {
- g_list_free (task->text_parts);
- }
- if (task->urls)
- {
- g_list_free (task->urls);
- }
- if (task->images)
- {
- g_list_free (task->images);
- }
- if (task->messages)
+ if (task)
{
- g_list_free (task->messages);
- }
- memory_pool_delete (task->task_pool);
- if (task->dispatcher)
- {
- if (is_soft)
- {
- /* Plan dispatcher shutdown */
- task->dispatcher->wanna_die = 1;
- }
- else
- {
- rspamd_remove_dispatcher (task->dispatcher);
- }
- }
- if (task->sock != -1)
- {
- close (task->sock);
+ debug_task ("free pointer %p", task);
+ while ((part = g_list_first (task->parts)))
+ {
+ task->parts = g_list_remove_link (task->parts, part);
+ p = (struct mime_part *) part->data;
+ g_byte_array_free (p->content, TRUE);
+ g_list_free_1 (part);
+ }
+ if (task->text_parts)
+ {
+ g_list_free (task->text_parts);
+ }
+ if (task->urls)
+ {
+ g_list_free (task->urls);
+ }
+ if (task->images)
+ {
+ g_list_free (task->images);
+ }
+ if (task->messages)
+ {
+ g_list_free (task->messages);
+ }
+ memory_pool_delete (task->task_pool);
+ if (task->dispatcher)
+ {
+ if (is_soft)
+ {
+ /* Plan dispatcher shutdown */
+ task->dispatcher->wanna_die = 1;
+ }
+ else
+ {
+ rspamd_remove_dispatcher (task->dispatcher);
+ }
+ }
+ if (task->sock != -1)
+ {
+ close (task->sock);
+ }
+ g_free (task);
}
- g_free (task);
- }
}
void
@@ -733,6 +734,18 @@ unload_custom_filters (struct rspamd_worker_ctx *ctx)
#endif
+gpointer
+init_worker (void)
+{
+ struct rspamd_worker_ctx *ctx;
+
+ ctx = g_malloc0 (sizeof (struct rspamd_worker_ctx));
+
+ register_worker_opt (TYPE_WORKER, "mime", xml_handle_boolean, ctx, G_STRUCT_OFFSET (struct rspamd_worker_ctx, is_mime));
+
+ return ctx;
+}
+
/*
* Start worker process
*/
@@ -740,9 +753,8 @@ void
start_worker (struct rspamd_worker *worker)
{
struct sigaction signals;
- gchar *is_mime_str;
gchar *is_custom_str;
- struct rspamd_worker_ctx *ctx;
+ struct rspamd_worker_ctx *ctx = worker->ctx;
#ifdef WITH_PROFILER
extern void _start (void), etext (void);
@@ -767,9 +779,6 @@ start_worker (struct rspamd_worker *worker)
accept_socket, (void *) worker);
event_add (&worker->bind_ev, NULL);
- /* Fill ctx */
- ctx = g_malloc0 (sizeof (struct rspamd_worker_ctx));
- worker->ctx = ctx;
#ifndef BUILD_STATIC
/* Check if this worker is not usual rspamd worker, but uses custom filters from specified path */
@@ -786,18 +795,6 @@ start_worker (struct rspamd_worker *worker)
#endif
/* Maps events */
start_map_watch ();
- /* Check whether we are mime worker */
- is_mime_str = g_hash_table_lookup (worker->cf->params, "mime");
- if (is_mime_str != NULL
- && (g_ascii_strcasecmp (is_mime_str, "no") == 0
- || g_ascii_strcasecmp (is_mime_str, "false") == 0))
- {
- ctx->is_mime = FALSE;
- }
- else
- {
- ctx->is_mime = TRUE;
- }
#ifndef BUILD_STATIC
}
#endif