diff options
140 files changed, 19213 insertions, 12158 deletions
diff --git a/src/classifiers/bayes.c b/src/classifiers/bayes.c index a8a18f5ff..8b148366d 100644 --- a/src/classifiers/bayes.c +++ b/src/classifiers/bayes.c @@ -42,56 +42,68 @@ bayes_error_quark (void) } struct bayes_statfile_data { - guint64 hits; - guint64 total_hits; - double value; - struct rspamd_statfile_config *st; - stat_file_t *file; + guint64 hits; + guint64 total_hits; + double value; + struct rspamd_statfile_config *st; + stat_file_t *file; }; struct bayes_callback_data { - statfile_pool_t *pool; - struct classifier_ctx *ctx; - gboolean in_class; - time_t now; - stat_file_t *file; - struct bayes_statfile_data *statfiles; - guint32 statfiles_num; - guint64 total_spam; - guint64 total_ham; - guint64 processed_tokens; - gsize max_tokens; - double spam_probability; - double ham_probability; + statfile_pool_t *pool; + struct classifier_ctx *ctx; + gboolean in_class; + time_t now; + stat_file_t *file; + struct bayes_statfile_data *statfiles; + guint32 statfiles_num; + guint64 total_spam; + guint64 total_ham; + guint64 processed_tokens; + gsize max_tokens; + double spam_probability; + double ham_probability; }; -static gboolean +static gboolean bayes_learn_callback (gpointer key, gpointer value, gpointer data) { - token_node_t *node = key; - struct bayes_callback_data *cd = data; - gint c; - guint64 v; + token_node_t *node = key; + struct bayes_callback_data *cd = data; + gint c; + guint64 v; c = (cd->in_class) ? 1 : -1; /* Consider that not found blocks have value 1 */ - v = statfile_pool_get_block (cd->pool, cd->file, node->h1, node->h2, cd->now); + v = + statfile_pool_get_block (cd->pool, cd->file, node->h1, node->h2, + cd->now); if (v == 0 && c > 0) { - statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, c); - cd->processed_tokens ++; + statfile_pool_set_block (cd->pool, + cd->file, + node->h1, + node->h2, + cd->now, + c); + cd->processed_tokens++; } else if (v != 0) { if (G_LIKELY (c > 0)) { - v ++; + v++; } - else if (c < 0){ + else if (c < 0) { if (v != 0) { - v --; + v--; } } - statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, v); - cd->processed_tokens ++; + statfile_pool_set_block (cd->pool, + cd->file, + node->h1, + node->h2, + cd->now, + v); + cd->processed_tokens++; } if (cd->max_tokens != 0 && cd->processed_tokens > cd->max_tokens) { @@ -133,7 +145,7 @@ inv_chi_square (gdouble value, gint freedom_deg) return 0; } sum = prob; - for (i = 1; i < freedom_deg / 2; i ++) { + for (i = 1; i < freedom_deg / 2; i++) { prob *= value / (gdouble)i; sum += prob; } @@ -148,16 +160,20 @@ static gboolean bayes_classify_callback (gpointer key, gpointer value, gpointer data) { - token_node_t *node = key; - struct bayes_callback_data *cd = data; - guint i; - struct bayes_statfile_data *cur; - guint64 spam_count = 0, ham_count = 0, total_count = 0; - double spam_prob, spam_freq, ham_freq, bayes_spam_prob; + token_node_t *node = key; + struct bayes_callback_data *cd = data; + guint i; + struct bayes_statfile_data *cur; + guint64 spam_count = 0, ham_count = 0, total_count = 0; + double spam_prob, spam_freq, ham_freq, bayes_spam_prob; - for (i = 0; i < cd->statfiles_num; i ++) { + for (i = 0; i < cd->statfiles_num; i++) { cur = &cd->statfiles[i]; - cur->value = statfile_pool_get_block (cd->pool, cur->file, node->h1, node->h2, cd->now); + cur->value = statfile_pool_get_block (cd->pool, + cur->file, + node->h1, + node->h2, + cd->now); if (cur->value > 0) { cur->total_hits += cur->value; if (cur->st->is_spam) { @@ -178,7 +194,7 @@ bayes_classify_callback (gpointer key, gpointer value, gpointer data) bayes_spam_prob = (0.5 + spam_prob * total_count) / (1. + total_count); cd->spam_probability += log (bayes_spam_prob); cd->ham_probability += log (1. - bayes_spam_prob); - cd->processed_tokens ++; + cd->processed_tokens++; } if (cd->max_tokens != 0 && cd->processed_tokens > cd->max_tokens) { @@ -189,10 +205,11 @@ bayes_classify_callback (gpointer key, gpointer value, gpointer data) return FALSE; } -struct classifier_ctx* +struct classifier_ctx * bayes_init (rspamd_mempool_t *pool, struct rspamd_classifier_config *cfg) { - struct classifier_ctx *ctx = rspamd_mempool_alloc (pool, sizeof (struct classifier_ctx)); + struct classifier_ctx *ctx = + rspamd_mempool_alloc (pool, sizeof (struct classifier_ctx)); ctx->pool = pool; ctx->cfg = cfg; @@ -202,23 +219,28 @@ bayes_init (rspamd_mempool_t *pool, struct rspamd_classifier_config *cfg) } gboolean -bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, struct rspamd_task *task, lua_State *L) +bayes_classify (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task, + lua_State *L) { - struct bayes_callback_data data; - gchar *value; - gint nodes, i = 0, selected_st = -1, cnt; - gint minnodes; - guint64 maxhits = 0, rev; - double final_prob, h, s; - struct rspamd_statfile_config *st; - stat_file_t *file; - GList *cur; - char *sumbuf; + struct bayes_callback_data data; + gchar *value; + gint nodes, i = 0, selected_st = -1, cnt; + gint minnodes; + guint64 maxhits = 0, rev; + double final_prob, h, s; + struct rspamd_statfile_config *st; + stat_file_t *file; + GList *cur; + char *sumbuf; g_assert (pool != NULL); g_assert (ctx != NULL); - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { + if (ctx->cfg->opts && + (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { minnodes = strtol (value, NULL, 10); nodes = g_tree_nnodes (input); if (nodes > FEATURE_WINDOW_SIZE) { @@ -231,7 +253,8 @@ bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, cur = call_classifier_pre_callbacks (ctx->cfg, task, FALSE, FALSE, L); if (cur) { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, cur); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, cur); } else { cur = ctx->cfg->statfiles; @@ -248,7 +271,8 @@ bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, data.ham_probability = 0; data.total_ham = 0; data.total_spam = 0; - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "max_tokens")) != NULL) { + if (ctx->cfg->opts && + (value = g_hash_table_lookup (ctx->cfg->opts, "max_tokens")) != NULL) { minnodes = rspamd_config_parse_limit (value, -1); data.max_tokens = minnodes; } @@ -260,10 +284,11 @@ bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, /* Select statfile to classify */ st = cur->data; if ((file = statfile_pool_is_open (pool, st->path)) == NULL) { - if ((file = statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { + if ((file = + statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { msg_warn ("cannot open %s", st->path); cur = g_list_next (cur); - data.statfiles_num --; + data.statfiles_num--; continue; } } @@ -278,7 +303,7 @@ bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, } cur = g_list_next (cur); - i ++; + i++; } cnt = i; @@ -289,17 +314,19 @@ bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, final_prob = 0; } else { - h = 1 - inv_chi_square (-2. * data.spam_probability, 2 * data.processed_tokens); - s = 1 - inv_chi_square (-2. * data.ham_probability, 2 * data.processed_tokens); + h = 1 - inv_chi_square (-2. * data.spam_probability, + 2 * data.processed_tokens); + s = 1 - inv_chi_square (-2. * data.ham_probability, + 2 * data.processed_tokens); final_prob = (s + 1 - h) / 2.; } if (data.processed_tokens > 0 && fabs (final_prob - 0.5) > 0.05) { sumbuf = rspamd_mempool_alloc (task->task_pool, 32); - for (i = 0; i < cnt; i ++) { + for (i = 0; i < cnt; i++) { if ((final_prob > 0.5 && !data.statfiles[i].st->is_spam) || - (final_prob < 0.5 && data.statfiles[i].st->is_spam)) { + (final_prob < 0.5 && data.statfiles[i].st->is_spam)) { continue; } if (data.statfiles[i].total_hits > maxhits) { @@ -308,7 +335,8 @@ bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, } } if (selected_st == -1) { - msg_err ("unexpected classifier error: cannot select desired statfile"); + msg_err ( + "unexpected classifier error: cannot select desired statfile"); } else { /* Calculate ham probability correctly */ @@ -317,7 +345,10 @@ bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, } rspamd_snprintf (sumbuf, 32, "%.2f%%", final_prob * 100.); cur = g_list_prepend (NULL, sumbuf); - insert_result (task, data.statfiles[selected_st].st->symbol, final_prob, cur); + insert_result (task, + data.statfiles[selected_st].st->symbol, + final_prob, + cur); } } @@ -327,34 +358,44 @@ bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, } gboolean -bayes_learn (struct classifier_ctx* ctx, statfile_pool_t *pool, const char *symbol, GTree *input, - gboolean in_class, double *sum, double multiplier, GError **err) +bayes_learn (struct classifier_ctx * ctx, + statfile_pool_t *pool, + const char *symbol, + GTree *input, + gboolean in_class, + double *sum, + double multiplier, + GError **err) { - struct bayes_callback_data data; - gchar *value; - gint nodes; - gint minnodes; - struct rspamd_statfile_config *st, *sel_st = NULL; - stat_file_t *to_learn; - GList *cur; + struct bayes_callback_data data; + gchar *value; + gint nodes; + gint minnodes; + struct rspamd_statfile_config *st, *sel_st = NULL; + stat_file_t *to_learn; + GList *cur; g_assert (pool != NULL); g_assert (ctx != NULL); - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { + if (ctx->cfg->opts && + (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { minnodes = strtol (value, NULL, 10); nodes = g_tree_nnodes (input); if (nodes > FEATURE_WINDOW_SIZE) { nodes = nodes / FEATURE_WINDOW_SIZE + FEATURE_WINDOW_SIZE; } if (nodes < minnodes) { - msg_info ("do not learn message as it has too few tokens: %d, while %d min", nodes, minnodes); + msg_info ( + "do not learn message as it has too few tokens: %d, while %d min", + nodes, + minnodes); *sum = 0; g_set_error (err, - bayes_error_quark(), /* error domain */ - 1, /* error code */ - "message contains too few tokens: %d, while min is %d", - nodes, (int)minnodes); + bayes_error_quark (), /* error domain */ + 1, /* error code */ + "message contains too few tokens: %d, while min is %d", + nodes, (int)minnodes); return FALSE; } } @@ -365,7 +406,8 @@ bayes_learn (struct classifier_ctx* ctx, statfile_pool_t *pool, const char *symb data.ctx = ctx; data.processed_tokens = 0; data.processed_tokens = 0; - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "max_tokens")) != NULL) { + if (ctx->cfg->opts && + (value = g_hash_table_lookup (ctx->cfg->opts, "max_tokens")) != NULL) { minnodes = rspamd_config_parse_limit (value, -1); data.max_tokens = minnodes; } @@ -384,31 +426,36 @@ bayes_learn (struct classifier_ctx* ctx, statfile_pool_t *pool, const char *symb } if (sel_st == NULL) { g_set_error (err, - bayes_error_quark(), /* error domain */ - 1, /* error code */ - "cannot find statfile for symbol: %s", - symbol); + bayes_error_quark (), /* error domain */ + 1, /* error code */ + "cannot find statfile for symbol: %s", + symbol); return FALSE; } if ((to_learn = statfile_pool_is_open (pool, sel_st->path)) == NULL) { - if ((to_learn = statfile_pool_open (pool, sel_st->path, sel_st->size, FALSE)) == NULL) { + if ((to_learn = + statfile_pool_open (pool, sel_st->path, sel_st->size, + FALSE)) == NULL) { msg_warn ("cannot open %s", sel_st->path); if (statfile_pool_create (pool, sel_st->path, sel_st->size) == -1) { msg_err ("cannot create statfile %s", sel_st->path); g_set_error (err, - bayes_error_quark(), /* error domain */ - 1, /* error code */ - "cannot create statfile: %s", - sel_st->path); + bayes_error_quark (), /* error domain */ + 1, /* error code */ + "cannot create statfile: %s", + sel_st->path); return FALSE; } - if ((to_learn = statfile_pool_open (pool, sel_st->path, sel_st->size, FALSE)) == NULL) { + if ((to_learn = + statfile_pool_open (pool, sel_st->path, sel_st->size, + FALSE)) == NULL) { g_set_error (err, - bayes_error_quark(), /* error domain */ - 1, /* error code */ - "cannot open statfile %s after creation", - sel_st->path); - msg_err ("cannot open statfile %s after creation", sel_st->path); + bayes_error_quark (), /* error domain */ + 1, /* error code */ + "cannot open statfile %s after creation", + sel_st->path); + msg_err ("cannot open statfile %s after creation", + sel_st->path); return FALSE; } } @@ -427,22 +474,28 @@ bayes_learn (struct classifier_ctx* ctx, statfile_pool_t *pool, const char *symb } gboolean -bayes_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, - GTree *input, struct rspamd_task *task, gboolean is_spam, lua_State *L, GError **err) +bayes_learn_spam (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task, + gboolean is_spam, + lua_State *L, + GError **err) { - struct bayes_callback_data data; - gchar *value; - gint nodes; - gint minnodes; - struct rspamd_statfile_config *st; - stat_file_t *file; - GList *cur; - gboolean skip_labels; + struct bayes_callback_data data; + gchar *value; + gint nodes; + gint minnodes; + struct rspamd_statfile_config *st; + stat_file_t *file; + GList *cur; + gboolean skip_labels; g_assert (pool != NULL); g_assert (ctx != NULL); - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { + if (ctx->cfg->opts && + (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { minnodes = strtol (value, NULL, 10); nodes = g_tree_nnodes (input); if (nodes > FEATURE_WINDOW_SIZE) { @@ -450,10 +503,10 @@ bayes_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, } if (nodes < minnodes) { g_set_error (err, - bayes_error_quark(), /* error domain */ - 1, /* error code */ - "message contains too few tokens: %d, while min is %d", - nodes, (int)minnodes); + bayes_error_quark (), /* error domain */ + 1, /* error code */ + "message contains too few tokens: %d, while min is %d", + nodes, (int)minnodes); return FALSE; } } @@ -461,7 +514,8 @@ bayes_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, cur = call_classifier_pre_callbacks (ctx->cfg, task, TRUE, is_spam, L); if (cur) { skip_labels = FALSE; - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, cur); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, cur); } else { /* Do not try to learn specific statfiles if pre callback returned nil */ @@ -475,7 +529,8 @@ bayes_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, data.in_class = TRUE; data.processed_tokens = 0; - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "max_tokens")) != NULL) { + if (ctx->cfg->opts && + (value = g_hash_table_lookup (ctx->cfg->opts, "max_tokens")) != NULL) { minnodes = rspamd_config_parse_limit (value, -1); data.max_tokens = minnodes; } @@ -491,24 +546,28 @@ bayes_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, continue; } if ((file = statfile_pool_is_open (pool, st->path)) == NULL) { - if ((file = statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { + if ((file = + statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { msg_warn ("cannot open %s", st->path); if (statfile_pool_create (pool, st->path, st->size) == -1) { msg_err ("cannot create statfile %s", st->path); g_set_error (err, - bayes_error_quark(), /* error domain */ - 1, /* error code */ - "cannot create statfile: %s", - st->path); + bayes_error_quark (), /* error domain */ + 1, /* error code */ + "cannot create statfile: %s", + st->path); return FALSE; } - if ((file = statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { + if ((file = + statfile_pool_open (pool, st->path, st->size, + FALSE)) == NULL) { g_set_error (err, - bayes_error_quark(), /* error domain */ - 1, /* error code */ - "cannot open statfile %s after creation", - st->path); - msg_err ("cannot open statfile %s after creation", st->path); + bayes_error_quark (), /* error domain */ + 1, /* error code */ + "cannot open statfile %s after creation", + st->path); + msg_err ("cannot open statfile %s after creation", + st->path); return FALSE; } } @@ -528,7 +587,10 @@ bayes_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, } GList * -bayes_weights (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, struct rspamd_task *task) +bayes_weights (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task) { /* This function is unimplemented with new normalizer */ return NULL; diff --git a/src/classifiers/classifiers.c b/src/classifiers/classifiers.c index fb294379c..95dd52c44 100644 --- a/src/classifiers/classifiers.c +++ b/src/classifiers/classifiers.c @@ -28,29 +28,29 @@ #include "classifiers.h" -struct classifier classifiers[] = { - { - .name = "winnow", - .init_func = winnow_init, - .classify_func = winnow_classify, - .learn_func = winnow_learn, - .learn_spam_func = winnow_learn_spam, - .weights_func = winnow_weights - }, - { - .name = "bayes", - .init_func = bayes_init, - .classify_func = bayes_classify, - .learn_func = bayes_learn, - .learn_spam_func = bayes_learn_spam, - .weights_func = bayes_weights - } +struct classifier classifiers[] = { + { + .name = "winnow", + .init_func = winnow_init, + .classify_func = winnow_classify, + .learn_func = winnow_learn, + .learn_spam_func = winnow_learn_spam, + .weights_func = winnow_weights + }, + { + .name = "bayes", + .init_func = bayes_init, + .classify_func = bayes_classify, + .learn_func = bayes_learn, + .learn_spam_func = bayes_learn_spam, + .weights_func = bayes_weights + } }; -struct classifier * +struct classifier * get_classifier (const char *name) { - guint i; + guint i; for (i = 0; i < sizeof (classifiers) / sizeof (classifiers[0]); i++) { if (strcmp (classifiers[i].name, name) == 0) { diff --git a/src/classifiers/classifiers.h b/src/classifiers/classifiers.h index 2b36d8c02..8e59fc555 100644 --- a/src/classifiers/classifiers.h +++ b/src/classifiers/classifiers.h @@ -28,36 +28,80 @@ struct classify_weight { /* Common classifier structure */ struct classifier { char *name; - struct classifier_ctx* (*init_func)(rspamd_mempool_t *pool, struct rspamd_classifier_config *cf); - gboolean (*classify_func)(struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, struct rspamd_task *task, lua_State *L); - gboolean (*learn_func)(struct classifier_ctx* ctx, statfile_pool_t *pool, - const char *symbol, GTree *input, gboolean in_class, - double *sum, double multiplier, GError **err); - gboolean (*learn_spam_func)(struct classifier_ctx* ctx, statfile_pool_t *pool, - GTree *input, struct rspamd_task *task, gboolean is_spam, lua_State *L, GError **err); - GList* (*weights_func)(struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, struct rspamd_task *task); + struct classifier_ctx * (*init_func)(rspamd_mempool_t *pool, + struct rspamd_classifier_config *cf); + gboolean (*classify_func)(struct classifier_ctx * ctx, + statfile_pool_t *pool, GTree *input, struct rspamd_task *task, + lua_State *L); + gboolean (*learn_func)(struct classifier_ctx * ctx, statfile_pool_t *pool, + const char *symbol, GTree *input, gboolean in_class, + double *sum, double multiplier, GError **err); + gboolean (*learn_spam_func)(struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, struct rspamd_task *task, gboolean is_spam, lua_State *L, + GError **err); + GList * (*weights_func)(struct classifier_ctx * ctx, statfile_pool_t *pool, + GTree *input, struct rspamd_task *task); }; /* Get classifier structure by name or return NULL if this name is not found */ -struct classifier* get_classifier (const char *name); +struct classifier * get_classifier (const char *name); /* Winnow algorithm */ -struct classifier_ctx* winnow_init (rspamd_mempool_t *pool, struct rspamd_classifier_config *cf); -gboolean winnow_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, struct rspamd_task *task, lua_State *L); -gboolean winnow_learn (struct classifier_ctx* ctx, statfile_pool_t *pool, const char *symbol, GTree *input, - gboolean in_class, double *sum, double multiplier, GError **err); -gboolean winnow_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, - GTree *input, struct rspamd_task *task, gboolean is_spam, lua_State *L, GError **err); -GList *winnow_weights (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, struct rspamd_task *task); +struct classifier_ctx * winnow_init (rspamd_mempool_t *pool, + struct rspamd_classifier_config *cf); +gboolean winnow_classify (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task, + lua_State *L); +gboolean winnow_learn (struct classifier_ctx * ctx, + statfile_pool_t *pool, + const char *symbol, + GTree *input, + gboolean in_class, + double *sum, + double multiplier, + GError **err); +gboolean winnow_learn_spam (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task, + gboolean is_spam, + lua_State *L, + GError **err); +GList * winnow_weights (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task); /* Bayes algorithm */ -struct classifier_ctx* bayes_init (rspamd_mempool_t *pool, struct rspamd_classifier_config *cf); -gboolean bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, struct rspamd_task *task, lua_State *L); -gboolean bayes_learn (struct classifier_ctx* ctx, statfile_pool_t *pool, const char *symbol, GTree *input, - gboolean in_class, double *sum, double multiplier, GError **err); -gboolean bayes_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, - GTree *input, struct rspamd_task *task, gboolean is_spam, lua_State *L, GError **err); -GList *bayes_weights (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, struct rspamd_task *task); +struct classifier_ctx * bayes_init (rspamd_mempool_t *pool, + struct rspamd_classifier_config *cf); +gboolean bayes_classify (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task, + lua_State *L); +gboolean bayes_learn (struct classifier_ctx * ctx, + statfile_pool_t *pool, + const char *symbol, + GTree *input, + gboolean in_class, + double *sum, + double multiplier, + GError **err); +gboolean bayes_learn_spam (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task, + gboolean is_spam, + lua_State *L, + GError **err); +GList * bayes_weights (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task); /* Array of all defined classifiers */ extern struct classifier classifiers[]; diff --git a/src/classifiers/winnow.c b/src/classifiers/winnow.c index 1fe8f16d2..d6f374f8f 100644 --- a/src/classifiers/winnow.c +++ b/src/classifiers/winnow.c @@ -51,40 +51,42 @@ winnow_error_quark (void) } struct winnow_callback_data { - statfile_pool_t *pool; - struct classifier_ctx *ctx; - stat_file_t *file; - stat_file_t *learn_file; - long double sum; - long double start; - double multiplier; - guint32 count; - guint32 new_blocks; - gboolean in_class; - gboolean do_demote; - gboolean fresh_run; - time_t now; + statfile_pool_t *pool; + struct classifier_ctx *ctx; + stat_file_t *file; + stat_file_t *learn_file; + long double sum; + long double start; + double multiplier; + guint32 count; + guint32 new_blocks; + gboolean in_class; + gboolean do_demote; + gboolean fresh_run; + time_t now; }; static const double max_common_weight = MAX_WEIGHT * WINNOW_DEMOTION; -static gboolean +static gboolean winnow_classify_callback (gpointer key, gpointer value, gpointer data) { - token_node_t *node = key; - struct winnow_callback_data *cd = data; - double v; + token_node_t *node = key; + struct winnow_callback_data *cd = data; + double v; /* Consider that not found blocks have value 1 */ - v = statfile_pool_get_block (cd->pool, cd->file, node->h1, node->h2, cd->now); + v = + statfile_pool_get_block (cd->pool, cd->file, node->h1, node->h2, + cd->now); if (fabs (v) > ALPHA) { cd->sum += v; } else { cd->sum += 1.0; - cd->new_blocks ++; + cd->new_blocks++; } cd->count++; @@ -92,24 +94,32 @@ winnow_classify_callback (gpointer key, gpointer value, gpointer data) return FALSE; } -static gboolean +static gboolean winnow_learn_callback (gpointer key, gpointer value, gpointer data) { - token_node_t *node = key; - struct winnow_callback_data *cd = data; - double v, c; - - c = (cd->in_class) ? WINNOW_PROMOTION * cd->multiplier : WINNOW_DEMOTION / cd->multiplier; + token_node_t *node = key; + struct winnow_callback_data *cd = data; + double v, c; + + c = (cd->in_class) ? WINNOW_PROMOTION * cd->multiplier : WINNOW_DEMOTION / + cd->multiplier; /* Consider that not found blocks have value 1 */ - v = statfile_pool_get_block (cd->pool, cd->file, node->h1, node->h2, cd->now); + v = + statfile_pool_get_block (cd->pool, cd->file, node->h1, node->h2, + cd->now); if (fabs (v) < ALPHA) { /* Block not found, insert new */ cd->start += 1; if (cd->file == cd->learn_file) { - statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, c); + statfile_pool_set_block (cd->pool, + cd->file, + node->h1, + node->h2, + cd->now, + c); node->value = c; - cd->new_blocks ++; + cd->new_blocks++; } } else { @@ -119,18 +129,23 @@ winnow_learn_callback (gpointer key, gpointer value, gpointer data) node->extra = 0; } else { - node->extra ++; + node->extra++; } node->value = v; - + if (node->extra > 1) { - /* + /* * Assume that this node is common for several statfiles, so * decrease its weight proportianally */ if (node->value > max_common_weight) { /* Static fluctuation */ - statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, 0.); + statfile_pool_set_block (cd->pool, + cd->file, + node->h1, + node->h2, + cd->now, + 0.); node->value = 0.; } else if (node->value > WINNOW_PROMOTION * cd->multiplier) { @@ -141,7 +156,7 @@ winnow_learn_callback (gpointer key, gpointer value, gpointer data) node->value *= c; } else { - /* + /* * Too high token value that exists also in other * statfiles, may be statistic error, so decrease it * slightly @@ -152,8 +167,13 @@ winnow_learn_callback (gpointer key, gpointer value, gpointer data) else { node->value = WINNOW_DEMOTION / cd->multiplier; } - statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, node->value); - } + statfile_pool_set_block (cd->pool, + cd->file, + node->h1, + node->h2, + cd->now, + node->value); + } } else if (cd->file == cd->learn_file) { /* New block or block that is in only one statfile */ @@ -164,12 +184,22 @@ winnow_learn_callback (gpointer key, gpointer value, gpointer data) else { node->value *= c; } - statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, node->value); + statfile_pool_set_block (cd->pool, + cd->file, + node->h1, + node->h2, + cd->now, + node->value); } else if (cd->do_demote) { /* Demote blocks in file */ node->value *= WINNOW_DEMOTION / cd->multiplier; - statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, node->value); + statfile_pool_set_block (cd->pool, + cd->file, + node->h1, + node->h2, + cd->now, + node->value); } } @@ -181,10 +211,11 @@ winnow_learn_callback (gpointer key, gpointer value, gpointer data) return FALSE; } -struct classifier_ctx * +struct classifier_ctx * winnow_init (rspamd_mempool_t * pool, struct rspamd_classifier_config *cfg) { - struct classifier_ctx *ctx = rspamd_mempool_alloc (pool, sizeof (struct classifier_ctx)); + struct classifier_ctx *ctx = + rspamd_mempool_alloc (pool, sizeof (struct classifier_ctx)); ctx->pool = pool; ctx->cfg = cfg; @@ -193,14 +224,18 @@ winnow_init (rspamd_mempool_t * pool, struct rspamd_classifier_config *cfg) } gboolean -winnow_classify (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * input, struct rspamd_task *task, lua_State *L) +winnow_classify (struct classifier_ctx *ctx, + statfile_pool_t * pool, + GTree * input, + struct rspamd_task *task, + lua_State *L) { - struct winnow_callback_data data; - char *sumbuf, *value; - long double res = 0., max = 0.; - GList *cur; - struct rspamd_statfile_config *st, *sel = NULL; - int nodes, minnodes; + struct winnow_callback_data data; + char *sumbuf, *value; + long double res = 0., max = 0.; + GList *cur; + struct rspamd_statfile_config *st, *sel = NULL; + int nodes, minnodes; g_assert (pool != NULL); g_assert (ctx != NULL); @@ -208,22 +243,27 @@ winnow_classify (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * inp data.pool = pool; data.now = time (NULL); data.ctx = ctx; - - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { + + if (ctx->cfg->opts && + (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { minnodes = strtol (value, NULL, 10); nodes = g_tree_nnodes (input); if (nodes > FEATURE_WINDOW_SIZE) { nodes = nodes / FEATURE_WINDOW_SIZE + FEATURE_WINDOW_SIZE; } if (nodes < minnodes) { - msg_info ("do not classify message as it has too few tokens: %d, while %d min", nodes, minnodes); + msg_info ( + "do not classify message as it has too few tokens: %d, while %d min", + nodes, + minnodes); return FALSE; } } cur = call_classifier_pre_callbacks (ctx->cfg, task, FALSE, FALSE, L); if (cur) { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, cur); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, cur); } else { cur = ctx->cfg->statfiles; @@ -235,7 +275,8 @@ winnow_classify (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * inp data.count = 0; data.new_blocks = 0; if ((data.file = statfile_pool_is_open (pool, st->path)) == NULL) { - if ((data.file = statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { + if ((data.file = + statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { msg_warn ("cannot open %s, skip it", st->path); cur = g_list_next (cur); continue; @@ -261,16 +302,16 @@ winnow_classify (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * inp if (sel != NULL) { #ifdef WITH_LUA - max = call_classifier_post_callbacks (ctx->cfg, task, max, L); + max = call_classifier_post_callbacks (ctx->cfg, task, max, L); #endif #ifdef HAVE_TANHL - max = tanhl (max); + max = tanhl (max); #else - /* - * As some implementations of libm does not support tanhl, try to use - * tanh - */ - max = tanh ((double) max); + /* + * As some implementations of libm does not support tanhl, try to use + * tanh + */ + max = tanh ((double) max); #endif sumbuf = rspamd_mempool_alloc (task->task_pool, 32); rspamd_snprintf (sumbuf, 32, "%.2F", max); @@ -282,15 +323,18 @@ winnow_classify (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * inp } GList * -winnow_weights (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * input, struct rspamd_task *task) +winnow_weights (struct classifier_ctx *ctx, + statfile_pool_t * pool, + GTree * input, + struct rspamd_task *task) { - struct winnow_callback_data data; - long double res = 0.; - GList *cur, *resl = NULL; - struct rspamd_statfile_config *st; - struct classify_weight *w; - char *value; - int nodes, minnodes; + struct winnow_callback_data data; + long double res = 0.; + GList *cur, *resl = NULL; + struct rspamd_statfile_config *st; + struct classify_weight *w; + char *value; + int nodes, minnodes; g_assert (pool != NULL); g_assert (ctx != NULL); @@ -299,25 +343,30 @@ winnow_weights (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * inpu data.now = time (NULL); data.ctx = ctx; - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { + if (ctx->cfg->opts && + (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { minnodes = strtol (value, NULL, 10); nodes = g_tree_nnodes (input); if (nodes > FEATURE_WINDOW_SIZE) { nodes = nodes / FEATURE_WINDOW_SIZE + FEATURE_WINDOW_SIZE; } if (nodes < minnodes) { - msg_info ("do not classify message as it has too few tokens: %d, while %d min", nodes, minnodes); + msg_info ( + "do not classify message as it has too few tokens: %d, while %d min", + nodes, + minnodes); return NULL; } } - + cur = ctx->cfg->statfiles; while (cur) { st = cur->data; data.sum = 0; data.count = 0; if ((data.file = statfile_pool_is_open (pool, st->path)) == NULL) { - if ((data.file = statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { + if ((data.file = + statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { msg_warn ("cannot open %s, skip it", st->path); cur = g_list_next (cur); continue; @@ -328,7 +377,9 @@ winnow_weights (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * inpu g_tree_foreach (input, winnow_classify_callback, &data); } - w = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct classify_weight)); + w = + rspamd_mempool_alloc0 (task->task_pool, + sizeof (struct classify_weight)); if (data.count != 0) { res = data.sum / (double)data.count; } @@ -340,9 +391,10 @@ winnow_weights (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * inpu resl = g_list_prepend (resl, w); cur = g_list_next (cur); } - + if (resl != NULL) { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, resl); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, resl); } return resl; @@ -351,21 +403,27 @@ winnow_weights (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * inpu gboolean -winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, const char *symbol, - GTree * input, int in_class, double *sum, double multiplier, GError **err) +winnow_learn (struct classifier_ctx *ctx, + statfile_pool_t *pool, + const char *symbol, + GTree * input, + int in_class, + double *sum, + double multiplier, + GError **err) { - struct winnow_callback_data data = { + struct winnow_callback_data data = { .file = NULL, .multiplier = multiplier }; - char *value; - int nodes, minnodes, iterations = 0; - struct rspamd_statfile_config *st, *sel_st = NULL; - stat_file_t *sel = NULL, *to_learn; - long double res = 0., max = 0., start_value = 0., end_value = 0.; - double learn_threshold = 0.0; - GList *cur, *to_demote = NULL; - gboolean force_learn = FALSE; + char *value; + int nodes, minnodes, iterations = 0; + struct rspamd_statfile_config *st, *sel_st = NULL; + stat_file_t *sel = NULL, *to_learn; + long double res = 0., max = 0., start_value = 0., end_value = 0.; + double learn_threshold = 0.0; + GList *cur, *to_demote = NULL; + gboolean force_learn = FALSE; g_assert (pool != NULL); g_assert (ctx != NULL); @@ -376,29 +434,35 @@ winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, const char *sym data.ctx = ctx; - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { + if (ctx->cfg->opts && + (value = g_hash_table_lookup (ctx->cfg->opts, "min_tokens")) != NULL) { minnodes = strtol (value, NULL, 10); nodes = g_tree_nnodes (input); if (nodes > FEATURE_WINDOW_SIZE) { nodes = nodes / FEATURE_WINDOW_SIZE + FEATURE_WINDOW_SIZE; } if (nodes < minnodes) { - msg_info ("do not learn message as it has too few tokens: %d, while %d min", nodes, minnodes); + msg_info ( + "do not learn message as it has too few tokens: %d, while %d min", + nodes, + minnodes); if (sum != NULL) { *sum = 0; } g_set_error (err, - winnow_error_quark(), /* error domain */ - 1, /* error code */ - "message contains too few tokens: %d, while min is %d", - nodes, minnodes); + winnow_error_quark (), /* error domain */ + 1, /* error code */ + "message contains too few tokens: %d, while min is %d", + nodes, minnodes); return FALSE; } } - if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "learn_threshold")) != NULL) { + if (ctx->cfg->opts && + (value = + g_hash_table_lookup (ctx->cfg->opts, "learn_threshold")) != NULL) { learn_threshold = strtod (value, NULL); } - + if (learn_threshold <= 1.0 && learn_threshold >= 0) { /* Classify message and check target statfile score */ cur = ctx->cfg->statfiles; @@ -406,24 +470,27 @@ winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, const char *sym /* Open or create all statfiles inside classifier */ st = cur->data; if (statfile_pool_is_open (pool, st->path) == NULL) { - if (statfile_pool_open (pool, st->path, st->size, FALSE) == NULL) { + if (statfile_pool_open (pool, st->path, st->size, + FALSE) == NULL) { msg_warn ("cannot open %s", st->path); if (statfile_pool_create (pool, st->path, st->size) == -1) { msg_err ("cannot create statfile %s", st->path); g_set_error (err, - winnow_error_quark(), /* error domain */ - 1, /* error code */ - "cannot create statfile: %s", - st->path); + winnow_error_quark (), /* error domain */ + 1, /* error code */ + "cannot create statfile: %s", + st->path); return FALSE; } - if (statfile_pool_open (pool, st->path, st->size, FALSE) == NULL) { + if (statfile_pool_open (pool, st->path, st->size, + FALSE) == NULL) { g_set_error (err, - winnow_error_quark(), /* error domain */ - 1, /* error code */ - "open statfile %s after creation", - st->path); - msg_err ("cannot open statfile %s after creation", st->path); + winnow_error_quark (), /* error domain */ + 1, /* error code */ + "open statfile %s after creation", + st->path); + msg_err ("cannot open statfile %s after creation", + st->path); return FALSE; } } @@ -437,10 +504,10 @@ winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, const char *sym if (sel_st == NULL) { g_set_error (err, - winnow_error_quark(), /* error domain */ - 1, /* error code */ - "cannot find statfile for symbol %s", - symbol); + winnow_error_quark (), /* error domain */ + 1, /* error code */ + "cannot find statfile for symbol %s", + symbol); msg_err ("cannot find statfile for symbol %s", symbol); return FALSE; } @@ -448,10 +515,10 @@ winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, const char *sym to_learn = statfile_pool_is_open (pool, sel_st->path); if (to_learn == NULL) { g_set_error (err, - winnow_error_quark(), /* error domain */ - 1, /* error code */ - "statfile %s is not opened this maybe if your statfile pool is too small to handle all statfiles", - sel_st->path); + winnow_error_quark (), /* error domain */ + 1, /* error code */ + "statfile %s is not opened this maybe if your statfile pool is too small to handle all statfiles", + sel_st->path); return FALSE; } /* Check target statfile */ @@ -477,10 +544,10 @@ winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, const char *sym data.count = 0; if ((data.file = statfile_pool_is_open (pool, st->path)) == NULL) { g_set_error (err, - winnow_error_quark(), /* error domain */ - 1, /* error code */ - "statfile %s is not opened this maybe if your statfile pool is too small to handle all statfiles", - st->path); + winnow_error_quark (), /* error domain */ + 1, /* error code */ + "statfile %s is not opened this maybe if your statfile pool is too small to handle all statfiles", + st->path); return FALSE; } g_tree_foreach (input, winnow_classify_callback, &data); @@ -498,18 +565,22 @@ winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, const char *sym } } else { - msg_err ("learn threshold is more than 1 or less than 0, so cannot do learn, please check your configuration"); + msg_err ( + "learn threshold is more than 1 or less than 0, so cannot do learn, please check your configuration"); g_set_error (err, - winnow_error_quark(), /* error domain */ - 1, /* error code */ - "bad learn_threshold setting: %.2f", - learn_threshold); + winnow_error_quark (), /* error domain */ + 1, /* error code */ + "bad learn_threshold setting: %.2f", + learn_threshold); return FALSE; } /* If to_demote list is empty this message is already classified correctly */ if (max > WINNOW_PROMOTION && to_demote == NULL && !force_learn) { - msg_info ("this message is already of class %s with threshold %.2f and weight %.2F", - sel_st->symbol, learn_threshold, max); + msg_info ( + "this message is already of class %s with threshold %.2f and weight %.2F", + sel_st->symbol, + learn_threshold, + max); goto end; } data.learn_file = to_learn; @@ -526,7 +597,8 @@ winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, const char *sym if ((data.file = statfile_pool_is_open (pool, st->path)) == NULL) { return FALSE; } - if (to_demote != NULL && g_list_find (to_demote, data.file) != NULL) { + if (to_demote != NULL && + g_list_find (to_demote, data.file) != NULL) { data.do_demote = TRUE; } else { @@ -557,48 +629,66 @@ winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, const char *sym } data.multiplier *= WINNOW_PROMOTION; - msg_info ("learn iteration %d for statfile %s: %G -> %G, multiplier: %.2f", iterations + 1, symbol, - start_value, end_value, data.multiplier); - } while ((in_class ? sel != to_learn : sel == to_learn) && iterations ++ < MAX_LEARN_ITERATIONS); - + msg_info ( + "learn iteration %d for statfile %s: %G -> %G, multiplier: %.2f", + iterations + 1, + symbol, + start_value, + end_value, + data.multiplier); + } while ((in_class ? sel != to_learn : sel == + to_learn) && iterations++ < MAX_LEARN_ITERATIONS); + if (iterations >= MAX_LEARN_ITERATIONS) { - msg_warn ("learning statfile %s was not fully successfull: iterations count is limited to %d, final sum is %G", - sel_st->symbol, MAX_LEARN_ITERATIONS, max); + msg_warn ( + "learning statfile %s was not fully successfull: iterations count is limited to %d, final sum is %G", + sel_st->symbol, + MAX_LEARN_ITERATIONS, + max); g_set_error (err, - winnow_error_quark(), /* error domain */ - 1, /* error code */ - "learning statfile %s was not fully successfull: iterations count is limited to %d", - sel_st->symbol, MAX_LEARN_ITERATIONS); + winnow_error_quark (), /* error domain */ + 1, /* error code */ + "learning statfile %s was not fully successfull: iterations count is limited to %d", + sel_st->symbol, MAX_LEARN_ITERATIONS); return FALSE; } else { - msg_info ("learned statfile %s successfully with %d iterations and sum %G", sel_st->symbol, iterations + 1, max); + msg_info ( + "learned statfile %s successfully with %d iterations and sum %G", + sel_st->symbol, + iterations + 1, + max); } end: if (sum) { #ifdef HAVE_TANHL - *sum = (double)tanhl (max); + *sum = (double)tanhl (max); #else - /* - * As some implementations of libm does not support tanhl, try to use - * tanh - */ - *sum = tanh ((double) max); + /* + * As some implementations of libm does not support tanhl, try to use + * tanh + */ + *sum = tanh ((double) max); #endif } return TRUE; } gboolean -winnow_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, - GTree *input, struct rspamd_task *task, gboolean is_spam, lua_State *L, GError **err) +winnow_learn_spam (struct classifier_ctx * ctx, + statfile_pool_t *pool, + GTree *input, + struct rspamd_task *task, + gboolean is_spam, + lua_State *L, + GError **err) { g_set_error (err, - winnow_error_quark(), /* error domain */ - 1, /* error code */ - "learn spam is not supported for winnow" - ); + winnow_error_quark (), /* error domain */ + 1, /* error code */ + "learn spam is not supported for winnow" + ); return FALSE; } diff --git a/src/client/rspamc.c b/src/client/rspamc.c index e526850c4..9db789005 100644 --- a/src/client/rspamc.c +++ b/src/client/rspamc.c @@ -31,53 +31,74 @@ #define DEFAULT_PORT 11333 #define DEFAULT_CONTROL_PORT 11334 -static gchar *connect_str = "localhost"; -static gchar *password = NULL; -static gchar *ip = NULL; -static gchar *from = NULL; -static gchar *deliver_to = NULL; -static gchar *rcpt = NULL; -static gchar *user = NULL; -static gchar *helo = NULL; -static gchar *hostname = NULL; -static gchar *classifier = "bayes"; -static gchar *local_addr = NULL; -static gint weight = 0; -static gint flag = 0; -static gint max_requests = 1024; -static gdouble timeout = 5.0; -static gboolean pass_all; -static gboolean tty = FALSE; -static gboolean verbose = FALSE; -static gboolean print_commands = FALSE; -static gboolean json = FALSE; -static gboolean headers = FALSE; -static gboolean raw = FALSE; +static gchar *connect_str = "localhost"; +static gchar *password = NULL; +static gchar *ip = NULL; +static gchar *from = NULL; +static gchar *deliver_to = NULL; +static gchar *rcpt = NULL; +static gchar *user = NULL; +static gchar *helo = NULL; +static gchar *hostname = NULL; +static gchar *classifier = "bayes"; +static gchar *local_addr = NULL; +static gint weight = 0; +static gint flag = 0; +static gint max_requests = 1024; +static gdouble timeout = 5.0; +static gboolean pass_all; +static gboolean tty = FALSE; +static gboolean verbose = FALSE; +static gboolean print_commands = FALSE; +static gboolean json = FALSE; +static gboolean headers = FALSE; +static gboolean raw = FALSE; static GOptionEntry entries[] = { - { "connect", 'h', 0, G_OPTION_ARG_STRING, &connect_str, "Specify host and port", NULL }, - { "password", 'P', 0, G_OPTION_ARG_STRING, &password, "Specify control password", NULL }, - { "classifier", 'c', 0, G_OPTION_ARG_STRING, &classifier, "Classifier to learn spam or ham", NULL }, - { "weight", 'w', 0, G_OPTION_ARG_INT, &weight, "Weight for fuzzy operations", NULL }, - { "flag", 'f', 0, G_OPTION_ARG_INT, &flag, "Flag for fuzzy operations", NULL }, - { "pass-all", 'p', 0, G_OPTION_ARG_NONE, &pass_all, "Pass all filters", NULL }, - { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "More verbose output", NULL }, - { "ip", 'i', 0, G_OPTION_ARG_STRING, &ip, "Emulate that message was received from specified ip address", NULL }, - { "user", 'u', 0, G_OPTION_ARG_STRING, &user, "Emulate that message was from specified user", NULL }, - { "deliver", 'd', 0, G_OPTION_ARG_STRING, &deliver_to, "Emulate that message is delivered to specified user", NULL }, - { "from", 'F', 0, G_OPTION_ARG_STRING, &from, "Emulate that message is from specified user", NULL }, - { "rcpt", 'r', 0, G_OPTION_ARG_STRING, &rcpt, "Emulate that message is for specified user", NULL }, - { "helo", 0, 0, G_OPTION_ARG_STRING, &helo, "Imitate SMTP HELO passing from MTA", NULL }, - { "hostname", 0, 0, G_OPTION_ARG_STRING, &hostname, "Imitate hostname passing from MTA", NULL }, - { "timeout", 't', 0, G_OPTION_ARG_DOUBLE, &timeout, "Time in seconds to wait for a reply", NULL }, - { "bind", 'b', 0, G_OPTION_ARG_STRING, &local_addr, "Bind to specified ip address", NULL }, - { "commands", 0, 0, G_OPTION_ARG_NONE, &print_commands, "List available commands", NULL }, - { "json", 'j', 0, G_OPTION_ARG_NONE, &json, "Output json reply", NULL }, - { "headers", 0, 0, G_OPTION_ARG_NONE, &headers, "Output HTTP headers", NULL }, - { "raw", 0, 0, G_OPTION_ARG_NONE, &raw, "Output raw reply from rspamd", NULL }, - { "max-requests", 'n', 0, G_OPTION_ARG_INT, &max_requests, "Maximum count of parallel requests to rspamd", NULL }, - { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } + { "connect", 'h', 0, G_OPTION_ARG_STRING, &connect_str, + "Specify host and port", NULL }, + { "password", 'P', 0, G_OPTION_ARG_STRING, &password, + "Specify control password", NULL }, + { "classifier", 'c', 0, G_OPTION_ARG_STRING, &classifier, + "Classifier to learn spam or ham", NULL }, + { "weight", 'w', 0, G_OPTION_ARG_INT, &weight, + "Weight for fuzzy operations", NULL }, + { "flag", 'f', 0, G_OPTION_ARG_INT, &flag, "Flag for fuzzy operations", + NULL }, + { "pass-all", 'p', 0, G_OPTION_ARG_NONE, &pass_all, "Pass all filters", + NULL }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "More verbose output", + NULL }, + { "ip", 'i', 0, G_OPTION_ARG_STRING, &ip, + "Emulate that message was received from specified ip address", + NULL }, + { "user", 'u', 0, G_OPTION_ARG_STRING, &user, + "Emulate that message was from specified user", NULL }, + { "deliver", 'd', 0, G_OPTION_ARG_STRING, &deliver_to, + "Emulate that message is delivered to specified user", NULL }, + { "from", 'F', 0, G_OPTION_ARG_STRING, &from, + "Emulate that message is from specified user", NULL }, + { "rcpt", 'r', 0, G_OPTION_ARG_STRING, &rcpt, + "Emulate that message is for specified user", NULL }, + { "helo", 0, 0, G_OPTION_ARG_STRING, &helo, + "Imitate SMTP HELO passing from MTA", NULL }, + { "hostname", 0, 0, G_OPTION_ARG_STRING, &hostname, + "Imitate hostname passing from MTA", NULL }, + { "timeout", 't', 0, G_OPTION_ARG_DOUBLE, &timeout, + "Time in seconds to wait for a reply", NULL }, + { "bind", 'b', 0, G_OPTION_ARG_STRING, &local_addr, + "Bind to specified ip address", NULL }, + { "commands", 0, 0, G_OPTION_ARG_NONE, &print_commands, + "List available commands", NULL }, + { "json", 'j', 0, G_OPTION_ARG_NONE, &json, "Output json reply", NULL }, + { "headers", 0, 0, G_OPTION_ARG_NONE, &headers, "Output HTTP headers", + NULL }, + { "raw", 0, 0, G_OPTION_ARG_NONE, &raw, "Output raw reply from rspamd", + NULL }, + { "max-requests", 'n', 0, G_OPTION_ARG_INT, &max_requests, + "Maximum count of parallel requests to rspamd", NULL }, + { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } }; static void rspamc_symbols_output (ucl_object_t *obj); @@ -143,7 +164,8 @@ struct rspamc_command { .cmd = RSPAMC_COMMAND_FUZZY_ADD, .name = "fuzzy_add", .path = "fuzzyadd", - .description = "add message to fuzzy storage (check -f and -w options for this command)", + .description = + "add message to fuzzy storage (check -f and -w options for this command)", .is_controller = TRUE, .is_privileged = TRUE, .need_input = TRUE, @@ -153,7 +175,8 @@ struct rspamc_command { .cmd = RSPAMC_COMMAND_FUZZY_DEL, .name = "fuzzy_del", .path = "fuzzydel", - .description = "delete message from fuzzy storage (check -f option for this command)", + .description = + "delete message from fuzzy storage (check -f option for this command)", .is_controller = TRUE, .is_privileged = TRUE, .need_input = TRUE, @@ -232,12 +255,13 @@ struct rspamc_callback_data { static void read_cmd_line (gint *argc, gchar ***argv) { - GError *error = NULL; - GOptionContext *context; + GError *error = NULL; + GOptionContext *context; /* Prepare parser */ context = g_option_context_new ("- run rspamc client"); - g_option_context_set_summary (context, "Summary:\n Rspamd client version " RVERSION "\n Release id: " RID); + g_option_context_set_summary (context, + "Summary:\n Rspamd client version " RVERSION "\n Release id: " RID); g_option_context_add_main_entries (context, entries, NULL); /* Parse options */ @@ -298,7 +322,7 @@ check_rspamc_command (const gchar *cmd) ct = RSPAMC_COMMAND_ADD_ACTION; } - for (i = 0; i < G_N_ELEMENTS (rspamc_commands); i ++) { + for (i = 0; i < G_N_ELEMENTS (rspamc_commands); i++) { if (rspamc_commands[i].cmd == ct) { return &rspamc_commands[i]; } @@ -310,17 +334,21 @@ check_rspamc_command (const gchar *cmd) static void print_commands_list (void) { - guint i; + guint i; rspamd_fprintf (stdout, "Rspamc commands summary:\n"); - for (i = 0; i < G_N_ELEMENTS (rspamc_commands); i ++) { - rspamd_fprintf (stdout, " %10s (%7s%1s)\t%s\n", rspamc_commands[i].name, - rspamc_commands[i].is_controller ? "control" : "normal", - rspamc_commands[i].is_privileged ? "*" : "", - rspamc_commands[i].description); - } - rspamd_fprintf (stdout, "\n* is for privileged commands that may need password (see -P option)\n"); - rspamd_fprintf (stdout, "control commands use port 11334 while normal use 11333 by default (see -h option)\n"); + for (i = 0; i < G_N_ELEMENTS (rspamc_commands); i++) { + rspamd_fprintf (stdout, + " %10s (%7s%1s)\t%s\n", + rspamc_commands[i].name, + rspamc_commands[i].is_controller ? "control" : "normal", + rspamc_commands[i].is_privileged ? "*" : "", + rspamc_commands[i].description); + } + rspamd_fprintf (stdout, + "\n* is for privileged commands that may need password (see -P option)\n"); + rspamd_fprintf (stdout, + "control commands use port 11334 while normal use 11333 by default (see -h option)\n"); } @@ -410,24 +438,28 @@ rspamc_metric_output (const ucl_object_t *obj) while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) { if (g_ascii_strcasecmp (ucl_object_key (cur), "is_spam") == 0) { rspamd_fprintf (stdout, "Spam: %s\n", ucl_object_toboolean (cur) ? - "true" : "false"); + "true" : "false"); } else if (g_ascii_strcasecmp (ucl_object_key (cur), "score") == 0) { score = ucl_object_todouble (cur); - got_scores ++; + got_scores++; } - else if (g_ascii_strcasecmp (ucl_object_key (cur), "required_score") == 0) { + else if (g_ascii_strcasecmp (ucl_object_key (cur), + "required_score") == 0) { required_score = ucl_object_todouble (cur); - got_scores ++; + got_scores++; } else if (g_ascii_strcasecmp (ucl_object_key (cur), "action") == 0) { - rspamd_fprintf (stdout, "Action: %s\n", ucl_object_tostring(cur)); + rspamd_fprintf (stdout, "Action: %s\n", ucl_object_tostring (cur)); } else if (cur->type == UCL_OBJECT) { rspamc_symbol_output (cur); } if (got_scores == 2) { - rspamd_fprintf (stdout, "Score: %.2f / %.2f\n", score, required_score); + rspamd_fprintf (stdout, + "Score: %.2f / %.2f\n", + score, + required_score); got_scores = 0; } } @@ -442,10 +474,12 @@ rspamc_symbols_output (ucl_object_t *obj) while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) { if (g_ascii_strcasecmp (ucl_object_key (cur), "message-id") == 0) { - rspamd_fprintf (stdout, "Message-ID: %s\n", ucl_object_tostring (cur)); + rspamd_fprintf (stdout, "Message-ID: %s\n", ucl_object_tostring ( + cur)); } else if (g_ascii_strcasecmp (ucl_object_key (cur), "queue-id") == 0) { - rspamd_fprintf (stdout, "Queue-ID: %s\n", ucl_object_tostring (cur)); + rspamd_fprintf (stdout, "Queue-ID: %s\n", + ucl_object_tostring (cur)); } else if (g_ascii_strcasecmp (ucl_object_key (cur), "urls") == 0) { emitted = ucl_object_emit (cur, UCL_EMIT_JSON_COMPACT); @@ -458,7 +492,8 @@ rspamc_symbols_output (ucl_object_t *obj) free (emitted); } else if (g_ascii_strcasecmp (ucl_object_key (cur), "error") == 0) { - rspamd_fprintf (stdout, "Scan error: %s\n", ucl_object_tostring (cur)); + rspamd_fprintf (stdout, "Scan error: %s\n", ucl_object_tostring ( + cur)); } else if (cur->type == UCL_OBJECT) { /* Parse metric */ @@ -475,7 +510,8 @@ rspamc_uptime_output (ucl_object_t *obj) elt = ucl_object_find_key (obj, "version"); if (elt != NULL) { - rspamd_fprintf (stdout, "Rspamd version: %s\n", ucl_object_tostring (elt)); + rspamd_fprintf (stdout, "Rspamd version: %s\n", ucl_object_tostring ( + elt)); } elt = ucl_object_find_key (obj, "uptime"); @@ -487,13 +523,13 @@ rspamc_uptime_output (ucl_object_t *obj) hours = seconds / 3600 - days * 24; minutes = seconds / 60 - hours * 60 - days * 1440; rspamd_printf ("%L day%s %L hour%s %L minute%s\n", days, - days > 1 ? "s" : "", hours, hours > 1 ? "s" : "", - minutes, minutes > 1 ? "s" : ""); + days > 1 ? "s" : "", hours, hours > 1 ? "s" : "", + minutes, minutes > 1 ? "s" : ""); } /* If uptime is less than 1 minute print only seconds */ else if (seconds / 60 == 0) { rspamd_printf ("%L second%s\n", (gint)seconds, - (gint)seconds > 1 ? "s" : ""); + (gint)seconds > 1 ? "s" : ""); } /* Else print the minutes and seconds. */ else { @@ -501,9 +537,9 @@ rspamc_uptime_output (ucl_object_t *obj) minutes = seconds / 60 - hours * 60; seconds -= hours * 3600 + minutes * 60; rspamd_printf ("%L hour%s %L minute%s %L second%s\n", hours, - hours > 1 ? "s" : "", minutes, - minutes > 1 ? "s" : "", - seconds, seconds > 1 ? "s" : ""); + hours > 1 ? "s" : "", minutes, + minutes > 1 ? "s" : "", + seconds, seconds > 1 ? "s" : ""); } } } @@ -532,7 +568,7 @@ rspamc_counters_output (ucl_object_t *obj) } rspamd_snprintf (fmt_buf, sizeof (fmt_buf), - "| %%3s | %%%ds | %%6s | %%9s | %%9s |\n", max_len); + "| %%3s | %%%ds | %%6s | %%9s | %%9s |\n", max_len); memset (dash_buf, '-', 40 + max_len); dash_buf[40 + max_len] = '\0'; @@ -546,7 +582,7 @@ rspamc_counters_output (ucl_object_t *obj) printf ("\033[0m"); } rspamd_snprintf (fmt_buf, sizeof (fmt_buf), - "| %%3d | %%%ds | %%6.1f | %%9d | %%9.3f |\n", max_len); + "| %%3d | %%%ds | %%6.1f | %%9d | %%9.3f |\n", max_len); iter = NULL; i = 0; @@ -563,7 +599,7 @@ rspamc_counters_output (ucl_object_t *obj) (gint)ucl_object_toint (freq), ucl_object_todouble (tim)); } - i ++; + i++; } printf (" %s \n", dash_buf); } @@ -573,7 +609,8 @@ rspamc_output_headers (struct rspamd_http_message *msg) { struct rspamd_http_header *h; - LL_FOREACH (msg->headers, h) { + LL_FOREACH (msg->headers, h) + { rspamd_fprintf (stdout, "%v: %v\n", h->name, h->value); } rspamd_fprintf (stdout, "\n"); @@ -581,9 +618,9 @@ rspamc_output_headers (struct rspamd_http_message *msg) static void rspamc_client_cb (struct rspamd_client_connection *conn, - struct rspamd_http_message *msg, - const gchar *name, ucl_object_t *result, - gpointer ud, GError *err) + struct rspamd_http_message *msg, + const gchar *name, ucl_object_t *result, + gpointer ud, GError *err) { gchar *out; struct rspamc_callback_data *cbdata = (struct rspamc_callback_data *)ud; @@ -628,13 +665,13 @@ rspamc_client_cb (struct rspamd_client_connection *conn, static void rspamc_process_input (struct event_base *ev_base, struct rspamc_command *cmd, - FILE *in, const gchar *name, GHashTable *attrs) + FILE *in, const gchar *name, GHashTable *attrs) { struct rspamd_client_connection *conn; gchar **connectv; guint16 port; GError *err = NULL; - struct rspamc_callback_data *cbdata; + struct rspamc_callback_data *cbdata; connectv = g_strsplit_set (connect_str, ":", -1); @@ -663,11 +700,16 @@ rspamc_process_input (struct event_base *ev_base, struct rspamc_command *cmd, cbdata->filename = name; if (cmd->need_input) { rspamd_client_command (conn, cmd->path, attrs, in, rspamc_client_cb, - cbdata, &err); + cbdata, &err); } else { - rspamd_client_command (conn, cmd->path, attrs, NULL, rspamc_client_cb, - cbdata, &err); + rspamd_client_command (conn, + cmd->path, + attrs, + NULL, + rspamc_client_cb, + cbdata, + &err); } } } @@ -675,11 +717,11 @@ rspamc_process_input (struct event_base *ev_base, struct rspamc_command *cmd, gint main (gint argc, gchar **argv, gchar **env) { - gint i, start_argc, cur_req = 0; - GHashTable *kwattrs; - struct rspamc_command *cmd; - FILE *in = NULL; - struct event_base *ev_base; + gint i, start_argc, cur_req = 0; + GHashTable *kwattrs; + struct rspamc_command *cmd; + FILE *in = NULL; + struct event_base *ev_base; kwattrs = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); @@ -719,18 +761,19 @@ main (gint argc, gchar **argv, gchar **env) else { if ((cmd = check_rspamc_command (argv[1])) != NULL) { /* In case of command read arguments starting from 2 */ - if (cmd->cmd == RSPAMC_COMMAND_ADD_SYMBOL || cmd->cmd == RSPAMC_COMMAND_ADD_ACTION) { + if (cmd->cmd == RSPAMC_COMMAND_ADD_SYMBOL || cmd->cmd == + RSPAMC_COMMAND_ADD_ACTION) { if (argc < 4 || argc > 5) { fprintf (stderr, "invalid arguments\n"); exit (EXIT_FAILURE); } if (argc == 5) { g_hash_table_insert (kwattrs, "metric", argv[2]); - g_hash_table_insert (kwattrs, "name", argv[3]); - g_hash_table_insert (kwattrs, "value", argv[4]); + g_hash_table_insert (kwattrs, "name", argv[3]); + g_hash_table_insert (kwattrs, "value", argv[4]); } else { - g_hash_table_insert (kwattrs, "name", argv[2]); + g_hash_table_insert (kwattrs, "name", argv[2]); g_hash_table_insert (kwattrs, "value", argv[3]); } start_argc = argc; @@ -752,14 +795,14 @@ main (gint argc, gchar **argv, gchar **env) rspamc_process_input (ev_base, cmd, in, "stdin", kwattrs); } else { - for (i = start_argc; i < argc; i ++) { + for (i = start_argc; i < argc; i++) { in = fopen (argv[i], "r"); if (in == NULL) { fprintf (stderr, "cannot open file %s\n", argv[i]); exit (EXIT_FAILURE); } rspamc_process_input (ev_base, cmd, in, argv[i], kwattrs); - cur_req ++; + cur_req++; fclose (in); if (cur_req >= max_requests) { cur_req = 0; diff --git a/src/client/rspamdclient.c b/src/client/rspamdclient.c index 55f1a6e37..e9a8f5409 100644 --- a/src/client/rspamdclient.c +++ b/src/client/rspamdclient.c @@ -62,8 +62,8 @@ rspamd_client_error_quark (void) static gint rspamd_client_body_handler (struct rspamd_http_connection *conn, - struct rspamd_http_message *msg, - const gchar *chunk, gsize len) + struct rspamd_http_message *msg, + const gchar *chunk, gsize len) { /* Do nothing here */ return 0; @@ -72,7 +72,8 @@ rspamd_client_body_handler (struct rspamd_http_connection *conn, static void rspamd_client_error_handler (struct rspamd_http_connection *conn, GError *err) { - struct rspamd_client_request *req = (struct rspamd_client_request *)conn->ud; + struct rspamd_client_request *req = + (struct rspamd_client_request *)conn->ud; struct rspamd_client_connection *c; c = req->conn; @@ -81,9 +82,10 @@ rspamd_client_error_handler (struct rspamd_http_connection *conn, GError *err) static gint rspamd_client_finish_handler (struct rspamd_http_connection *conn, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_client_request *req = (struct rspamd_client_request *)conn->ud; + struct rspamd_client_request *req = + (struct rspamd_client_request *)conn->ud; struct rspamd_client_connection *c; struct ucl_parser *parser; GError *err; @@ -93,13 +95,18 @@ rspamd_client_finish_handler (struct rspamd_http_connection *conn, if (!c->req_sent) { c->req_sent = TRUE; rspamd_http_connection_reset (c->http_conn); - rspamd_http_connection_read_message (c->http_conn, c->req, c->fd, &c->timeout, c->ev_base); + rspamd_http_connection_read_message (c->http_conn, + c->req, + c->fd, + &c->timeout, + c->ev_base); return 0; } else { if (msg->body == NULL || msg->body->len == 0 || msg->code != 200) { err = g_error_new (RCLIENT_ERROR, msg->code, "HTTP error: %d, %s", - msg->code, msg->status ? msg->status->str : "unknown error"); + msg->code, + msg->status ? msg->status->str : "unknown error"); req->cb (c, msg, c->server_name->str, NULL, req->ud, err); g_error_free (err); return -1; @@ -115,7 +122,8 @@ rspamd_client_finish_handler (struct rspamd_http_connection *conn, return -1; } - req->cb (c, msg, c->server_name->str, ucl_parser_get_object (parser), req->ud, NULL); + req->cb (c, msg, c->server_name->str, ucl_parser_get_object ( + parser), req->ud, NULL); ucl_parser_free (parser); } @@ -124,7 +132,7 @@ rspamd_client_finish_handler (struct rspamd_http_connection *conn, struct rspamd_client_connection * rspamd_client_init (struct event_base *ev_base, const gchar *name, - guint16 port, gdouble timeout) + guint16 port, gdouble timeout) { struct rspamd_client_connection *conn; gint fd; @@ -139,7 +147,10 @@ rspamd_client_init (struct event_base *ev_base, const gchar *name, conn->fd = fd; conn->req_sent = FALSE; conn->http_conn = rspamd_http_connection_new (rspamd_client_body_handler, - rspamd_client_error_handler, rspamd_client_finish_handler, 0, RSPAMD_HTTP_CLIENT); + rspamd_client_error_handler, + rspamd_client_finish_handler, + 0, + RSPAMD_HTTP_CLIENT); conn->server_name = g_string_new (name); if (port != 0) { rspamd_printf_gstring (conn->server_name, ":%d", (int)port); @@ -152,9 +163,9 @@ rspamd_client_init (struct event_base *ev_base, const gchar *name, gboolean rspamd_client_command (struct rspamd_client_connection *conn, - const gchar *command, GHashTable *attrs, - FILE *in, rspamd_client_callback cb, - gpointer ud, GError **err) + const gchar *command, GHashTable *attrs, + FILE *in, rspamd_client_callback cb, + gpointer ud, GError **err) { struct rspamd_client_request *req; gchar *p, *hn, *hv; @@ -186,7 +197,8 @@ rspamd_client_command (struct rspamd_client_connection *conn, } } if (ferror (in) != 0) { - g_set_error (err, RCLIENT_ERROR, ferror (in), "input IO error: %s", strerror (ferror (in))); + g_set_error (err, RCLIENT_ERROR, ferror ( + in), "input IO error: %s", strerror (ferror (in))); g_slice_free1 (sizeof (struct rspamd_client_request), req); return FALSE; } @@ -207,7 +219,7 @@ rspamd_client_command (struct rspamd_client_connection *conn, conn->req = req; rspamd_http_connection_write_message (conn->http_conn, req->msg, NULL, - "text/plain", req, conn->fd, &conn->timeout, conn->ev_base); + "text/plain", req, conn->fd, &conn->timeout, conn->ev_base); return TRUE; } diff --git a/src/client/rspamdclient.h b/src/client/rspamdclient.h index 85b57c376..6a41c35c1 100644 --- a/src/client/rspamdclient.h +++ b/src/client/rspamdclient.h @@ -39,12 +39,12 @@ struct rspamd_http_message; * @param err error pointer */ typedef void (*rspamd_client_callback) ( - struct rspamd_client_connection *conn, - struct rspamd_http_message *msg, - const gchar *name, - ucl_object_t *result, - gpointer ud, - GError *err); + struct rspamd_client_connection *conn, + struct rspamd_http_message *msg, + const gchar *name, + ucl_object_t *result, + gpointer ud, + GError *err); /** * Start rspamd worker or controller command @@ -54,11 +54,11 @@ typedef void (*rspamd_client_callback) ( * @param timeout timeout in seconds * @return */ -struct rspamd_client_connection* rspamd_client_init ( - struct event_base *ev_base, - const gchar *name, - guint16 port, - gdouble timeout); +struct rspamd_client_connection * rspamd_client_init ( + struct event_base *ev_base, + const gchar *name, + guint16 port, + gdouble timeout); /** * @@ -71,13 +71,13 @@ struct rspamd_client_connection* rspamd_client_init ( * @return */ gboolean rspamd_client_command ( - struct rspamd_client_connection *conn, - const gchar *command, - GHashTable *attrs, - FILE *in, - rspamd_client_callback cb, - gpointer ud, - GError **err); + struct rspamd_client_connection *conn, + const gchar *command, + GHashTable *attrs, + FILE *in, + rspamd_client_callback cb, + gpointer ud, + GError **err); /** * Destroy a connection to rspamd diff --git a/src/controller.c b/src/controller.c index e3d82fa49..96e885cc9 100644 --- a/src/controller.c +++ b/src/controller.c @@ -75,25 +75,25 @@ gpointer init_controller_worker (struct rspamd_config *cfg); void start_controller_worker (struct rspamd_worker *worker); worker_t controller_worker = { - "controller", /* Name */ - init_controller_worker, /* Init function */ - start_controller_worker, /* Start function */ - TRUE, /* Has socket */ - TRUE, /* Non unique */ - FALSE, /* Non threaded */ - TRUE, /* Killable */ - SOCK_STREAM /* TCP socket */ + "controller", /* Name */ + init_controller_worker, /* Init function */ + start_controller_worker, /* Start function */ + TRUE, /* Has socket */ + TRUE, /* Non unique */ + FALSE, /* Non threaded */ + TRUE, /* Killable */ + SOCK_STREAM /* TCP socket */ }; /* * Worker's context */ struct rspamd_controller_worker_ctx { - guint32 timeout; - struct timeval io_tv; + guint32 timeout; + struct timeval io_tv; /* DNS resolver */ - struct rspamd_dns_resolver *resolver; + struct rspamd_dns_resolver *resolver; /* Events base */ - struct event_base *ev_base; + struct event_base *ev_base; /* Whether we use ssl for this server */ gboolean use_ssl; /* Webui password */ @@ -138,11 +138,11 @@ struct rspamd_controller_session { /* Check for password if it is required by configuration */ static gboolean rspamd_controller_check_password (struct rspamd_http_connection_entry *entry, - struct rspamd_controller_session *session, struct rspamd_http_message *msg, - gboolean is_enable) + struct rspamd_controller_session *session, struct rspamd_http_message *msg, + gboolean is_enable) { - const gchar *password, *check; - struct rspamd_controller_worker_ctx *ctx = session->ctx; + const gchar *password, *check; + struct rspamd_controller_worker_ctx *ctx = session->ctx; gboolean ret = TRUE; /* Access list logic */ @@ -151,9 +151,9 @@ rspamd_controller_check_password (struct rspamd_http_connection_entry *entry, return TRUE; } else if (ctx->secure_map && radix32_tree_find_addr (ctx->secure_map, - &session->from_addr) != RADIX_NO_VALUE) { + &session->from_addr) != RADIX_NO_VALUE) { msg_info ("allow unauthorized connection from a trusted IP %s", - rspamd_inet_address_to_string (&session->from_addr)); + rspamd_inet_address_to_string (&session->from_addr)); return TRUE; } @@ -163,7 +163,8 @@ rspamd_controller_check_password (struct rspamd_http_connection_entry *entry, password = rspamd_http_message_find_header (msg, "Password"); if (ctx->enable_password == NULL) { /* Use just a password (legacy mode) */ - msg_info ("using password as enable_password for a privileged command"); + msg_info ( + "using password as enable_password for a privileged command"); check = ctx->password; } else { @@ -176,7 +177,8 @@ rspamd_controller_check_password (struct rspamd_http_connection_entry *entry, } } else { - msg_warn ("no password to check while executing a privileged command"); + msg_warn ( + "no password to check while executing a privileged command"); if (ctx->secure_map) { msg_info ("deny unauthorized connection"); ret = FALSE; @@ -227,13 +229,13 @@ rspamd_controller_check_password (struct rspamd_http_connection_entry *entry, */ static int rspamd_controller_handle_auth (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - struct rspamd_stat *st; - int64_t uptime; - gulong data[4]; - ucl_object_t *obj; + struct rspamd_controller_session *session = conn_ent->ud; + struct rspamd_stat *st; + int64_t uptime; + gulong data[4]; + ucl_object_t *obj; if (!rspamd_controller_check_password (conn_ent, session, msg, FALSE)) { return 0; @@ -242,22 +244,32 @@ rspamd_controller_handle_auth (struct rspamd_http_connection_entry *conn_ent, obj = ucl_object_typed_new (UCL_OBJECT); st = session->ctx->srv->stat; data[0] = st->actions_stat[METRIC_ACTION_NOACTION]; - data[1] = st->actions_stat[METRIC_ACTION_ADD_HEADER] + st->actions_stat[METRIC_ACTION_REWRITE_SUBJECT]; + data[1] = st->actions_stat[METRIC_ACTION_ADD_HEADER] + + st->actions_stat[METRIC_ACTION_REWRITE_SUBJECT]; data[2] = st->actions_stat[METRIC_ACTION_GREYLIST]; data[3] = st->actions_stat[METRIC_ACTION_REJECT]; /* Get uptime */ uptime = time (NULL) - session->ctx->start_time; - ucl_object_insert_key (obj, ucl_object_fromstring (RVERSION), "version", 0, false); - ucl_object_insert_key (obj, ucl_object_fromstring ("ok"), "auth", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (uptime), "uptime", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (data[0]), "clean", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (data[1]), "probable", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (data[2]), "greylist", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (data[3]), "reject", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (st->messages_scanned), "scanned", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (st->messages_learned), "learned", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + RVERSION), "version", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + "ok"), "auth", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + uptime), "uptime", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + data[0]), "clean", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + data[1]), "probable", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + data[2]), "greylist", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + data[3]), "reject", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + st->messages_scanned), "scanned", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + st->messages_learned), "learned", 0, false); rspamd_controller_send_ucl (conn_ent, obj); ucl_object_unref (obj); @@ -269,26 +281,26 @@ rspamd_controller_handle_auth (struct rspamd_http_connection_entry *conn_ent, * Symbols command handler: * request: /symbols * reply: json [{ - * "name": "group_name", - * "symbols": [ - * { - * "name": "name", - * "weight": 0.1, - * "description": "description of symbol" - * }, - * {...} + * "name": "group_name", + * "symbols": [ + * { + * "name": "name", + * "weight": 0.1, + * "description": "description of symbol" + * }, + * {...} * }, * {...}] */ static int rspamd_controller_handle_symbols (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - GList *cur_gr, *cur_sym; - struct rspamd_symbols_group *gr; - struct rspamd_symbol_def *sym; - ucl_object_t *obj, *top, *sym_obj; + struct rspamd_controller_session *session = conn_ent->ud; + GList *cur_gr, *cur_sym; + struct rspamd_symbols_group *gr; + struct rspamd_symbol_def *sym; + ucl_object_t *obj, *top, *sym_obj; if (!rspamd_controller_check_password (conn_ent, session, msg, FALSE)) { return 0; @@ -301,7 +313,8 @@ rspamd_controller_handle_symbols (struct rspamd_http_connection_entry *conn_ent, while (cur_gr) { gr = cur_gr->data; obj = ucl_object_typed_new (UCL_OBJECT); - ucl_object_insert_key (obj, ucl_object_fromstring (gr->name), "group", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + gr->name), "group", 0, false); /* Iterate through all symbols */ cur_sym = gr->symbols; while (cur_sym) { @@ -309,11 +322,13 @@ rspamd_controller_handle_symbols (struct rspamd_http_connection_entry *conn_ent, sym = cur_sym->data; ucl_object_insert_key (sym_obj, ucl_object_fromstring (sym->name), - "symbol", 0, false); - ucl_object_insert_key (sym_obj, ucl_object_fromdouble (*sym->weight_ptr), - "weight", 0, false); + "symbol", 0, false); + ucl_object_insert_key (sym_obj, + ucl_object_fromdouble (*sym->weight_ptr), + "weight", 0, false); if (sym->description) { - ucl_object_insert_key (sym_obj, ucl_object_fromstring (sym->description), + ucl_object_insert_key (sym_obj, + ucl_object_fromstring (sym->description), "description", 0, false); } @@ -334,20 +349,20 @@ rspamd_controller_handle_symbols (struct rspamd_http_connection_entry *conn_ent, * Actions command handler: * request: /actions * reply: json [{ - * "action": "no action", - * "value": 1.1 + * "action": "no action", + * "value": 1.1 * }, * {...}] */ static int rspamd_controller_handle_actions (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - struct metric *metric; - struct metric_action *act; - gint i; - ucl_object_t *obj, *top; + struct rspamd_controller_session *session = conn_ent->ud; + struct metric *metric; + struct metric_action *act; + gint i; + ucl_object_t *obj, *top; if (!rspamd_controller_check_password (conn_ent, session, msg, FALSE)) { return 0; @@ -358,13 +373,15 @@ rspamd_controller_handle_actions (struct rspamd_http_connection_entry *conn_ent, /* Get actions for default metric */ metric = g_hash_table_lookup (session->ctx->cfg->metrics, DEFAULT_METRIC); if (metric != NULL) { - for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { + for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) { act = &metric->actions[i]; if (act->score > 0) { obj = ucl_object_typed_new (UCL_OBJECT); ucl_object_insert_key (obj, - ucl_object_fromstring (str_action_metric (act->action)), "action", 0, false); - ucl_object_insert_key (obj, ucl_object_fromdouble (act->score), "value", 0, false); + ucl_object_fromstring (str_action_metric ( + act->action)), "action", 0, false); + ucl_object_insert_key (obj, ucl_object_fromdouble ( + act->score), "value", 0, false); ucl_array_append (top, obj); } } @@ -380,23 +397,23 @@ rspamd_controller_handle_actions (struct rspamd_http_connection_entry *conn_ent, * request: /maps * headers: Password * reply: json [ - * { - * "map": "name", - * "description": "description", - * "editable": true - * }, - * {...} + * { + * "map": "name", + * "description": "description", + * "editable": true + * }, + * {...} * ] */ static int rspamd_controller_handle_maps (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - GList *cur, *tmp = NULL; - struct rspamd_map *map; - gboolean editable; - ucl_object_t *obj, *top; + struct rspamd_controller_session *session = conn_ent->ud; + GList *cur, *tmp = NULL; + struct rspamd_map *map; + gboolean editable; + ucl_object_t *obj, *top; if (!rspamd_controller_check_password (conn_ent, session, msg, FALSE)) { @@ -422,12 +439,12 @@ rspamd_controller_handle_maps (struct rspamd_http_connection_entry *conn_ent, editable = (access (map->uri, W_OK) == 0); obj = ucl_object_typed_new (UCL_OBJECT); - ucl_object_insert_key (obj, ucl_object_fromint (map->id), - "map", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint (map->id), + "map", 0, false); ucl_object_insert_key (obj, ucl_object_fromstring (map->description), - "description", 0, false); - ucl_object_insert_key (obj, ucl_object_frombool (editable), - "editable", 0, false); + "description", 0, false); + ucl_object_insert_key (obj, ucl_object_frombool (editable), + "editable", 0, false); ucl_array_append (top, obj); cur = g_list_next (cur); @@ -451,18 +468,18 @@ rspamd_controller_handle_maps (struct rspamd_http_connection_entry *conn_ent, */ static int rspamd_controller_handle_get_map (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - GList *cur; - struct rspamd_map *map; - const gchar *idstr; - gchar *errstr; - struct stat st; - gint fd; - guint32 id; - gboolean found = FALSE; - struct rspamd_http_message *reply; + struct rspamd_controller_session *session = conn_ent->ud; + GList *cur; + struct rspamd_map *map; + const gchar *idstr; + gchar *errstr; + struct stat st; + gint fd; + guint32 id; + gboolean found = FALSE; + struct rspamd_http_message *reply; if (!rspamd_controller_check_password (conn_ent, session, msg, FALSE)) { @@ -528,8 +545,8 @@ rspamd_controller_handle_get_map (struct rspamd_http_connection_entry *conn_ent, rspamd_http_connection_reset (conn_ent->conn); rspamd_http_connection_write_message (conn_ent->conn, reply, NULL, - "text/plain", conn_ent, conn_ent->conn->fd, - conn_ent->rt->ptv, conn_ent->rt->ev_base); + "text/plain", conn_ent, conn_ent->conn->fd, + conn_ent->rt->ptv, conn_ent->rt->ev_base); conn_ent->is_reply = TRUE; return 0; @@ -541,20 +558,20 @@ rspamd_controller_handle_get_map (struct rspamd_http_connection_entry *conn_ent, * request: /graph * headers: Password * reply: json [ - * { label: "Foo", data: [ [10, 1], [17, -14], [30, 5] ] }, - * { label: "Bar", data: [ [10, 1], [17, -14], [30, 5] ] }, - * {...} + * { label: "Foo", data: [ [10, 1], [17, -14], [30, 5] ] }, + * { label: "Bar", data: [ [10, 1], [17, -14], [30, 5] ] }, + * {...} * ] */ /* XXX: now this function returns only random data */ static void rspamd_controller_handle_graph (struct evhttp_request *req, gpointer arg) { - struct rspamd_controller_worker_ctx *ctx = arg; - struct evbuffer *evb; - gint i, seed; - time_t now, t; - double vals[5][100]; + struct rspamd_controller_worker_ctx *ctx = arg; + struct evbuffer *evb; + gint i, seed; + time_t now, t; + double vals[5][100]; if (!http_check_password (ctx, req)) { return; @@ -572,8 +589,10 @@ rspamd_controller_handle_graph (struct evhttp_request *req, gpointer arg) /* XXX: simple and stupid set */ seed = g_random_int (); - for (i = 0; i < 100; i ++, seed ++) { - vals[0][i] = fabs ((sin (seed * 0.1 * M_PI_2) + 1) * 40. + ((gint)(g_random_int () % 2) - 1)); + for (i = 0; i < 100; i++, seed++) { + vals[0][i] = + fabs ((sin (seed * 0.1 * + M_PI_2) + 1) * 40. + ((gint)(g_random_int () % 2) - 1)); vals[1][i] = vals[0][i] * 0.5; vals[2][i] = vals[0][i] * 0.1; vals[3][i] = vals[0][i] * 0.3; @@ -584,50 +603,75 @@ rspamd_controller_handle_graph (struct evhttp_request *req, gpointer arg) /* Ham label */ t = now - 6000; - evbuffer_add_printf (evb, "{\"label\": \"Clean messages\", \"lines\": {\"fill\": false}, \"color\": \"" - COLOR_CLEAN "\", \"data\":["); - for (i = 0; i < 100; i ++, t += 60) { - evbuffer_add_printf (evb, "[%llu,%.2f%s", (long long unsigned)t * 1000, vals[0][i], i == 99 ? "]" : "],"); + evbuffer_add_printf (evb, + "{\"label\": \"Clean messages\", \"lines\": {\"fill\": false}, \"color\": \"" + COLOR_CLEAN "\", \"data\":["); + for (i = 0; i < 100; i++, t += 60) { + evbuffer_add_printf (evb, + "[%llu,%.2f%s", + (long long unsigned)t * 1000, + vals[0][i], + i == 99 ? "]" : "],"); } evbuffer_add (evb, "]},", 3); /* Probable spam label */ t = now - 6000; - evbuffer_add_printf (evb, "{\"label\": \"Probable spam messages\", \"lines\": {\"fill\": false}, \"color\": \"" - COLOR_PROBABLE_SPAM "\", \"data\":["); - for (i = 0; i < 100; i ++, t += 60) { - evbuffer_add_printf (evb, "[%llu,%.2f%s", (long long unsigned)t * 1000, vals[1][i], i == 99 ? "]" : "],"); + evbuffer_add_printf (evb, + "{\"label\": \"Probable spam messages\", \"lines\": {\"fill\": false}, \"color\": \"" + COLOR_PROBABLE_SPAM "\", \"data\":["); + for (i = 0; i < 100; i++, t += 60) { + evbuffer_add_printf (evb, + "[%llu,%.2f%s", + (long long unsigned)t * 1000, + vals[1][i], + i == 99 ? "]" : "],"); } evbuffer_add (evb, "]},", 3); /* Greylist label */ t = now - 6000; - evbuffer_add_printf (evb, "{\"label\": \"Greylisted messages\", \"lines\": {\"fill\": false}, \"color\": \"" - COLOR_GREYLIST "\", \"data\":["); - for (i = 0; i < 100; i ++, t += 60) { - evbuffer_add_printf (evb, "[%llu,%.2f%s", (long long unsigned)t * 1000, vals[2][i], i == 99 ? "]" : "],"); + evbuffer_add_printf (evb, + "{\"label\": \"Greylisted messages\", \"lines\": {\"fill\": false}, \"color\": \"" + COLOR_GREYLIST "\", \"data\":["); + for (i = 0; i < 100; i++, t += 60) { + evbuffer_add_printf (evb, + "[%llu,%.2f%s", + (long long unsigned)t * 1000, + vals[2][i], + i == 99 ? "]" : "],"); } evbuffer_add (evb, "]},", 3); /* Reject label */ t = now - 6000; - evbuffer_add_printf (evb, "{\"label\": \"Rejected messages\", \"lines\": {\"fill\": false}, \"color\": \"" - COLOR_REJECT "\", \"data\":["); - for (i = 0; i < 100; i ++, t += 60) { - evbuffer_add_printf (evb, "[%llu,%.2f%s", (long long unsigned)t * 1000, vals[3][i], i == 99 ? "]" : "],"); + evbuffer_add_printf (evb, + "{\"label\": \"Rejected messages\", \"lines\": {\"fill\": false}, \"color\": \"" + COLOR_REJECT "\", \"data\":["); + for (i = 0; i < 100; i++, t += 60) { + evbuffer_add_printf (evb, + "[%llu,%.2f%s", + (long long unsigned)t * 1000, + vals[3][i], + i == 99 ? "]" : "],"); } evbuffer_add (evb, "]},", 3); /* Total label */ t = now - 6000; - evbuffer_add_printf (evb, "{\"label\": \"Total messages\", \"lines\": {\"fill\": false}, \"color\": \"" - COLOR_TOTAL "\", \"data\":["); - for (i = 0; i < 100; i ++, t += 60) { - evbuffer_add_printf (evb, "[%llu,%.2f%s", (long long unsigned)t * 1000, vals[4][i], i == 99 ? "]" : "],"); + evbuffer_add_printf (evb, + "{\"label\": \"Total messages\", \"lines\": {\"fill\": false}, \"color\": \"" + COLOR_TOTAL "\", \"data\":["); + for (i = 0; i < 100; i++, t += 60) { + evbuffer_add_printf (evb, + "[%llu,%.2f%s", + (long long unsigned)t * 1000, + vals[4][i], + i == 99 ? "]" : "],"); } - evbuffer_add (evb, "]}", 2); + evbuffer_add (evb, "]}", 2); - evbuffer_add (evb, "]" CRLF, 3); + evbuffer_add (evb, "]" CRLF, 3); evhttp_add_header (req->output_headers, "Connection", "close"); http_calculate_content_length (evb, req); @@ -641,19 +685,20 @@ rspamd_controller_handle_graph (struct evhttp_request *req, gpointer arg) * request: /pie * headers: Password * reply: json [ - * { label: "Foo", data: 11 }, - * { label: "Bar", data: 20 }, - * {...} + * { label: "Foo", data: 11 }, + * { label: "Bar", data: 20 }, + * {...} * ] */ static int -rspamd_controller_handle_pie_chart (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) +rspamd_controller_handle_pie_chart ( + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - struct rspamd_controller_worker_ctx *ctx; - gdouble data[4], total; - ucl_object_t *top, *obj; + struct rspamd_controller_session *session = conn_ent->ud; + struct rspamd_controller_worker_ctx *ctx; + gdouble data[4], total; + ucl_object_t *top, *obj; ctx = session->ctx; @@ -666,31 +711,36 @@ rspamd_controller_handle_pie_chart (struct rspamd_http_connection_entry *conn_en if (total != 0) { obj = ucl_object_typed_new (UCL_ARRAY); - data[0] = ctx->srv->stat->actions_stat[METRIC_ACTION_NOACTION] / total * 100.; + data[0] = ctx->srv->stat->actions_stat[METRIC_ACTION_NOACTION] / total * + 100.; data[1] = (ctx->srv->stat->actions_stat[METRIC_ACTION_ADD_HEADER] + - ctx->srv->stat->actions_stat[METRIC_ACTION_REWRITE_SUBJECT]) / total * 100.; - data[2] = ctx->srv->stat->actions_stat[METRIC_ACTION_GREYLIST] / total * 100.; - data[3] = ctx->srv->stat->actions_stat[METRIC_ACTION_REJECT] / total * 100.; + ctx->srv->stat->actions_stat[METRIC_ACTION_REWRITE_SUBJECT]) / + total * 100.; + data[2] = ctx->srv->stat->actions_stat[METRIC_ACTION_GREYLIST] / total * + 100.; + data[3] = ctx->srv->stat->actions_stat[METRIC_ACTION_REJECT] / total * + 100.; ucl_array_append (obj, ucl_object_fromstring ("Clean messages")); ucl_array_append (obj, ucl_object_fromdouble (data[0])); - ucl_array_append (top, obj); - ucl_array_append (obj, ucl_object_fromstring ("Probable spam messages")); + ucl_array_append (top, obj); + ucl_array_append (obj, + ucl_object_fromstring ("Probable spam messages")); ucl_array_append (obj, ucl_object_fromdouble (data[1])); - ucl_array_append (top, obj); + ucl_array_append (top, obj); ucl_array_append (obj, ucl_object_fromstring ("Greylisted messages")); ucl_array_append (obj, ucl_object_fromdouble (data[2])); - ucl_array_append (top, obj); + ucl_array_append (top, obj); ucl_array_append (obj, ucl_object_fromstring ("Rejected messages")); ucl_array_append (obj, ucl_object_fromdouble (data[3])); - ucl_array_append (top, obj); + ucl_array_append (top, obj); } else { obj = ucl_object_typed_new (UCL_ARRAY); ucl_array_append (obj, ucl_object_fromstring ("Scanned messages")); ucl_array_append (obj, ucl_object_fromdouble (0)); - ucl_array_append (top, obj); + ucl_array_append (top, obj); } rspamd_controller_send_ucl (conn_ent, top); @@ -704,24 +754,24 @@ rspamd_controller_handle_pie_chart (struct rspamd_http_connection_entry *conn_en * request: /history * headers: Password * reply: json [ - * { label: "Foo", data: 11 }, - * { label: "Bar", data: 20 }, - * {...} + * { label: "Foo", data: 11 }, + * { label: "Bar", data: 20 }, + * {...} * ] */ static int rspamd_controller_handle_history (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - struct rspamd_controller_worker_ctx *ctx; - struct roll_history_row *row; - struct roll_history copied_history; - gint i, rows_proc, row_num; - struct tm *tm; - gchar timebuf[32]; - gchar ip_buf[INET6_ADDRSTRLEN]; - ucl_object_t *top, *obj; + struct rspamd_controller_session *session = conn_ent->ud; + struct rspamd_controller_worker_ctx *ctx; + struct roll_history_row *row; + struct roll_history copied_history; + gint i, rows_proc, row_num; + struct tm *tm; + gchar timebuf[32]; + gchar ip_buf[INET6_ADDRSTRLEN]; + ucl_object_t *top, *obj; ctx = session->ctx; @@ -740,7 +790,7 @@ rspamd_controller_handle_history (struct rspamd_http_connection_entry *conn_ent, /* Go through all rows */ row_num = copied_history.cur_row; - for (i = 0, rows_proc = 0; i < HISTORY_MAX_ROWS; i ++, row_num ++) { + for (i = 0, rows_proc = 0; i < HISTORY_MAX_ROWS; i++, row_num++) { if (row_num == HISTORY_MAX_ROWS) { row_num = 0; } @@ -751,30 +801,44 @@ rspamd_controller_handle_history (struct rspamd_http_connection_entry *conn_ent, strftime (timebuf, sizeof (timebuf), "%F %H:%M:%S", tm); #ifdef HAVE_INET_PTON if (row->from_addr.ipv6) { - inet_ntop (AF_INET6, &row->from_addr.d.in6, ip_buf, sizeof (ip_buf)); + inet_ntop (AF_INET6, &row->from_addr.d.in6, ip_buf, + sizeof (ip_buf)); } else { - inet_ntop (AF_INET, &row->from_addr.d.in4, ip_buf, sizeof (ip_buf)); + inet_ntop (AF_INET, &row->from_addr.d.in4, ip_buf, + sizeof (ip_buf)); } #else - rspamd_strlcpy (ip_buf, inet_ntoa (task->from_addr), sizeof (ip_buf)); + rspamd_strlcpy (ip_buf, inet_ntoa (task->from_addr), + sizeof (ip_buf)); #endif obj = ucl_object_typed_new (UCL_OBJECT); - ucl_object_insert_key (obj, ucl_object_fromstring (timebuf), "time", 0, false); - ucl_object_insert_key (obj, ucl_object_fromstring (row->message_id), "id", 0, false); - ucl_object_insert_key (obj, ucl_object_fromstring (ip_buf), "ip", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + timebuf), "time", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + row->message_id), "id", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + ip_buf), "ip", 0, false); + ucl_object_insert_key (obj, + ucl_object_fromstring (str_action_metric ( + row->action)), "action", 0, false); + ucl_object_insert_key (obj, ucl_object_fromdouble ( + row->score), "score", 0, false); ucl_object_insert_key (obj, - ucl_object_fromstring (str_action_metric (row->action)), "action", 0, false); - ucl_object_insert_key (obj, ucl_object_fromdouble (row->score), "score", 0, false); - ucl_object_insert_key (obj, ucl_object_fromdouble (row->required_score), "required_score", 0, false); - ucl_object_insert_key (obj, ucl_object_fromstring (row->symbols), "symbols", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (row->len), "size", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (row->scan_time), "scan_time", 0, false); + ucl_object_fromdouble ( + row->required_score), "required_score", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + row->symbols), "symbols", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + row->len), "size", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + row->scan_time), "scan_time", 0, false); if (row->user[0] != '\0') { - ucl_object_insert_key (obj, ucl_object_fromstring (row->user), "user", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + row->user), "user", 0, false); } ucl_array_append (top, obj); - rows_proc ++; + rows_proc++; } } @@ -787,10 +851,10 @@ rspamd_controller_handle_history (struct rspamd_http_connection_entry *conn_ent, static gboolean rspamd_controller_learn_fin_task (void *ud) { - struct rspamd_task *task = ud; - struct rspamd_controller_session *session; - struct rspamd_http_connection_entry *conn_ent; - GError *err = NULL; + struct rspamd_task *task = ud; + struct rspamd_controller_session *session; + struct rspamd_http_connection_entry *conn_ent; + GError *err = NULL; conn_ent = task->fin_arg; session = conn_ent->ud; @@ -808,8 +872,8 @@ rspamd_controller_learn_fin_task (void *ud) static gboolean rspamd_controller_check_fin_task (void *ud) { - struct rspamd_task *task = ud; - struct rspamd_http_connection_entry *conn_ent; + struct rspamd_task *task = ud; + struct rspamd_http_connection_entry *conn_ent; struct rspamd_http_message *msg; conn_ent = task->fin_arg; @@ -819,22 +883,24 @@ rspamd_controller_check_fin_task (void *ud) rspamd_protocol_http_reply (msg, task); rspamd_http_connection_reset (conn_ent->conn); rspamd_http_connection_write_message (conn_ent->conn, msg, NULL, - "application/json", conn_ent, conn_ent->conn->fd, conn_ent->rt->ptv, - conn_ent->rt->ev_base); + "application/json", conn_ent, conn_ent->conn->fd, conn_ent->rt->ptv, + conn_ent->rt->ev_base); conn_ent->is_reply = TRUE; return TRUE; } static int -rspamd_controller_handle_learn_common (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, gboolean is_spam) +rspamd_controller_handle_learn_common ( + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg, + gboolean is_spam) { - struct rspamd_controller_session *session = conn_ent->ud; - struct rspamd_controller_worker_ctx *ctx; - struct rspamd_classifier_config *cl; - struct rspamd_task *task; - const gchar *classifier; + struct rspamd_controller_session *session = conn_ent->ud; + struct rspamd_controller_worker_ctx *ctx; + struct rspamd_classifier_config *cl; + struct rspamd_task *task; + const gchar *classifier; ctx = session->ctx; @@ -844,11 +910,14 @@ rspamd_controller_handle_learn_common (struct rspamd_http_connection_entry *conn if (msg->body == NULL || msg->body->len == 0) { msg_err ("got zero length body, cannot continue"); - rspamd_controller_send_error (conn_ent, 400, "Empty body is not permitted"); + rspamd_controller_send_error (conn_ent, + 400, + "Empty body is not permitted"); return 0; } - if ((classifier = rspamd_http_message_find_header (msg, "Classifier")) == NULL) { + if ((classifier = + rspamd_http_message_find_header (msg, "Classifier")) == NULL) { classifier = "bayes"; } @@ -865,8 +934,11 @@ rspamd_controller_handle_learn_common (struct rspamd_http_connection_entry *conn task->ev_base = ctx->ev_base; - task->s = new_async_session (session->pool, rspamd_controller_learn_fin_task, NULL, - rspamd_task_free_hard, task); + task->s = new_async_session (session->pool, + rspamd_controller_learn_fin_task, + NULL, + rspamd_task_free_hard, + task); task->s->wanna_die = TRUE; task->fin_arg = conn_ent; task->http_conn = rspamd_http_connection_ref (conn_ent->conn);; @@ -895,8 +967,9 @@ rspamd_controller_handle_learn_common (struct rspamd_http_connection_entry *conn * reply: json {"success":true} or {"error":"error message"} */ static int -rspamd_controller_handle_learnspam (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) +rspamd_controller_handle_learnspam ( + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg) { return rspamd_controller_handle_learn_common (conn_ent, msg, TRUE); } @@ -908,8 +981,9 @@ rspamd_controller_handle_learnspam (struct rspamd_http_connection_entry *conn_en * reply: json {"success":true} or {"error":"error message"} */ static int -rspamd_controller_handle_learnham (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) +rspamd_controller_handle_learnham ( + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg) { return rspamd_controller_handle_learn_common (conn_ent, msg, TRUE); } @@ -923,11 +997,11 @@ rspamd_controller_handle_learnham (struct rspamd_http_connection_entry *conn_ent */ static int rspamd_controller_handle_scan (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - struct rspamd_controller_worker_ctx *ctx; - struct rspamd_task *task; + struct rspamd_controller_session *session = conn_ent->ud; + struct rspamd_controller_worker_ctx *ctx; + struct rspamd_task *task; ctx = session->ctx; @@ -937,7 +1011,9 @@ rspamd_controller_handle_scan (struct rspamd_http_connection_entry *conn_ent, if (msg->body == NULL || msg->body->len == 0) { msg_err ("got zero length body, cannot continue"); - rspamd_controller_send_error (conn_ent, 400, "Empty body is not permitted"); + rspamd_controller_send_error (conn_ent, + 400, + "Empty body is not permitted"); return 0; } @@ -948,8 +1024,11 @@ rspamd_controller_handle_scan (struct rspamd_http_connection_entry *conn_ent, task->resolver = ctx->resolver; task->ev_base = ctx->ev_base; - task->s = new_async_session (session->pool, rspamd_controller_check_fin_task, NULL, - rspamd_task_free_hard, task); + task->s = new_async_session (session->pool, + rspamd_controller_check_fin_task, + NULL, + rspamd_task_free_hard, + task); task->s->wanna_die = TRUE; task->fin_arg = conn_ent; task->http_conn = rspamd_http_connection_ref (conn_ent->conn); @@ -975,18 +1054,19 @@ rspamd_controller_handle_scan (struct rspamd_http_connection_entry *conn_ent, * reply: json {"success":true} or {"error":"error message"} */ static int -rspamd_controller_handle_saveactions (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) +rspamd_controller_handle_saveactions ( + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - struct ucl_parser *parser; - struct metric *metric; - ucl_object_t *obj, *cur; - struct rspamd_controller_worker_ctx *ctx; - const gchar *error; - gdouble score; - gint i; - enum rspamd_metric_action act; + struct rspamd_controller_session *session = conn_ent->ud; + struct ucl_parser *parser; + struct metric *metric; + ucl_object_t *obj, *cur; + struct rspamd_controller_worker_ctx *ctx; + const gchar *error; + gdouble score; + gint i; + enum rspamd_metric_action act; ctx = session->ctx; @@ -996,21 +1076,26 @@ rspamd_controller_handle_saveactions (struct rspamd_http_connection_entry *conn_ if (msg->body == NULL || msg->body->len == 0) { msg_err ("got zero length body, cannot continue"); - rspamd_controller_send_error (conn_ent, 400, "Empty body is not permitted"); + rspamd_controller_send_error (conn_ent, + 400, + "Empty body is not permitted"); return 0; } metric = g_hash_table_lookup (ctx->cfg->metrics, DEFAULT_METRIC); if (metric == NULL) { msg_err ("cannot find default metric"); - rspamd_controller_send_error (conn_ent, 500, "Default metric is absent"); + rspamd_controller_send_error (conn_ent, 500, + "Default metric is absent"); return 0; } /* Now check for dynamic config */ if (!ctx->cfg->dynamic_conf) { msg_err ("dynamic conf has not been defined"); - rspamd_controller_send_error (conn_ent, 500, "No dynamic_rules setting defined"); + rspamd_controller_send_error (conn_ent, + 500, + "No dynamic_rules setting defined"); return 0; } @@ -1035,8 +1120,8 @@ rspamd_controller_handle_saveactions (struct rspamd_http_connection_entry *conn_ } cur = obj->value.av; - for (i = 0; i < 3 && cur != NULL; i ++, cur = cur->next) { - switch(i) { + for (i = 0; i < 3 && cur != NULL; i++, cur = cur->next) { + switch (i) { case 0: act = METRIC_ACTION_REJECT; break; @@ -1068,19 +1153,20 @@ rspamd_controller_handle_saveactions (struct rspamd_http_connection_entry *conn_ * reply: json {"success":true} or {"error":"error message"} */ static int -rspamd_controller_handle_savesymbols (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) +rspamd_controller_handle_savesymbols ( + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - struct ucl_parser *parser; - struct metric *metric; - ucl_object_t *obj; - const ucl_object_t *cur, *jname, *jvalue; - ucl_object_iter_t iter = NULL; - struct rspamd_controller_worker_ctx *ctx; - const gchar *error; - gdouble val; - struct symbol *sym; + struct rspamd_controller_session *session = conn_ent->ud; + struct ucl_parser *parser; + struct metric *metric; + ucl_object_t *obj; + const ucl_object_t *cur, *jname, *jvalue; + ucl_object_iter_t iter = NULL; + struct rspamd_controller_worker_ctx *ctx; + const gchar *error; + gdouble val; + struct symbol *sym; ctx = session->ctx; @@ -1090,21 +1176,26 @@ rspamd_controller_handle_savesymbols (struct rspamd_http_connection_entry *conn_ if (msg->body == NULL || msg->body->len == 0) { msg_err ("got zero length body, cannot continue"); - rspamd_controller_send_error (conn_ent, 400, "Empty body is not permitted"); + rspamd_controller_send_error (conn_ent, + 400, + "Empty body is not permitted"); return 0; } metric = g_hash_table_lookup (ctx->cfg->metrics, DEFAULT_METRIC); if (metric == NULL) { msg_err ("cannot find default metric"); - rspamd_controller_send_error (conn_ent, 500, "Default metric is absent"); + rspamd_controller_send_error (conn_ent, 500, + "Default metric is absent"); return 0; } /* Now check for dynamic config */ if (!ctx->cfg->dynamic_conf) { msg_err ("dynamic conf has not been defined"); - rspamd_controller_send_error (conn_ent, 500, "No dynamic_rules setting defined"); + rspamd_controller_send_error (conn_ent, + 500, + "No dynamic_rules setting defined"); return 0; } @@ -1138,12 +1229,15 @@ rspamd_controller_handle_savesymbols (struct rspamd_http_connection_entry *conn_ jname = ucl_object_find_key (cur, "name"); jvalue = ucl_object_find_key (cur, "value"); val = ucl_object_todouble (jvalue); - sym = g_hash_table_lookup (metric->symbols, ucl_object_tostring (jname)); + sym = + g_hash_table_lookup (metric->symbols, ucl_object_tostring (jname)); if (sym && fabs (sym->score - val) > 0.01) { if (!add_dynamic_symbol (ctx->cfg, DEFAULT_METRIC, - ucl_object_tostring (jname), val)) { - msg_err ("add symbol failed for %s", ucl_object_tostring (jname)); - rspamd_controller_send_error (conn_ent, 506, "Add symbol failed"); + ucl_object_tostring (jname), val)) { + msg_err ("add symbol failed for %s", + ucl_object_tostring (jname)); + rspamd_controller_send_error (conn_ent, 506, + "Add symbol failed"); ucl_object_unref (obj); return 0; } @@ -1166,17 +1260,17 @@ rspamd_controller_handle_savesymbols (struct rspamd_http_connection_entry *conn_ */ static int rspamd_controller_handle_savemap (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - GList *cur; - struct rspamd_map *map; - struct rspamd_controller_worker_ctx *ctx; - const gchar *idstr; - gchar *errstr; - guint32 id; - gboolean found = FALSE; - gint fd; + struct rspamd_controller_session *session = conn_ent->ud; + GList *cur; + struct rspamd_map *map; + struct rspamd_controller_worker_ctx *ctx; + const gchar *idstr; + gchar *errstr; + guint32 id; + gboolean found = FALSE; + gint fd; ctx = session->ctx; @@ -1186,7 +1280,9 @@ rspamd_controller_handle_savemap (struct rspamd_http_connection_entry *conn_ent, if (msg->body == NULL || msg->body->len == 0) { msg_err ("got zero length body, cannot continue"); - rspamd_controller_send_error (conn_ent, 400, "Empty body is not permitted"); + rspamd_controller_send_error (conn_ent, + 400, + "Empty body is not permitted"); return 0; } @@ -1262,8 +1358,10 @@ rspamd_controller_handle_savemap (struct rspamd_http_connection_entry *conn_ent, * reply: json data */ static int -rspamd_controller_handle_stat_common (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, gboolean do_reset) +rspamd_controller_handle_stat_common ( + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg, + gboolean do_reset) { struct rspamd_controller_session *session = conn_ent->ud; ucl_object_t *top, *sub; @@ -1282,13 +1380,14 @@ rspamd_controller_handle_stat_common (struct rspamd_http_connection_entry *conn_ stat = &stat_copy; top = ucl_object_typed_new (UCL_OBJECT); - ucl_object_insert_key (top, ucl_object_fromint (stat->messages_scanned), "scanned", 0, false); + ucl_object_insert_key (top, ucl_object_fromint ( + stat->messages_scanned), "scanned", 0, false); if (stat->messages_scanned > 0) { sub = ucl_object_typed_new (UCL_OBJECT); - for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i ++) { + for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i++) { ucl_object_insert_key (sub, - ucl_object_fromint (stat->actions_stat[i]), - str_action_metric (i), 0, false); + ucl_object_fromint (stat->actions_stat[i]), + str_action_metric (i), 0, false); if (i < METRIC_ACTION_GREYLIST) { spam += stat->actions_stat[i]; } @@ -1302,35 +1401,42 @@ rspamd_controller_handle_stat_common (struct rspamd_http_connection_entry *conn_ ucl_object_insert_key (top, sub, "actions", 0, false); } - ucl_object_insert_key (top, ucl_object_fromint (spam), "spam_count", 0, false); - ucl_object_insert_key (top, ucl_object_fromint (ham), "ham_count", 0, false); + ucl_object_insert_key (top, ucl_object_fromint ( + spam), "spam_count", 0, false); + ucl_object_insert_key (top, ucl_object_fromint ( + ham), "ham_count", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (stat->messages_learned), "learned", 0, false); + ucl_object_fromint (stat->messages_learned), "learned", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (stat->connections_count), "connections", 0, false); + ucl_object_fromint (stat->connections_count), "connections", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (stat->control_connections_count), - "control_connections", 0, false); + ucl_object_fromint (stat->control_connections_count), + "control_connections", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (mem_st.pools_allocated), "pools_allocated", 0, false); + ucl_object_fromint (mem_st.pools_allocated), "pools_allocated", 0, + false); ucl_object_insert_key (top, - ucl_object_fromint (mem_st.pools_freed), "pools_freed", 0, false); + ucl_object_fromint (mem_st.pools_freed), "pools_freed", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (mem_st.bytes_allocated), "bytes_allocated", 0, false); + ucl_object_fromint (mem_st.bytes_allocated), "bytes_allocated", 0, + false); ucl_object_insert_key (top, - ucl_object_fromint (mem_st.chunks_allocated), "chunks_allocated", 0, false); + ucl_object_fromint ( + mem_st.chunks_allocated), "chunks_allocated", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (mem_st.shared_chunks_allocated), - "shared_chunks_allocated", 0, false); + ucl_object_fromint (mem_st.shared_chunks_allocated), + "shared_chunks_allocated", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (mem_st.chunks_freed), "chunks_freed", 0, false); + ucl_object_fromint (mem_st.chunks_freed), "chunks_freed", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (mem_st.oversized_chunks), "chunks_oversized", 0, false); + ucl_object_fromint ( + mem_st.oversized_chunks), "chunks_oversized", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (stat->fuzzy_hashes), "fuzzy_stored", 0, false); + ucl_object_fromint (stat->fuzzy_hashes), "fuzzy_stored", 0, false); ucl_object_insert_key (top, - ucl_object_fromint (stat->fuzzy_hashes_expired), "fuzzy_expired", 0, false); + ucl_object_fromint ( + stat->fuzzy_hashes_expired), "fuzzy_expired", 0, false); /* Now write statistics for each statfile */ cur_cl = g_list_first (session->ctx->cfg->classifiers); @@ -1340,8 +1446,9 @@ rspamd_controller_handle_stat_common (struct rspamd_http_connection_entry *conn_ cur_st = g_list_first (ccf->statfiles); while (cur_st) { st = cur_st->data; - if ((statfile = statfile_pool_is_open (session->ctx->srv->statfile_pool, - st->path)) == NULL) { + if ((statfile = + statfile_pool_is_open (session->ctx->srv->statfile_pool, + st->path)) == NULL) { statfile = statfile_pool_open (session->ctx->srv->statfile_pool, st->path, st->size, FALSE); } @@ -1352,14 +1459,17 @@ rspamd_controller_handle_stat_common (struct rspamd_http_connection_entry *conn_ total = statfile_get_total_blocks (statfile); statfile_get_revision (statfile, &rev, &ti); ucl_object_insert_key (obj, - ucl_object_fromstring (st->symbol), "symbol", 0, false); + ucl_object_fromstring (st->symbol), "symbol", 0, false); if (st->label != NULL) { ucl_object_insert_key (obj, - ucl_object_fromstring (st->label), "label", 0, false); + ucl_object_fromstring (st->label), "label", 0, false); } - ucl_object_insert_key (obj, ucl_object_fromint (rev), "revision", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (used), "used", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (total), "total", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + rev), "revision", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + used), "used", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint ( + total), "total", 0, false); ucl_array_append (sub, obj); } @@ -1386,9 +1496,9 @@ rspamd_controller_handle_stat_common (struct rspamd_http_connection_entry *conn_ static int rspamd_controller_handle_stat (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; + struct rspamd_controller_session *session = conn_ent->ud; if (!rspamd_controller_check_password (conn_ent, session, msg, FALSE)) { return 0; @@ -1398,10 +1508,11 @@ rspamd_controller_handle_stat (struct rspamd_http_connection_entry *conn_ent, } static int -rspamd_controller_handle_statreset (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) +rspamd_controller_handle_statreset ( + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; + struct rspamd_controller_session *session = conn_ent->ud; if (!rspamd_controller_check_password (conn_ent, session, msg, TRUE)) { return 0; @@ -1413,17 +1524,17 @@ rspamd_controller_handle_statreset (struct rspamd_http_connection_entry *conn_en static ucl_object_t * rspamd_controller_cache_item_to_ucl (struct cache_item *item) { - ucl_object_t *obj; + ucl_object_t *obj; obj = ucl_object_typed_new (UCL_OBJECT); ucl_object_insert_key (obj, ucl_object_fromstring (item->s->symbol), - "symbol", 0, false); + "symbol", 0, false); ucl_object_insert_key (obj, ucl_object_fromdouble (item->s->weight), - "weight", 0, false); - ucl_object_insert_key (obj, ucl_object_fromint (item->s->frequency), - "frequency", 0, false); + "weight", 0, false); + ucl_object_insert_key (obj, ucl_object_fromint (item->s->frequency), + "frequency", 0, false); ucl_object_insert_key (obj, ucl_object_fromdouble (item->s->avg_time), - "time", 0, false); + "time", 0, false); return obj; } @@ -1435,14 +1546,15 @@ rspamd_controller_cache_item_to_ucl (struct cache_item *item) * reply: json array of all counters */ static int -rspamd_controller_handle_counters (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) +rspamd_controller_handle_counters ( + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - ucl_object_t *top; - GList *cur; - struct cache_item *item; - struct symbols_cache *cache; + struct rspamd_controller_session *session = conn_ent->ud; + ucl_object_t *top; + GList *cur; + struct cache_item *item; + struct symbols_cache *cache; if (!rspamd_controller_check_password (conn_ent, session, msg, FALSE)) { return 0; @@ -1455,7 +1567,8 @@ rspamd_controller_handle_counters (struct rspamd_http_connection_entry *conn_ent while (cur) { item = cur->data; if (!item->is_callback) { - ucl_array_append (top, rspamd_controller_cache_item_to_ucl (item)); + ucl_array_append (top, rspamd_controller_cache_item_to_ucl ( + item)); } cur = g_list_next (cur); } @@ -1463,7 +1576,8 @@ rspamd_controller_handle_counters (struct rspamd_http_connection_entry *conn_ent while (cur) { item = cur->data; if (!item->is_callback) { - ucl_array_append (top, rspamd_controller_cache_item_to_ucl (item)); + ucl_array_append (top, rspamd_controller_cache_item_to_ucl ( + item)); } cur = g_list_next (cur); } @@ -1476,10 +1590,10 @@ rspamd_controller_handle_counters (struct rspamd_http_connection_entry *conn_ent static int rspamd_controller_handle_custom (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_controller_session *session = conn_ent->ud; - struct rspamd_custom_controller_command *cmd; + struct rspamd_controller_session *session = conn_ent->ud; + struct rspamd_custom_controller_command *cmd; cmd = g_hash_table_lookup (session->ctx->custom_commands, msg->url->str); if (cmd == NULL || cmd->handler == NULL) { @@ -1488,12 +1602,15 @@ rspamd_controller_handle_custom (struct rspamd_http_connection_entry *conn_ent, return 0; } - if (!rspamd_controller_check_password (conn_ent, session, msg, cmd->privilleged)) { + if (!rspamd_controller_check_password (conn_ent, session, msg, + cmd->privilleged)) { return 0; } if (cmd->require_message && (msg->body == NULL || msg->body->len == 0)) { msg_err ("got zero length body, cannot continue"); - rspamd_controller_send_error (conn_ent, 400, "Empty body is not permitted"); + rspamd_controller_send_error (conn_ent, + 400, + "Empty body is not permitted"); return 0; } @@ -1501,7 +1618,8 @@ rspamd_controller_handle_custom (struct rspamd_http_connection_entry *conn_ent, } static void -rspamd_controller_error_handler (struct rspamd_http_connection_entry *conn_ent, GError *err) +rspamd_controller_error_handler (struct rspamd_http_connection_entry *conn_ent, + GError *err) { msg_err ("http error occurred: %s", err->message); } @@ -1509,7 +1627,7 @@ rspamd_controller_error_handler (struct rspamd_http_connection_entry *conn_ent, static void rspamd_controller_finish_handler (struct rspamd_http_connection_entry *conn_ent) { - struct rspamd_controller_session *session = conn_ent->ud; + struct rspamd_controller_session *session = conn_ent->ud; if (session->task != NULL) { destroy_session (session->task->s); @@ -1524,16 +1642,16 @@ rspamd_controller_finish_handler (struct rspamd_http_connection_entry *conn_ent) static void rspamd_controller_accept_socket (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *) arg; - struct rspamd_controller_worker_ctx *ctx; - struct rspamd_controller_session *nsession; - rspamd_inet_addr_t addr; - gint nfd; + struct rspamd_worker *worker = (struct rspamd_worker *) arg; + struct rspamd_controller_worker_ctx *ctx; + struct rspamd_controller_session *nsession; + rspamd_inet_addr_t addr; + gint nfd; ctx = worker->ctx; if ((nfd = - rspamd_accept_from_socket (fd, &addr)) == -1) { + rspamd_accept_from_socket (fd, &addr)) == -1) { msg_warn ("accept failed: %s", strerror (errno)); return; } @@ -1543,8 +1661,8 @@ rspamd_controller_accept_socket (gint fd, short what, void *arg) } msg_info ("accepted connection from %s port %d", - rspamd_inet_address_to_string (&addr), - rspamd_inet_address_get_port (&addr)); + rspamd_inet_address_to_string (&addr), + rspamd_inet_address_get_port (&addr)); nsession = g_slice_alloc0 (sizeof (struct rspamd_controller_session)); nsession->pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); @@ -1558,8 +1676,8 @@ rspamd_controller_accept_socket (gint fd, short what, void *arg) gpointer init_controller_worker (struct rspamd_config *cfg) { - struct rspamd_controller_worker_ctx *ctx; - GQuark type; + struct rspamd_controller_worker_ctx *ctx; + GQuark type; type = g_quark_try_string ("controller"); @@ -1568,35 +1686,37 @@ init_controller_worker (struct rspamd_config *cfg) ctx->timeout = DEFAULT_WORKER_IO_TIMEOUT; rspamd_rcl_register_worker_option (cfg, type, "password", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, password), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, password), 0); rspamd_rcl_register_worker_option (cfg, type, "enable_password", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, password), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, password), 0); rspamd_rcl_register_worker_option (cfg, type, "ssl", - rspamd_rcl_parse_struct_boolean, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, use_ssl), 0); + rspamd_rcl_parse_struct_boolean, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, use_ssl), 0); rspamd_rcl_register_worker_option (cfg, type, "ssl_cert", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, ssl_cert), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, ssl_cert), 0); rspamd_rcl_register_worker_option (cfg, type, "ssl_key", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, ssl_key), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, ssl_key), 0); rspamd_rcl_register_worker_option (cfg, type, "timeout", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, timeout), RSPAMD_CL_FLAG_TIME_INTEGER); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, + timeout), RSPAMD_CL_FLAG_TIME_INTEGER); rspamd_rcl_register_worker_option (cfg, type, "secure_ip", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, secure_ip), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, secure_ip), 0); rspamd_rcl_register_worker_option (cfg, type, "static_dir", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, static_files_dir), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_worker_ctx, + static_files_dir), 0); return ctx; } @@ -1615,7 +1735,9 @@ start_controller_worker (struct rspamd_worker *worker) gpointer key, value; - ctx->ev_base = rspamd_prepare_worker (worker, "controller", rspamd_controller_accept_socket); + ctx->ev_base = rspamd_prepare_worker (worker, + "controller", + rspamd_controller_accept_socket); msec_to_tv (ctx->timeout, &ctx->io_tv); ctx->start_time = time (NULL); @@ -1625,10 +1747,13 @@ start_controller_worker (struct rspamd_worker *worker) ctx->custom_commands = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); if (ctx->secure_ip != NULL) { - if (!add_map (worker->srv->cfg, ctx->secure_ip, "Allow webui access from the specified IP", - read_radix_list, fin_radix_list, (void **)&ctx->secure_map)) { - if (!rspamd_config_parse_ip_list (ctx->secure_ip, &ctx->secure_map)) { - msg_warn ("cannot load or parse ip list from '%s'", ctx->secure_ip); + if (!add_map (worker->srv->cfg, ctx->secure_ip, + "Allow webui access from the specified IP", + read_radix_list, fin_radix_list, (void **)&ctx->secure_map)) { + if (!rspamd_config_parse_ip_list (ctx->secure_ip, + &ctx->secure_map)) { + msg_warn ("cannot load or parse ip list from '%s'", + ctx->secure_ip); } } } @@ -1638,23 +1763,57 @@ start_controller_worker (struct rspamd_worker *worker) ctx->static_files_dir); /* Add callbacks for different methods */ - rspamd_http_router_add_path (ctx->http, PATH_AUTH, rspamd_controller_handle_auth); - rspamd_http_router_add_path (ctx->http, PATH_SYMBOLS, rspamd_controller_handle_symbols); - rspamd_http_router_add_path (ctx->http, PATH_ACTIONS, rspamd_controller_handle_actions); - rspamd_http_router_add_path (ctx->http, PATH_MAPS, rspamd_controller_handle_maps); - rspamd_http_router_add_path (ctx->http, PATH_GET_MAP, rspamd_controller_handle_get_map); - rspamd_http_router_add_path (ctx->http, PATH_PIE_CHART, rspamd_controller_handle_pie_chart); - rspamd_http_router_add_path (ctx->http, PATH_HISTORY, rspamd_controller_handle_history); - rspamd_http_router_add_path (ctx->http, PATH_LEARN_SPAM, rspamd_controller_handle_learnspam); - rspamd_http_router_add_path (ctx->http, PATH_LEARN_HAM, rspamd_controller_handle_learnham); - rspamd_http_router_add_path (ctx->http, PATH_SAVE_ACTIONS, rspamd_controller_handle_saveactions); - rspamd_http_router_add_path (ctx->http, PATH_SAVE_SYMBOLS, rspamd_controller_handle_savesymbols); - rspamd_http_router_add_path (ctx->http, PATH_SAVE_MAP, rspamd_controller_handle_savemap); - rspamd_http_router_add_path (ctx->http, PATH_SCAN, rspamd_controller_handle_scan); - rspamd_http_router_add_path (ctx->http, PATH_CHECK, rspamd_controller_handle_scan); - rspamd_http_router_add_path (ctx->http, PATH_STAT, rspamd_controller_handle_stat); - rspamd_http_router_add_path (ctx->http, PATH_STAT_RESET, rspamd_controller_handle_statreset); - rspamd_http_router_add_path (ctx->http, PATH_COUNTERS, rspamd_controller_handle_counters); + rspamd_http_router_add_path (ctx->http, + PATH_AUTH, + rspamd_controller_handle_auth); + rspamd_http_router_add_path (ctx->http, + PATH_SYMBOLS, + rspamd_controller_handle_symbols); + rspamd_http_router_add_path (ctx->http, + PATH_ACTIONS, + rspamd_controller_handle_actions); + rspamd_http_router_add_path (ctx->http, + PATH_MAPS, + rspamd_controller_handle_maps); + rspamd_http_router_add_path (ctx->http, + PATH_GET_MAP, + rspamd_controller_handle_get_map); + rspamd_http_router_add_path (ctx->http, + PATH_PIE_CHART, + rspamd_controller_handle_pie_chart); + rspamd_http_router_add_path (ctx->http, + PATH_HISTORY, + rspamd_controller_handle_history); + rspamd_http_router_add_path (ctx->http, + PATH_LEARN_SPAM, + rspamd_controller_handle_learnspam); + rspamd_http_router_add_path (ctx->http, + PATH_LEARN_HAM, + rspamd_controller_handle_learnham); + rspamd_http_router_add_path (ctx->http, + PATH_SAVE_ACTIONS, + rspamd_controller_handle_saveactions); + rspamd_http_router_add_path (ctx->http, + PATH_SAVE_SYMBOLS, + rspamd_controller_handle_savesymbols); + rspamd_http_router_add_path (ctx->http, + PATH_SAVE_MAP, + rspamd_controller_handle_savemap); + rspamd_http_router_add_path (ctx->http, + PATH_SCAN, + rspamd_controller_handle_scan); + rspamd_http_router_add_path (ctx->http, + PATH_CHECK, + rspamd_controller_handle_scan); + rspamd_http_router_add_path (ctx->http, + PATH_STAT, + rspamd_controller_handle_stat); + rspamd_http_router_add_path (ctx->http, + PATH_STAT_RESET, + rspamd_controller_handle_statreset); + rspamd_http_router_add_path (ctx->http, + PATH_COUNTERS, + rspamd_controller_handle_counters); /* Attach plugins */ cur = g_list_first (ctx->cfg->filters); @@ -1662,21 +1821,29 @@ start_controller_worker (struct rspamd_worker *worker) f = cur->data; mctx = g_hash_table_lookup (ctx->cfg->c_modules, f->module->name); if (mctx != NULL && f->module->module_attach_controller_func != NULL) { - f->module->module_attach_controller_func (mctx, ctx->custom_commands); + f->module->module_attach_controller_func (mctx, + ctx->custom_commands); } cur = g_list_next (cur); } g_hash_table_iter_init (&iter, ctx->custom_commands); while (g_hash_table_iter_next (&iter, &key, &value)) { - rspamd_http_router_add_path (ctx->http, key, rspamd_controller_handle_custom); + rspamd_http_router_add_path (ctx->http, + key, + rspamd_controller_handle_custom); } #if 0 - rspamd_http_router_add_path (ctx->http, PATH_GRAPH, rspamd_controller_handle_graph, ctx); + rspamd_http_router_add_path (ctx->http, + PATH_GRAPH, + rspamd_controller_handle_graph, + ctx); #endif - ctx->resolver = dns_resolver_init (worker->srv->logger, ctx->ev_base, worker->srv->cfg); + ctx->resolver = dns_resolver_init (worker->srv->logger, + ctx->ev_base, + worker->srv->cfg); /* Maps events */ start_map_watch (worker->srv->cfg, ctx->ev_base); diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c index 7fca37566..c32ed61fa 100644 --- a/src/fuzzy_storage.c +++ b/src/fuzzy_storage.c @@ -58,55 +58,55 @@ /* Current version of fuzzy hash file format */ #define CURRENT_FUZZY_VERSION 1 -#define INVALID_NODE_TIME (guint64)-1 +#define INVALID_NODE_TIME (guint64) - 1 /* Init functions */ gpointer init_fuzzy (struct rspamd_config *cfg); void start_fuzzy (struct rspamd_worker *worker); worker_t fuzzy_worker = { - "fuzzy", /* Name */ - init_fuzzy, /* Init function */ - start_fuzzy, /* Start function */ - TRUE, /* No socket */ - TRUE, /* Unique */ - TRUE, /* Threaded */ - FALSE, /* Non killable */ - SOCK_DGRAM /* UDP socket */ + "fuzzy", /* Name */ + init_fuzzy, /* Init function */ + start_fuzzy, /* Start function */ + TRUE, /* No socket */ + TRUE, /* Unique */ + TRUE, /* Threaded */ + FALSE, /* Non killable */ + SOCK_DGRAM /* UDP socket */ }; -static GQueue *hashes[BUCKETS]; -static GQueue *frequent; -static GHashTable *static_hash; -static rspamd_bloom_filter_t *bf; +static GQueue *hashes[BUCKETS]; +static GQueue *frequent; +static GHashTable *static_hash; +static rspamd_bloom_filter_t *bf; /* Number of cache modifications */ -static guint32 mods = 0; +static guint32 mods = 0; /* For evtimer */ -static struct timeval tmv; -static struct event tev; -static struct rspamd_stat *server_stat; +static struct timeval tmv; +static struct event tev; +static struct rspamd_stat *server_stat; struct rspamd_fuzzy_storage_ctx { - gboolean strict_hash; - char *hashfile; - gdouble expire; - guint32 frequent_score; - guint32 max_mods; - radix_tree_t *update_ips; - gchar *update_map; - struct event_base *ev_base; - rspamd_rwlock_t *tree_lock; - rspamd_mutex_t *update_mtx; - GCond *update_cond; - GThread *update_thread; + gboolean strict_hash; + char *hashfile; + gdouble expire; + guint32 frequent_score; + guint32 max_mods; + radix_tree_t *update_ips; + gchar *update_map; + struct event_base *ev_base; + rspamd_rwlock_t *tree_lock; + rspamd_mutex_t *update_mtx; + GCond *update_cond; + GThread *update_thread; }; struct rspamd_fuzzy_node { - gint32 value; - gint32 flag; - guint64 time; - fuzzy_hash_t h; + gint32 value; + gint32 flag; + guint64 time; + fuzzy_hash_t h; }; struct fuzzy_session { @@ -152,20 +152,20 @@ rspamd_fuzzy_free_node (gpointer n) */ static void expire_nodes (gpointer *to_expire, gint expired_num, - struct rspamd_fuzzy_storage_ctx *ctx) + struct rspamd_fuzzy_storage_ctx *ctx) { - gint i; - struct rspamd_fuzzy_node *node; - GList *cur; - GQueue *head; + gint i; + struct rspamd_fuzzy_node *node; + GList *cur; + GQueue *head; - for (i = 0; i < expired_num; i ++) { + for (i = 0; i < expired_num; i++) { if (ctx->strict_hash) { node = (struct rspamd_fuzzy_node *)to_expire[i]; if (node->time != INVALID_NODE_TIME) { - server_stat->fuzzy_hashes_expired ++; + server_stat->fuzzy_hashes_expired++; } - server_stat->fuzzy_hashes --; + server_stat->fuzzy_hashes--; rspamd_bloom_del (bf, node->h.hash_pipe); g_hash_table_remove (static_hash, node->h.hash_pipe); } @@ -176,7 +176,7 @@ expire_nodes (gpointer *to_expire, gint expired_num, g_queue_delete_link (head, cur); rspamd_bloom_del (bf, node->h.hash_pipe); if (node->time != INVALID_NODE_TIME) { - server_stat->fuzzy_hashes_expired ++; + server_stat->fuzzy_hashes_expired++; } server_stat->fuzzy_hashes--; g_slice_free1 (sizeof(struct rspamd_fuzzy_node), node); @@ -187,20 +187,20 @@ expire_nodes (gpointer *to_expire, gint expired_num, static gpointer sync_cache (gpointer ud) { - static const int max_expired = 8192; - struct rspamd_worker *wrk = ud; - gint fd, i, expired_num = 0; - gchar *filename, header[4]; - GList *cur; - struct rspamd_fuzzy_node *node; - gpointer *nodes_expired = NULL; - guint64 expire, now; + static const int max_expired = 8192; + struct rspamd_worker *wrk = ud; + gint fd, i, expired_num = 0; + gchar *filename, header[4]; + GList *cur; + struct rspamd_fuzzy_node *node; + gpointer *nodes_expired = NULL; + guint64 expire, now; struct rspamd_fuzzy_storage_ctx *ctx; - GHashTableIter iter; + GHashTableIter iter; ctx = wrk->ctx; - for (;;) { + for (;; ) { rspamd_mutex_lock (ctx->update_mtx); @@ -221,9 +221,9 @@ sync_cache (gpointer ud) 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)); + S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) == -1) { + msg_err ( + "cannot create hash file %s: %s", filename, strerror (errno)); rspamd_mutex_unlock (ctx->update_mtx); if (wanna_die) { return NULL; @@ -239,8 +239,10 @@ sync_cache (gpointer ud) memcpy (header, FUZZY_FILE_MAGIC, 3); header[3] = (gchar) CURRENT_FUZZY_VERSION; if (write (fd, header, sizeof(header)) == -1) { - msg_err( - "cannot write file %s while writing header: %s", filename, strerror (errno)); + msg_err ( + "cannot write file %s while writing header: %s", + filename, + strerror (errno)); goto end; } @@ -249,18 +251,21 @@ sync_cache (gpointer ud) g_hash_table_iter_init (&iter, static_hash); while (g_hash_table_iter_next (&iter, NULL, (void **)&node)) { - if (node->time == INVALID_NODE_TIME || now - node->time > expire) { + if (node->time == INVALID_NODE_TIME || now - node->time > + expire) { if (nodes_expired == NULL) { - nodes_expired = g_malloc (max_expired * sizeof (gpointer)); + nodes_expired = g_malloc ( + max_expired * sizeof (gpointer)); } if (expired_num < max_expired) { - nodes_expired[expired_num ++] = node; + nodes_expired[expired_num++] = node; } continue; } if (write (fd, node, sizeof (struct rspamd_fuzzy_node)) == -1) { - msg_err ("cannot write file %s: %s", filename, strerror (errno)); + msg_err ("cannot write file %s: %s", filename, + strerror (errno)); goto end; } } @@ -272,7 +277,8 @@ sync_cache (gpointer ud) while (cur) { node = cur->data; if (write (fd, node, sizeof(struct rspamd_fuzzy_node)) == -1) { - msg_err("cannot write file %s: %s", filename, strerror (errno)); + msg_err ("cannot write file %s: %s", filename, + strerror (errno)); } cur = g_list_next (cur); } @@ -282,18 +288,21 @@ sync_cache (gpointer ud) node = cur->data; if (now - node->time > expire) { if (nodes_expired == NULL) { - nodes_expired = g_malloc (max_expired * sizeof (gpointer)); + nodes_expired = + g_malloc (max_expired * sizeof (gpointer)); } if (expired_num < max_expired) { - nodes_expired[expired_num ++] = cur; + nodes_expired[expired_num++] = cur; } cur = g_list_next (cur); continue; } - if (write (fd, node, sizeof(struct rspamd_fuzzy_node)) == -1) { - msg_err( - "cannot write file %s: %s", filename, strerror (errno)); + if (write (fd, node, + sizeof(struct rspamd_fuzzy_node)) == -1) { + msg_err ( + "cannot write file %s: %s", filename, + strerror (errno)); goto end; } cur = g_list_next (cur); @@ -328,9 +337,9 @@ end: static void sigterm_handler (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *)arg; + struct rspamd_worker *worker = (struct rspamd_worker *)arg; struct rspamd_fuzzy_storage_ctx *ctx; - static struct timeval tv = { + static struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; @@ -354,9 +363,9 @@ sigterm_handler (gint fd, short what, void *arg) static void sigusr2_handler (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *)arg; + struct rspamd_worker *worker = (struct rspamd_worker *)arg; /* Do not accept new connections, preparing to end worker's process */ - struct timeval tv; + struct timeval tv; struct rspamd_fuzzy_storage_ctx *ctx; ctx = worker->ctx; @@ -376,20 +385,20 @@ sigusr2_handler (gint fd, short what, void *arg) return; } -static gboolean +static gboolean read_hashes_file (struct rspamd_worker *wrk) { - gint r, fd, i, version = 0; - struct stat st; - gchar *filename, header[4]; - gboolean touch_stat = TRUE; - struct rspamd_fuzzy_node *node; + gint r, fd, i, version = 0; + struct stat st; + 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; - fuzzy_hash_t h; - } legacy_node; + gint32 value; + guint64 time; + fuzzy_hash_t h; + } legacy_node; if (server_stat->fuzzy_hashes != 0) { touch_stat = FALSE; @@ -419,20 +428,24 @@ read_hashes_file (struct rspamd_worker *wrk) close (fd); return FALSE; } - msg_info ("reading fuzzy hashes storage file of version %d of size %d", - version, (gint)(st.st_size - sizeof (header)) / sizeof (struct rspamd_fuzzy_node)); + msg_info ( + "reading fuzzy hashes storage file of version %d of size %d", + version, + (gint)(st.st_size - + sizeof (header)) / sizeof (struct rspamd_fuzzy_node)); } else { /* Old version */ version = 0; - msg_info ("got old version of fuzzy hashes storage, it would be converted to new version %d automatically", - CURRENT_FUZZY_VERSION); + msg_info ( + "got old version of fuzzy hashes storage, it would be converted to new version %d automatically", + CURRENT_FUZZY_VERSION); /* Rewind file */ (void)lseek (fd, 0, SEEK_SET); } } - for (;;) { + for (;; ) { node = g_slice_alloc (sizeof (struct rspamd_fuzzy_node)); if (version == 0) { r = read (fd, &legacy_node, sizeof (legacy_node)); @@ -463,14 +476,14 @@ read_hashes_file (struct rspamd_worker *wrk) } rspamd_bloom_add (bf, node->h.hash_pipe); if (touch_stat) { - server_stat->fuzzy_hashes ++; + server_stat->fuzzy_hashes++; } } if (!ctx->strict_hash) { /* Sort everything */ g_queue_sort (frequent, compare_nodes, NULL); - for (i = 0; i < BUCKETS; i ++) { + for (i = 0; i < BUCKETS; i++) { g_queue_sort (hashes[i], compare_nodes, NULL); } } @@ -479,7 +492,8 @@ read_hashes_file (struct rspamd_worker *wrk) close (fd); if (r > 0) { - msg_warn ("ignore garbage at the end of file, length of garbage: %d", r); + msg_warn ("ignore garbage at the end of file, length of garbage: %d", + r); } else if (r == -1) { msg_err ("cannot open read file %s: %s", filename, strerror (errno)); @@ -491,11 +505,11 @@ 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, - guint64 time, struct rspamd_fuzzy_storage_ctx *ctx) + guint64 time, struct rspamd_fuzzy_storage_ctx *ctx) { - GList *cur; - struct rspamd_fuzzy_node *h; - gint prob = 0; + GList *cur; + struct rspamd_fuzzy_node *h; + gint prob = 0; if (ctx->strict_hash) { h = g_hash_table_lookup (static_hash, s->hash_pipe); @@ -506,7 +520,7 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value, } else if (update_value == 0 && time - h->time > ctx->expire) { h->time = INVALID_NODE_TIME; - server_stat->fuzzy_hashes_expired ++; + server_stat->fuzzy_hashes_expired++; return NULL; } else if (h->h.block_size== s->block_size) { @@ -533,7 +547,7 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value, } else if (time - h->time > ctx->expire) { h->time = INVALID_NODE_TIME; - server_stat->fuzzy_hashes_expired ++; + server_stat->fuzzy_hashes_expired++; return NULL; } return h; @@ -555,7 +569,7 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value, } else if (time - h->time > ctx->expire) { h->time = INVALID_NODE_TIME; - server_stat->fuzzy_hashes_expired ++; + server_stat->fuzzy_hashes_expired++; return NULL; } if (h->value > (gint)ctx->frequent_score) { @@ -572,11 +586,14 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value, return NULL; } -static gint -process_check_command (struct fuzzy_cmd *cmd, gint *flag, guint64 time, struct rspamd_fuzzy_storage_ctx *ctx) +static gint +process_check_command (struct fuzzy_cmd *cmd, + gint *flag, + guint64 time, + struct rspamd_fuzzy_storage_ctx *ctx) { - fuzzy_hash_t s; - struct rspamd_fuzzy_node *h; + fuzzy_hash_t s; + struct rspamd_fuzzy_node *h; if (!rspamd_bloom_check (bf, cmd->hash)) { @@ -591,7 +608,9 @@ process_check_command (struct fuzzy_cmd *cmd, gint *flag, guint64 time, struct r h = check_hash_node (NULL, &s, 0, time, ctx); } else { - h = check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, 0, time, ctx); + h = + check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, 0, time, + ctx); } rspamd_rwlock_reader_unlock (ctx->tree_lock); @@ -604,22 +623,28 @@ process_check_command (struct fuzzy_cmd *cmd, gint *flag, guint64 time, struct r } } -static gboolean -update_hash (struct fuzzy_cmd *cmd, guint64 time, struct rspamd_fuzzy_storage_ctx *ctx) +static gboolean +update_hash (struct fuzzy_cmd *cmd, + guint64 time, + struct rspamd_fuzzy_storage_ctx *ctx) { - fuzzy_hash_t s; - struct rspamd_fuzzy_node *n; + fuzzy_hash_t s; + struct rspamd_fuzzy_node *n; memcpy (s.hash_pipe, cmd->hash, sizeof (s.hash_pipe)); s.block_size = cmd->blocksize; - mods ++; + mods++; rspamd_rwlock_writer_lock (ctx->tree_lock); if (ctx->strict_hash) { n = check_hash_node (NULL, &s, cmd->value, time, ctx); } else { - n = check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, cmd->value, time, ctx); + n = check_hash_node (hashes[cmd->blocksize % BUCKETS], + &s, + cmd->value, + time, + ctx); } rspamd_rwlock_writer_unlock (ctx->tree_lock); @@ -630,10 +655,12 @@ update_hash (struct fuzzy_cmd *cmd, guint64 time, struct rspamd_fuzzy_storage_ct return FALSE; } -static gboolean -process_write_command (struct fuzzy_cmd *cmd, guint64 time, struct rspamd_fuzzy_storage_ctx *ctx) +static gboolean +process_write_command (struct fuzzy_cmd *cmd, + guint64 time, + struct rspamd_fuzzy_storage_ctx *ctx) { - struct rspamd_fuzzy_node *h; + struct rspamd_fuzzy_node *h; if (rspamd_bloom_check (bf, cmd->hash)) { if (update_hash (cmd, time, ctx)) { @@ -659,25 +686,26 @@ process_write_command (struct fuzzy_cmd *cmd, guint64 time, struct rspamd_fuzzy_ rspamd_rwlock_writer_unlock (ctx->tree_lock); mods++; - server_stat->fuzzy_hashes ++; + server_stat->fuzzy_hashes++; msg_info ("fuzzy hash was successfully added"); return TRUE; } static gboolean -delete_hash (GQueue *hash, fuzzy_hash_t *s, struct rspamd_fuzzy_storage_ctx *ctx) +delete_hash (GQueue *hash, fuzzy_hash_t *s, + struct rspamd_fuzzy_storage_ctx *ctx) { - GList *cur, *tmp; - struct rspamd_fuzzy_node *h; - gboolean res = FALSE; + GList *cur, *tmp; + struct rspamd_fuzzy_node *h; + gboolean res = FALSE; if (ctx->strict_hash) { rspamd_rwlock_writer_lock (ctx->tree_lock); if (g_hash_table_remove (static_hash, s->hash_pipe)) { rspamd_bloom_del (bf, s->hash_pipe); msg_info ("fuzzy hash was successfully deleted"); - server_stat->fuzzy_hashes --; + server_stat->fuzzy_hashes--; mods++; } rspamd_rwlock_writer_unlock (ctx->tree_lock); @@ -696,7 +724,7 @@ delete_hash (GQueue *hash, fuzzy_hash_t *s, struct rspamd_fuzzy_storage_ctx *ctx g_queue_delete_link (hash, tmp); rspamd_bloom_del (bf, s->hash_pipe); msg_info ("fuzzy hash was successfully deleted"); - server_stat->fuzzy_hashes --; + server_stat->fuzzy_hashes--; mods++; res = TRUE; continue; @@ -710,11 +738,13 @@ delete_hash (GQueue *hash, fuzzy_hash_t *s, struct rspamd_fuzzy_storage_ctx *ctx } -static gboolean -process_delete_command (struct fuzzy_cmd *cmd, guint64 time, struct rspamd_fuzzy_storage_ctx *ctx) +static gboolean +process_delete_command (struct fuzzy_cmd *cmd, + guint64 time, + struct rspamd_fuzzy_storage_ctx *ctx) { - fuzzy_hash_t s; - gboolean res = FALSE; + fuzzy_hash_t s; + gboolean res = FALSE; if (!rspamd_bloom_check (bf, cmd->hash)) { return FALSE; @@ -750,7 +780,8 @@ check_fuzzy_client (struct fuzzy_session *session) return FALSE; } if (radix32tree_find (session->ctx->update_ips, - ntohl (session->client_addr.s4.sin_addr.s_addr)) == RADIX_NO_VALUE) { + ntohl (session->client_addr.s4.sin_addr.s_addr)) == + RADIX_NO_VALUE) { return FALSE; } } @@ -758,39 +789,45 @@ check_fuzzy_client (struct fuzzy_session *session) return TRUE; } -#define CMD_PROCESS(x) \ -do { \ -if (process_##x##_command (&session->cmd, session->time, session->worker->ctx)) { \ - if (sendto (session->fd, "OK" CRLF, sizeof ("OK" CRLF) - 1, 0, &session->client_addr.ss, session->salen) == -1) { \ - msg_err ("error while writing reply: %s", strerror (errno)); \ - } \ -} \ -else { \ - if (sendto (session->fd, "ERR" CRLF, sizeof ("ERR" CRLF) - 1, 0, &session->client_addr.ss, session->salen) == -1) { \ - msg_err ("error while writing reply: %s", strerror (errno)); \ - } \ -} \ -} while(0) +#define CMD_PROCESS(x) \ + do { \ + if (process_ ## x ## _command (&session->cmd, session->time, \ + session->worker->ctx)) { \ + if (sendto (session->fd, "OK" CRLF, sizeof ("OK" CRLF) - 1, 0, \ + &session->client_addr.ss, session->salen) == -1) { \ + msg_err ("error while writing reply: %s", strerror (errno)); \ + } \ + } \ + else { \ + if (sendto (session->fd, "ERR" CRLF, sizeof ("ERR" CRLF) - 1, 0, \ + &session->client_addr.ss, session->salen) == -1) { \ + msg_err ("error while writing reply: %s", strerror (errno)); \ + } \ + } \ + } while (0) static void process_fuzzy_command (struct fuzzy_session *session) { - gint r, flag = 0; - gchar buf[64]; + gint r, flag = 0; + gchar buf[64]; switch (session->cmd.cmd) { case FUZZY_CHECK: - r = process_check_command (&session->cmd, &flag, session->time, session->worker->ctx); + r = process_check_command (&session->cmd, + &flag, + session->time, + 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, - &session->client_addr.ss, session->salen) == -1) { + &session->client_addr.ss, session->salen) == -1) { msg_err ("error while writing reply: %s", strerror (errno)); } } else { if (sendto (session->fd, "ERR" CRLF, sizeof ("ERR" CRLF) - 1, 0, - &session->client_addr.ss, session->salen) == -1) { + &session->client_addr.ss, session->salen) == -1) { msg_err ("error while writing reply: %s", strerror (errno)); } } @@ -798,8 +835,9 @@ process_fuzzy_command (struct fuzzy_session *session) case FUZZY_WRITE: if (!check_fuzzy_client (session)) { msg_info ("try to insert a hash from an untrusted address"); - if (sendto (session->fd, "UNAUTH" CRLF, sizeof ("UNAUTH" CRLF) - 1, 0, - &session->client_addr.ss, session->salen) == -1) { + if (sendto (session->fd, "UNAUTH" CRLF, sizeof ("UNAUTH" CRLF) - 1, + 0, + &session->client_addr.ss, session->salen) == -1) { msg_err ("error while writing reply: %s", strerror (errno)); } } @@ -810,8 +848,9 @@ process_fuzzy_command (struct fuzzy_session *session) case FUZZY_DEL: if (!check_fuzzy_client (session)) { msg_info ("try to delete a hash from an untrusted address"); - if (sendto (session->fd, "UNAUTH" CRLF, sizeof ("UNAUTH" CRLF) - 1, 0, - &session->client_addr.ss, session->salen) == -1) { + if (sendto (session->fd, "UNAUTH" CRLF, sizeof ("UNAUTH" CRLF) - 1, + 0, + &session->client_addr.ss, session->salen) == -1) { msg_err ("error while writing reply: %s", strerror (errno)); } } @@ -821,7 +860,7 @@ process_fuzzy_command (struct fuzzy_session *session) break; default: if (sendto (session->fd, "ERR" CRLF, sizeof ("ERR" CRLF) - 1, 0, - &session->client_addr.ss, session->salen) == -1) { + &session->client_addr.ss, session->salen) == -1) { msg_err ("error while writing reply: %s", strerror (errno)); } break; @@ -837,20 +876,20 @@ process_fuzzy_command (struct fuzzy_session *session) static void accept_fuzzy_socket (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *)arg; - struct fuzzy_session session; - ssize_t r; + struct rspamd_worker *worker = (struct rspamd_worker *)arg; + struct fuzzy_session session; + ssize_t r; struct { - u_char cmd; - guint32 blocksize; - gint32 value; - u_char hash[FUZZY_HASHLEN]; - } legacy_cmd; + u_char cmd; + guint32 blocksize; + gint32 value; + u_char hash[FUZZY_HASHLEN]; + } legacy_cmd; session.worker = worker; session.fd = fd; - session.pos = (u_char *) & session.cmd; + session.pos = (u_char *) &session.cmd; session.salen = sizeof (session.client_addr); session.ctx = worker->ctx; session.time = (guint64)time (NULL); @@ -858,11 +897,13 @@ accept_fuzzy_socket (gint fd, short what, void *arg) /* Got some data */ if (what == EV_READ) { while ((r = recvfrom (fd, session.pos, sizeof (struct fuzzy_cmd), - MSG_WAITALL, &session.client_addr.ss, &session.salen)) == -1) { + MSG_WAITALL, &session.client_addr.ss, &session.salen)) == -1) { if (errno == EINTR) { continue; } - msg_err ("got error while reading from socket: %d, %s", errno, strerror (errno)); + msg_err ("got error while reading from socket: %d, %s", + errno, + strerror (errno)); return; } if (r == sizeof (struct fuzzy_cmd)) { @@ -876,11 +917,14 @@ accept_fuzzy_socket (gint fd, short what, void *arg) session.cmd.blocksize = legacy_cmd.blocksize; session.cmd.value = legacy_cmd.value; session.cmd.flag = 0; - memcpy (session.cmd.hash, legacy_cmd.hash, sizeof (legacy_cmd.hash)); + memcpy (session.cmd.hash, legacy_cmd.hash, + sizeof (legacy_cmd.hash)); process_fuzzy_command (&session); } else { - msg_err ("got incomplete data while reading from socket: %d, %s", errno, strerror (errno)); + msg_err ("got incomplete data while reading from socket: %d, %s", + errno, + strerror (errno)); return; } } @@ -889,8 +933,8 @@ accept_fuzzy_socket (gint fd, short what, void *arg) static void sync_callback (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *)arg; - struct rspamd_fuzzy_storage_ctx *ctx; + struct rspamd_worker *worker = (struct rspamd_worker *)arg; + struct rspamd_fuzzy_storage_ctx *ctx; ctx = worker->ctx; /* Timer event */ @@ -909,8 +953,8 @@ sync_callback (gint fd, short what, void *arg) gpointer init_fuzzy (struct rspamd_config *cfg) { - struct rspamd_fuzzy_storage_ctx *ctx; - GQuark type; + struct rspamd_fuzzy_storage_ctx *ctx; + GQuark type; type = g_quark_try_string ("fuzzy"); @@ -929,28 +973,31 @@ init_fuzzy (struct rspamd_config *cfg) #endif rspamd_rcl_register_worker_option (cfg, type, "hashfile", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, hashfile), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, hashfile), 0); rspamd_rcl_register_worker_option (cfg, type, "max_mods", - rspamd_rcl_parse_struct_integer, ctx, - G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, max_mods), RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_parse_struct_integer, ctx, + G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, + max_mods), RSPAMD_CL_FLAG_INT_32); rspamd_rcl_register_worker_option (cfg, type, "frequent_score", - rspamd_rcl_parse_struct_integer, ctx, - G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, frequent_score), RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_parse_struct_integer, ctx, + G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, + frequent_score), RSPAMD_CL_FLAG_INT_32); rspamd_rcl_register_worker_option (cfg, type, "expire", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, expire), RSPAMD_CL_FLAG_TIME_FLOAT); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, + expire), RSPAMD_CL_FLAG_TIME_FLOAT); rspamd_rcl_register_worker_option (cfg, type, "strict_hash", - rspamd_rcl_parse_struct_boolean, ctx, - G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, strict_hash), 0); + rspamd_rcl_parse_struct_boolean, ctx, + G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, strict_hash), 0); rspamd_rcl_register_worker_option (cfg, type, "allow_update", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, update_map), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, update_map), 0); return ctx; @@ -962,17 +1009,20 @@ init_fuzzy (struct rspamd_config *cfg) void start_fuzzy (struct rspamd_worker *worker) { - struct event sev; + struct event sev; struct rspamd_fuzzy_storage_ctx *ctx = worker->ctx; - GError *err = NULL; + GError *err = NULL; gint i; - ctx->ev_base = rspamd_prepare_worker (worker, "controller", accept_fuzzy_socket); + ctx->ev_base = rspamd_prepare_worker (worker, + "controller", + accept_fuzzy_socket); server_stat = worker->srv->stat; /* Custom SIGUSR2 handler */ event_del (&worker->sig_ev_usr2); - signal_set (&worker->sig_ev_usr2, SIGUSR2, sigusr2_handler, (void *) worker); + signal_set (&worker->sig_ev_usr2, SIGUSR2, sigusr2_handler, + (void *) worker); event_base_set (ctx->ev_base, &worker->sig_ev_usr2); signal_add (&worker->sig_ev_usr2, NULL); @@ -997,7 +1047,8 @@ start_fuzzy (struct rspamd_worker *worker) bf = rspamd_bloom_create (2000000L, RSPAMD_DEFAULT_BLOOM_HASHES); /* Try to read hashes from file */ if (!read_hashes_file (worker)) { - msg_err ("cannot read hashes file, it can be created after save procedure"); + msg_err ( + "cannot read hashes file, it can be created after save procedure"); } /* Timer event */ @@ -1010,10 +1061,13 @@ start_fuzzy (struct rspamd_worker *worker) /* Create radix tree */ if (ctx->update_map != NULL) { - if (!add_map (worker->srv->cfg, ctx->update_map, "Allow fuzzy updates from specified addresses", - read_radix_list, fin_radix_list, (void **)&ctx->update_ips)) { - if (!rspamd_config_parse_ip_list (ctx->update_map, &ctx->update_ips)) { - msg_warn ("cannot load or parse ip list from '%s'", ctx->update_map); + if (!add_map (worker->srv->cfg, ctx->update_map, + "Allow fuzzy updates from specified addresses", + read_radix_list, fin_radix_list, (void **)&ctx->update_ips)) { + if (!rspamd_config_parse_ip_list (ctx->update_map, + &ctx->update_ips)) { + msg_warn ("cannot load or parse ip list from '%s'", + ctx->update_map); } } } @@ -1021,7 +1075,10 @@ start_fuzzy (struct rspamd_worker *worker) /* Maps events */ start_map_watch (worker->srv->cfg, ctx->ev_base); - ctx->update_thread = rspamd_create_thread ("fuzzy update", sync_cache, worker, &err); + ctx->update_thread = rspamd_create_thread ("fuzzy update", + sync_cache, + worker, + &err); if (ctx->update_thread == NULL) { msg_err ("error creating update thread: %s", err->message); } diff --git a/src/kvstorage.c b/src/kvstorage.c index 9cb921d7e..caa131afe 100644 --- a/src/kvstorage.c +++ b/src/kvstorage.c @@ -33,10 +33,16 @@ /** Create new kv storage */ struct rspamd_kv_storage * -rspamd_kv_storage_new (gint id, const gchar *name, struct rspamd_kv_cache *cache, struct rspamd_kv_backend *backend, struct rspamd_kv_expire *expire, - gsize max_elts, gsize max_memory, gboolean no_overwrite) +rspamd_kv_storage_new (gint id, + const gchar *name, + struct rspamd_kv_cache *cache, + struct rspamd_kv_backend *backend, + struct rspamd_kv_expire *expire, + gsize max_elts, + gsize max_memory, + gboolean no_overwrite) { - struct rspamd_kv_storage *new; + struct rspamd_kv_storage *new; new = g_slice_alloc (sizeof (struct rspamd_kv_storage)); new->elts = 0; @@ -84,18 +90,27 @@ rspamd_kv_storage_new (gint id, const gchar *name, struct rspamd_kv_cache *cache /** Internal insertion to the kv storage from backend */ gboolean -rspamd_kv_storage_insert_cache (struct rspamd_kv_storage *storage, gpointer key, guint keylen, - gpointer data, gsize len, gint flags, guint expire, struct rspamd_kv_element **pelt) +rspamd_kv_storage_insert_cache (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + gpointer data, + gsize len, + gint flags, + guint expire, + struct rspamd_kv_element **pelt) { - gint steps = 0; - struct rspamd_kv_element *elt; + gint steps = 0; + struct rspamd_kv_element *elt; RW_W_LOCK (&storage->rwlock); /* Hard limit */ if (storage->max_memory > 0) { if (len > storage->max_memory) { - msg_info ("<%s>: trying to insert value of length %z while limit is %z", storage->name, - len, storage->max_memory); + msg_info ( + "<%s>: trying to insert value of length %z while limit is %z", + storage->name, + len, + storage->max_memory); RW_W_UNLOCK (&storage->rwlock); return FALSE; } @@ -103,14 +118,18 @@ rspamd_kv_storage_insert_cache (struct rspamd_kv_storage *storage, gpointer key, /* Now check limits */ while (storage->memory + len > storage->max_memory) { if (storage->expire) { - storage->expire->step_func (storage->expire, storage, time (NULL), steps); + storage->expire->step_func (storage->expire, storage, time ( + NULL), steps); } else { - msg_warn ("<%s>: storage is full and no expire function is defined", storage->name); + msg_warn ( + "<%s>: storage is full and no expire function is defined", + storage->name); } if (++steps > MAX_EXPIRE_STEPS) { RW_W_UNLOCK (&storage->rwlock); - msg_warn ("<%s>: cannot expire enough keys in storage", storage->name); + msg_warn ("<%s>: cannot expire enough keys in storage", + storage->name); return FALSE; } } @@ -134,7 +153,7 @@ rspamd_kv_storage_insert_cache (struct rspamd_kv_storage *storage, gpointer key, storage->expire->insert_func (storage->expire, elt); } - storage->elts ++; + storage->elts++; storage->memory += ELT_SIZE (elt); RW_W_UNLOCK (&storage->rwlock); @@ -143,20 +162,29 @@ rspamd_kv_storage_insert_cache (struct rspamd_kv_storage *storage, gpointer key, /** Insert new element to the kv storage */ gboolean -rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint keylen, - gpointer data, gsize len, gint flags, guint expire) +rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + gpointer data, + gsize len, + gint flags, + guint expire) { - gint steps = 0; - struct rspamd_kv_element *elt; - gboolean res = TRUE; - glong longval; + gint steps = 0; + struct rspamd_kv_element *elt; + gboolean res = TRUE; + glong longval; /* Hard limit */ RW_W_LOCK (&storage->rwlock); if (storage->max_memory > 0) { - if (len + sizeof (struct rspamd_kv_element) + keylen >= storage->max_memory) { - msg_warn ("<%s>: trying to insert value of length %z while limit is %z", storage->name, - len, storage->max_memory); + if (len + sizeof (struct rspamd_kv_element) + keylen >= + storage->max_memory) { + msg_warn ( + "<%s>: trying to insert value of length %z while limit is %z", + storage->name, + len, + storage->max_memory); RW_W_UNLOCK (&storage->rwlock); return FALSE; } @@ -164,14 +192,18 @@ rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint /* Now check limits */ while (storage->memory + len + keylen > storage->max_memory) { if (storage->expire) { - storage->expire->step_func (storage->expire, storage, time (NULL), steps); + storage->expire->step_func (storage->expire, storage, time ( + NULL), steps); } else { - msg_warn ("<%s>: storage is full and no expire function is defined", storage->name); + msg_warn ( + "<%s>: storage is full and no expire function is defined", + storage->name); } if (++steps > MAX_EXPIRE_STEPS) { RW_W_UNLOCK (&storage->rwlock); - msg_warn ("<%s>: cannot expire enough keys in storage", storage->name); + msg_warn ("<%s>: cannot expire enough keys in storage", + storage->name); return FALSE; } } @@ -181,14 +213,18 @@ rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint steps = 0; while (storage->elts > storage->max_elts) { if (storage->expire) { - storage->expire->step_func (storage->expire, storage, time (NULL), steps); + storage->expire->step_func (storage->expire, storage, time ( + NULL), steps); } else { - msg_warn ("<%s>: storage is full and no expire function is defined", storage->name); + msg_warn ( + "<%s>: storage is full and no expire function is defined", + storage->name); } if (++steps > MAX_EXPIRE_STEPS) { RW_W_UNLOCK (&storage->rwlock); - msg_warn ("<%s>: cannot expire enough keys in storage", storage->name); + msg_warn ("<%s>: cannot expire enough keys in storage", + storage->name); return FALSE; } } @@ -216,7 +252,8 @@ rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint else { /* Just do incref and nothing more */ if (storage->backend && storage->backend->incref_func) { - if (storage->backend->incref_func (storage->backend, key, keylen)) { + if (storage->backend->incref_func (storage->backend, key, + keylen)) { RW_W_UNLOCK (&storage->rwlock); return TRUE; } @@ -232,7 +269,11 @@ rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint /* First of all check element for integer */ if (rspamd_strtol (data, len, &longval)) { - elt = storage->cache->insert_func (storage->cache, key, keylen, &longval, sizeof (glong)); + elt = storage->cache->insert_func (storage->cache, + key, + keylen, + &longval, + sizeof (glong)); if (elt == NULL) { return FALSE; } @@ -241,7 +282,11 @@ rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint } } else { - elt = storage->cache->insert_func (storage->cache, key, keylen, data, len); + elt = storage->cache->insert_func (storage->cache, + key, + keylen, + data, + len); if (elt == NULL) { RW_W_UNLOCK (&storage->rwlock); return FALSE; @@ -256,7 +301,8 @@ rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint /* Place to the backend */ if (storage->backend) { - res = storage->backend->insert_func (storage->backend, key, keylen, elt); + res = + storage->backend->insert_func (storage->backend, key, keylen, elt); } /* Insert to the expire */ @@ -264,7 +310,7 @@ rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint storage->expire->insert_func (storage->expire, elt); } - storage->elts ++; + storage->elts++; storage->memory += ELT_SIZE (elt); RW_W_UNLOCK (&storage->rwlock); @@ -273,16 +319,22 @@ rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint /** Replace an element in the kv storage */ gboolean -rspamd_kv_storage_replace (struct rspamd_kv_storage *storage, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_kv_storage_replace (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - gboolean res = TRUE; - gint steps = 0; + gboolean res = TRUE; + gint steps = 0; /* Hard limit */ if (storage->max_memory > 0) { if (elt->size > storage->max_memory) { - msg_info ("<%s>: trying to replace value of length %z while limit is %z", storage->name, - elt->size, storage->max_memory); + msg_info ( + "<%s>: trying to replace value of length %z while limit is %z", + storage->name, + elt->size, + storage->max_memory); return FALSE; } @@ -290,14 +342,18 @@ rspamd_kv_storage_replace (struct rspamd_kv_storage *storage, gpointer key, guin while (storage->memory + ELT_SIZE (elt) > storage->max_memory) { if (storage->expire) { RW_W_LOCK (&storage->rwlock); - storage->expire->step_func (storage->expire, storage, time (NULL), steps); + storage->expire->step_func (storage->expire, storage, time ( + NULL), steps); RW_W_UNLOCK (&storage->rwlock); } else { - msg_warn ("<%s>: storage is full and no expire function is defined", storage->name); + msg_warn ( + "<%s>: storage is full and no expire function is defined", + storage->name); } if (++steps > MAX_EXPIRE_STEPS) { - msg_warn ("<%s>: cannot expire enough keys in storage", storage->name); + msg_warn ("<%s>: cannot expire enough keys in storage", + storage->name); return FALSE; } } @@ -309,7 +365,8 @@ rspamd_kv_storage_replace (struct rspamd_kv_storage *storage, gpointer key, guin /* Place to the backend */ if (res && storage->backend) { - res = storage->backend->replace_func (storage->backend, key, keylen, elt); + res = + storage->backend->replace_func (storage->backend, key, keylen, elt); } RW_W_UNLOCK (&storage->rwlock); @@ -318,10 +375,13 @@ rspamd_kv_storage_replace (struct rspamd_kv_storage *storage, gpointer key, guin /** Increment value in kvstorage */ gboolean -rspamd_kv_storage_increment (struct rspamd_kv_storage *storage, gpointer key, guint keylen, glong *value) +rspamd_kv_storage_increment (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + glong *value) { - struct rspamd_kv_element *elt = NULL, *belt; - glong *lp; + struct rspamd_kv_element *elt = NULL, *belt; + glong *lp; /* First try to look at cache */ RW_W_LOCK (&storage->rwlock); @@ -333,7 +393,8 @@ rspamd_kv_storage_increment (struct rspamd_kv_storage *storage, gpointer key, gu /* Put this element into cache */ if ((belt->flags & KV_ELT_INTEGER) != 0) { RW_W_UNLOCK (&storage->rwlock); - rspamd_kv_storage_insert_cache (storage, ELT_KEY (belt), keylen, ELT_DATA (belt), + rspamd_kv_storage_insert_cache (storage, ELT_KEY ( + belt), keylen, ELT_DATA (belt), belt->size, belt->flags, belt->expire, &elt); RW_W_LOCK (&storage->rwlock); @@ -355,7 +416,8 @@ rspamd_kv_storage_increment (struct rspamd_kv_storage *storage, gpointer key, gu } elt->age = time (NULL); if (storage->backend) { - if (storage->backend->replace_func (storage->backend, key, keylen, elt)) { + if (storage->backend->replace_func (storage->backend, key, keylen, + elt)) { RW_W_UNLOCK (&storage->rwlock); return TRUE; } @@ -376,10 +438,13 @@ rspamd_kv_storage_increment (struct rspamd_kv_storage *storage, gpointer key, gu } /** Lookup an element inside kv storage */ -struct rspamd_kv_element* -rspamd_kv_storage_lookup (struct rspamd_kv_storage *storage, gpointer key, guint keylen, time_t now) +struct rspamd_kv_element * +rspamd_kv_storage_lookup (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + time_t now) { - struct rspamd_kv_element *elt = NULL, *belt; + struct rspamd_kv_element *elt = NULL, *belt; /* First try to look at cache */ RW_R_LOCK (&storage->rwlock); @@ -416,9 +481,11 @@ rspamd_kv_storage_lookup (struct rspamd_kv_storage *storage, gpointer key, guint /** Expire an element from kv storage */ struct rspamd_kv_element * -rspamd_kv_storage_delete (struct rspamd_kv_storage *storage, gpointer key, guint keylen) +rspamd_kv_storage_delete (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen) { - struct rspamd_kv_element *elt; + struct rspamd_kv_element *elt; /* First delete key from cache */ RW_W_LOCK (&storage->rwlock); @@ -433,7 +500,7 @@ rspamd_kv_storage_delete (struct rspamd_kv_storage *storage, gpointer key, guint if (storage->expire) { storage->expire->delete_func (storage->expire, elt); } - storage->elts --; + storage->elts--; storage->memory -= elt->size; if ((elt->flags & KV_ELT_DIRTY) != 0) { elt->flags |= KV_ELT_NEED_FREE; @@ -471,20 +538,27 @@ rspamd_kv_storage_destroy (struct rspamd_kv_storage *storage) /** Insert array */ gboolean -rspamd_kv_storage_insert_array (struct rspamd_kv_storage *storage, gpointer key, guint keylen, - guint elt_size, gpointer data, gsize len, gint flags, guint expire) +rspamd_kv_storage_insert_array (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + guint elt_size, + gpointer data, + gsize len, + gint flags, + guint expire) { - struct rspamd_kv_element *elt; - guint *es; - gpointer arr_data; + struct rspamd_kv_element *elt; + guint *es; + gpointer arr_data; /* Make temporary copy */ arr_data = g_slice_alloc (len + sizeof (guint)); es = arr_data; *es = elt_size; memcpy (arr_data, (gchar *)data + sizeof (guint), len); - if (!rspamd_kv_storage_insert_cache (storage, key, keylen, arr_data, len + sizeof (guint), - flags, expire, &elt)) { + if (!rspamd_kv_storage_insert_cache (storage, key, keylen, arr_data, len + + sizeof (guint), + flags, expire, &elt)) { g_slice_free1 (len + sizeof (guint), arr_data); return FALSE; } @@ -494,7 +568,8 @@ rspamd_kv_storage_insert_array (struct rspamd_kv_storage *storage, gpointer key, /* Place to the backend */ if (storage->backend) { - return storage->backend->insert_func (storage->backend, key, keylen, elt); + return storage->backend->insert_func (storage->backend, key, keylen, + elt); } return TRUE; @@ -502,12 +577,17 @@ rspamd_kv_storage_insert_array (struct rspamd_kv_storage *storage, gpointer key, /** Set element inside array */ gboolean -rspamd_kv_storage_set_array (struct rspamd_kv_storage *storage, gpointer key, guint keylen, - guint elt_num, gpointer data, gsize len, time_t now) +rspamd_kv_storage_set_array (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + guint elt_num, + gpointer data, + gsize len, + time_t now) { - struct rspamd_kv_element *elt; - guint *es; - gpointer target; + struct rspamd_kv_element *elt; + guint *es; + gpointer target; elt = rspamd_kv_storage_lookup (storage, key, keylen, now); if (elt == NULL) { @@ -531,7 +611,10 @@ rspamd_kv_storage_set_array (struct rspamd_kv_storage *storage, gpointer key, gu memcpy (target, data, len); /* Place to the backend */ if (storage->backend) { - return storage->backend->replace_func (storage->backend, key, keylen, elt); + return storage->backend->replace_func (storage->backend, + key, + keylen, + elt); } return TRUE; @@ -539,12 +622,17 @@ rspamd_kv_storage_set_array (struct rspamd_kv_storage *storage, gpointer key, gu /** Get element inside array */ gboolean -rspamd_kv_storage_get_array (struct rspamd_kv_storage *storage, gpointer key, guint keylen, - guint elt_num, gpointer *data, gsize *len, time_t now) +rspamd_kv_storage_get_array (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + guint elt_num, + gpointer *data, + gsize *len, + time_t now) { - struct rspamd_kv_element *elt; - guint *es; - gpointer target; + struct rspamd_kv_element *elt; + guint *es; + gpointer target; elt = rspamd_kv_storage_lookup (storage, key, keylen, now); if (elt == NULL) { @@ -573,11 +661,11 @@ rspamd_kv_storage_get_array (struct rspamd_kv_storage *storage, gpointer key, gu */ struct rspamd_kv_lru_expire { - expire_init init_func; /*< this callback is called on kv storage initialization */ - expire_insert insert_func; /*< this callback is called when element is inserted */ - expire_step step_func; /*< this callback is used when cache is full */ - expire_delete delete_func; /*< this callback is called when an element is deleted */ - expire_destroy destroy_func; /*< this callback is used for destroying all elements inside expire */ + expire_init init_func; /*< this callback is called on kv storage initialization */ + expire_insert insert_func; /*< this callback is called when element is inserted */ + expire_step step_func; /*< this callback is used when cache is full */ + expire_delete delete_func; /*< this callback is called when an element is deleted */ + expire_destroy destroy_func; /*< this callback is used for destroying all elements inside expire */ TAILQ_HEAD (eltq, rspamd_kv_element) head; }; @@ -588,7 +676,7 @@ struct rspamd_kv_lru_expire { static void rspamd_lru_insert (struct rspamd_kv_expire *e, struct rspamd_kv_element *elt) { - struct rspamd_kv_lru_expire *expire = (struct rspamd_kv_lru_expire *)e; + struct rspamd_kv_lru_expire *expire = (struct rspamd_kv_lru_expire *)e; /* Get a proper queue */ TAILQ_INSERT_TAIL (&expire->head, elt, entry); @@ -599,7 +687,7 @@ rspamd_lru_insert (struct rspamd_kv_expire *e, struct rspamd_kv_element *elt) static void rspamd_lru_delete (struct rspamd_kv_expire *e, struct rspamd_kv_element *elt) { - struct rspamd_kv_lru_expire *expire = (struct rspamd_kv_lru_expire *)e; + struct rspamd_kv_lru_expire *expire = (struct rspamd_kv_lru_expire *)e; /* Unlink element */ TAILQ_REMOVE (&expire->head, elt, entry); @@ -609,15 +697,19 @@ rspamd_lru_delete (struct rspamd_kv_expire *e, struct rspamd_kv_element *elt) * Expire elements */ static gboolean -rspamd_lru_expire_step (struct rspamd_kv_expire *e, struct rspamd_kv_storage *storage, time_t now, gboolean forced) +rspamd_lru_expire_step (struct rspamd_kv_expire *e, + struct rspamd_kv_storage *storage, + time_t now, + gboolean forced) { - struct rspamd_kv_lru_expire *expire = (struct rspamd_kv_lru_expire *)e; - struct rspamd_kv_element *elt, *oldest_elt = NULL, *temp; - time_t diff; - gboolean res = FALSE; + struct rspamd_kv_lru_expire *expire = (struct rspamd_kv_lru_expire *)e; + struct rspamd_kv_element *elt, *oldest_elt = NULL, *temp; + time_t diff; + gboolean res = FALSE; elt = TAILQ_FIRST (&expire->head); - if (elt && (forced || (elt->flags & (KV_ELT_PERSISTENT|KV_ELT_DIRTY)) == 0)) { + if (elt && + (forced || (elt->flags & (KV_ELT_PERSISTENT | KV_ELT_DIRTY)) == 0)) { diff = elt->expire - (now - elt->age); if (diff > 0 || (forced && elt->expire == 0)) { oldest_elt = elt; @@ -626,10 +718,10 @@ rspamd_lru_expire_step (struct rspamd_kv_expire *e, struct rspamd_kv_storage *st /* This element is already expired */ storage->cache->steal_func (storage->cache, elt); storage->memory -= ELT_SIZE (elt); - storage->elts --; + storage->elts--; TAILQ_REMOVE (&expire->head, elt, entry); /* Free memory */ - if ((elt->flags & (KV_ELT_DIRTY|KV_ELT_NEED_INSERT)) != 0) { + if ((elt->flags & (KV_ELT_DIRTY | KV_ELT_NEED_INSERT)) != 0) { elt->flags |= KV_ELT_NEED_FREE; } else { @@ -637,17 +729,19 @@ rspamd_lru_expire_step (struct rspamd_kv_expire *e, struct rspamd_kv_storage *st } res = TRUE; /* Check other elements in this queue */ - TAILQ_FOREACH_SAFE (elt, &expire->head, entry, temp) { + TAILQ_FOREACH_SAFE (elt, &expire->head, entry, temp) + { if ((!forced && - (elt->flags & (KV_ELT_PERSISTENT|KV_ELT_DIRTY)) != 0) || (gint)elt->expire < (now - elt->age)) { + (elt->flags & (KV_ELT_PERSISTENT | KV_ELT_DIRTY)) != 0) || + (gint)elt->expire < (now - elt->age)) { break; } storage->memory -= ELT_SIZE (elt); - storage->elts --; + storage->elts--; storage->cache->steal_func (storage->cache, elt); TAILQ_REMOVE (&expire->head, elt, entry); /* Free memory */ - if ((elt->flags & (KV_ELT_DIRTY|KV_ELT_NEED_INSERT)) != 0) { + if ((elt->flags & (KV_ELT_DIRTY | KV_ELT_NEED_INSERT)) != 0) { elt->flags |= KV_ELT_NEED_FREE; } else { @@ -660,11 +754,11 @@ rspamd_lru_expire_step (struct rspamd_kv_expire *e, struct rspamd_kv_storage *st if (!res && oldest_elt != NULL) { storage->memory -= ELT_SIZE (oldest_elt); - storage->elts --; + storage->elts--; storage->cache->steal_func (storage->cache, oldest_elt); TAILQ_REMOVE (&expire->head, oldest_elt, entry); /* Free memory */ - if ((oldest_elt->flags & (KV_ELT_DIRTY|KV_ELT_NEED_INSERT)) != 0) { + if ((oldest_elt->flags & (KV_ELT_DIRTY | KV_ELT_NEED_INSERT)) != 0) { oldest_elt->flags |= KV_ELT_NEED_FREE; } else { @@ -681,7 +775,7 @@ rspamd_lru_expire_step (struct rspamd_kv_expire *e, struct rspamd_kv_storage *st static void rspamd_lru_destroy (struct rspamd_kv_expire *e) { - struct rspamd_kv_lru_expire *expire = (struct rspamd_kv_lru_expire *)e; + struct rspamd_kv_lru_expire *expire = (struct rspamd_kv_lru_expire *)e; g_slice_free1 (sizeof (struct rspamd_kv_lru_expire), expire); } @@ -689,10 +783,10 @@ rspamd_lru_destroy (struct rspamd_kv_expire *e) /** * Create new LRU cache */ -struct rspamd_kv_expire* +struct rspamd_kv_expire * rspamd_lru_expire_new (void) { - struct rspamd_kv_lru_expire *new; + struct rspamd_kv_lru_expire *new; new = g_slice_alloc (sizeof (struct rspamd_kv_lru_expire)); TAILQ_INIT (&new->head); @@ -711,36 +805,41 @@ rspamd_lru_expire_new (void) * KV cache hash table */ struct rspamd_kv_hash_cache { - cache_init init_func; /*< this callback is called on kv storage initialization */ - cache_insert insert_func; /*< this callback is called when element is inserted */ - cache_replace replace_func; /*< this callback is called when element is replace */ - cache_lookup lookup_func; /*< this callback is used for lookup of element */ - cache_delete delete_func; /*< this callback is called when an element is deleted */ - cache_steal steal_func; /*< this callback is used to replace duplicates in cache */ - cache_destroy destroy_func; /*< this callback is used for destroying all elements inside cache */ + cache_init init_func; /*< this callback is called on kv storage initialization */ + cache_insert insert_func; /*< this callback is called when element is inserted */ + cache_replace replace_func; /*< this callback is called when element is replace */ + cache_lookup lookup_func; /*< this callback is used for lookup of element */ + cache_delete delete_func; /*< this callback is called when an element is deleted */ + cache_steal steal_func; /*< this callback is used to replace duplicates in cache */ + cache_destroy destroy_func; /*< this callback is used for destroying all elements inside cache */ GHashTable *hash; }; /** * Insert an element inside cache */ -static struct rspamd_kv_element* -rspamd_kv_hash_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, gpointer value, gsize len) +static struct rspamd_kv_element * +rspamd_kv_hash_insert (struct rspamd_kv_cache *c, + gpointer key, + guint keylen, + gpointer value, + gsize len) { - struct rspamd_kv_element *elt; - struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; - struct rspamd_kv_element search_elt; + struct rspamd_kv_element *elt; + struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; if ((elt = g_hash_table_lookup (cache->hash, &search_elt)) == NULL) { - elt = g_slice_alloc (sizeof (struct rspamd_kv_element) + len + keylen + 1); + elt = g_slice_alloc ( + sizeof (struct rspamd_kv_element) + len + keylen + 1); elt->age = time (NULL); elt->keylen = keylen; elt->size = len; elt->flags = 0; - memcpy (ELT_KEY (elt), key, keylen + 1); + memcpy (ELT_KEY (elt), key, keylen + 1); memcpy (ELT_DATA (elt), value, len); elt->p = &elt->data; g_hash_table_insert (cache->hash, elt, elt); @@ -754,12 +853,13 @@ rspamd_kv_hash_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, gp /* Free it by self */ g_slice_free1 (ELT_SIZE (elt), elt); } - elt = g_slice_alloc (sizeof (struct rspamd_kv_element) + len + keylen + 1); + elt = g_slice_alloc ( + sizeof (struct rspamd_kv_element) + len + keylen + 1); elt->age = time (NULL); elt->keylen = keylen; elt->size = len; elt->flags = 0; - memcpy (ELT_KEY (elt), key, keylen + 1); + memcpy (ELT_KEY (elt), key, keylen + 1); memcpy (ELT_DATA (elt), value, len); elt->p = &elt->data; g_hash_table_insert (cache->hash, elt, elt); @@ -771,11 +871,11 @@ rspamd_kv_hash_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, gp /** * Lookup an item inside hash */ -static struct rspamd_kv_element* +static struct rspamd_kv_element * rspamd_kv_hash_lookup (struct rspamd_kv_cache *c, gpointer key, guint keylen) { - struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; - struct rspamd_kv_element search_elt; + struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -787,10 +887,13 @@ rspamd_kv_hash_lookup (struct rspamd_kv_cache *c, gpointer key, guint keylen) * Replace an element inside cache */ static gboolean -rspamd_kv_hash_replace (struct rspamd_kv_cache *c, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_kv_hash_replace (struct rspamd_kv_cache *c, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; - struct rspamd_kv_element *oldelt, search_elt; + struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; + struct rspamd_kv_element *oldelt, search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -818,9 +921,9 @@ rspamd_kv_hash_replace (struct rspamd_kv_cache *c, gpointer key, guint keylen, s static struct rspamd_kv_element * rspamd_kv_hash_delete (struct rspamd_kv_cache *c, gpointer key, guint keylen) { - struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; - struct rspamd_kv_element *elt; - struct rspamd_kv_element search_elt; + struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; + struct rspamd_kv_element *elt; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -838,7 +941,7 @@ rspamd_kv_hash_delete (struct rspamd_kv_cache *c, gpointer key, guint keylen) static void rspamd_kv_hash_steal (struct rspamd_kv_cache *c, struct rspamd_kv_element *elt) { - struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; + struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; g_hash_table_steal (cache->hash, elt); } @@ -850,7 +953,7 @@ rspamd_kv_hash_steal (struct rspamd_kv_cache *c, struct rspamd_kv_element *elt) static void rspamd_kv_hash_destroy_cb (gpointer key, gpointer value, gpointer unused) { - struct rspamd_kv_element *elt = value; + struct rspamd_kv_element *elt = value; g_slice_free1 (ELT_SIZE (elt), elt); } @@ -858,7 +961,7 @@ rspamd_kv_hash_destroy_cb (gpointer key, gpointer value, gpointer unused) static void rspamd_kv_hash_destroy (struct rspamd_kv_cache *c) { - struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; + struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c; g_hash_table_foreach (cache->hash, rspamd_kv_hash_destroy_cb, NULL); g_hash_table_destroy (cache->hash); @@ -868,26 +971,26 @@ rspamd_kv_hash_destroy (struct rspamd_kv_cache *c) /** * Make hash for element */ -#define rot(x,k) (((x)<<(k)) ^ ((x)>>(32-(k)))) +#define rot(x,k) (((x) << (k)) ^ ((x) >> (32 - (k)))) #define mix(a,b,c) \ -{ \ - a -= c; a ^= rot(c, 4); c += b; \ - b -= a; b ^= rot(a, 6); a += c; \ - c -= b; c ^= rot(b, 8); b += a; \ - a -= c; a ^= rot(c,16); c += b; \ - b -= a; b ^= rot(a,19); a += c; \ - c -= b; c ^= rot(b, 4); b += a; \ -} + { \ + a -= c; a ^= rot (c, 4); c += b; \ + b -= a; b ^= rot (a, 6); a += c; \ + c -= b; c ^= rot (b, 8); b += a; \ + a -= c; a ^= rot (c,16); c += b; \ + b -= a; b ^= rot (a,19); a += c; \ + c -= b; c ^= rot (b, 4); b += a; \ + } #define final(a,b,c) \ -{ \ - c ^= b; c -= rot(b,14); \ - a ^= c; a -= rot(c,11); \ - b ^= a; b -= rot(a,25); \ - c ^= b; c -= rot(b,16); \ - a ^= c; a -= rot(c,4); \ - b ^= a; b -= rot(a,14); \ - c ^= b; c -= rot(b,24); \ -} + { \ + c ^= b; c -= rot (b,14); \ + a ^= c; a -= rot (c,11); \ + b ^= a; b -= rot (a,25); \ + c ^= b; c -= rot (b,16); \ + a ^= c; a -= rot (c,4); \ + b ^= a; b -= rot (a,14); \ + c ^= b; c -= rot (b,24); \ + } /* * The hash function used here is by Bob Jenkins, 1996: * <http://burtleburtle.net/bob/hash/doobs.html> @@ -899,10 +1002,10 @@ rspamd_kv_hash_destroy (struct rspamd_kv_cache *c) guint kv_elt_hash_func (gconstpointer e) { - struct rspamd_kv_element *elt = (struct rspamd_kv_element *)e; - guint32 a, b, c; + struct rspamd_kv_element *elt = (struct rspamd_kv_element *)e; + guint32 a, b, c; union { const void *ptr; size_t i; } u; - guint length; + guint length; /* Set up the internal state */ length = elt->keylen; @@ -934,30 +1037,30 @@ kv_elt_hash_func (gconstpointer e) */ switch (length) { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; - case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; - case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=k[1]&0xffffff; a+=k[0]; break; - case 6 : b+=k[1]&0xffff; a+=k[0]; break; - case 5 : b+=k[1]&0xff; a+=k[0]; break; - case 4 : a+=k[0]; break; - case 3 : a+=k[0]&0xffffff; break; - case 2 : a+=k[0]&0xffff; break; - case 1 : a+=k[0]&0xff; break; - case 0 : return c; /* zero length strings require no mixing */ + case 12: c += k[2]; b += k[1]; a += k[0]; break; + case 11: c += k[2] & 0xffffff; b += k[1]; a += k[0]; break; + case 10: c += k[2] & 0xffff; b += k[1]; a += k[0]; break; + case 9: c += k[2] & 0xff; b += k[1]; a += k[0]; break; + case 8: b += k[1]; a += k[0]; break; + case 7: b += k[1] & 0xffffff; a += k[0]; break; + case 6: b += k[1] & 0xffff; a += k[0]; break; + case 5: b += k[1] & 0xff; a += k[0]; break; + case 4: a += k[0]; break; + case 3: a += k[0] & 0xffffff; break; + case 2: a += k[0] & 0xffff; break; + case 1: a += k[0] & 0xff; break; + case 0: return c; /* zero length strings require no mixing */ } } else if (((u.i & 0x1) == 0)) { const guint16 *k = (const guint16 *)elt->p; /* read 16-bit chunks */ - const guint8 *k8; + const guint8 *k8; /*--------------- all but last block: aligned reads and different mixing */ while (length > 12) { - a += k[0] + (((guint32)k[1])<<16); - b += k[2] + (((guint32)k[3])<<16); - c += k[4] + (((guint32)k[5])<<16); + a += k[0] + (((guint32)k[1]) << 16); + b += k[2] + (((guint32)k[3]) << 16); + c += k[4] + (((guint32)k[5]) << 16); mix (a,b,c); length -= 12; k += 6; @@ -967,32 +1070,32 @@ kv_elt_hash_func (gconstpointer e) k8 = (const guint8 *)k; switch (length) { - case 12: c+=k[4]+(((guint32)k[5])<<16); - b+=k[2]+(((guint32)k[3])<<16); - a+=k[0]+(((guint32)k[1])<<16); - break; - case 11: c+=((guint32)k8[10])<<16; /* @fallthrough */ - case 10: c+=k[4]; /* @fallthrough@ */ - b+=k[2]+(((guint32)k[3])<<16); - a+=k[0]+(((guint32)k[1])<<16); - break; - case 9 : c+=k8[8]; /* @fallthrough */ - case 8 : b+=k[2]+(((guint32)k[3])<<16); - a+=k[0]+(((guint32)k[1])<<16); - break; - case 7 : b+=((guint32)k8[6])<<16; /* @fallthrough */ - case 6 : b+=k[2]; - a+=k[0]+(((guint32)k[1])<<16); - break; - case 5 : b+=k8[4]; /* @fallthrough */ - case 4 : a+=k[0]+(((guint32)k[1])<<16); - break; - case 3 : a+=((guint32)k8[2])<<16; /* @fallthrough */ - case 2 : a+=k[0]; - break; - case 1 : a+=k8[0]; - break; - case 0 : return c; /* zero length strings require no mixing */ + case 12: c += k[4] + (((guint32)k[5]) << 16); + b += k[2] + (((guint32)k[3]) << 16); + a += k[0] + (((guint32)k[1]) << 16); + break; + case 11: c += ((guint32)k8[10]) << 16; /* @fallthrough */ + case 10: c += k[4]; /* @fallthrough@ */ + b += k[2] + (((guint32)k[3]) << 16); + a += k[0] + (((guint32)k[1]) << 16); + break; + case 9: c += k8[8]; /* @fallthrough */ + case 8: b += k[2] + (((guint32)k[3]) << 16); + a += k[0] + (((guint32)k[1]) << 16); + break; + case 7: b += ((guint32)k8[6]) << 16; /* @fallthrough */ + case 6: b += k[2]; + a += k[0] + (((guint32)k[1]) << 16); + break; + case 5: b += k8[4]; /* @fallthrough */ + case 4: a += k[0] + (((guint32)k[1]) << 16); + break; + case 3: a += ((guint32)k8[2]) << 16; /* @fallthrough */ + case 2: a += k[0]; + break; + case 1: a += k8[0]; + break; + case 0: return c; /* zero length strings require no mixing */ } } else { /* need to read the key one byte at a time */ @@ -1002,18 +1105,18 @@ kv_elt_hash_func (gconstpointer e) while (length > 12) { a += k[0]; - a += ((guint32)k[1])<<8; - a += ((guint32)k[2])<<16; - a += ((guint32)k[3])<<24; + a += ((guint32)k[1]) << 8; + a += ((guint32)k[2]) << 16; + a += ((guint32)k[3]) << 24; b += k[4]; - b += ((guint32)k[5])<<8; - b += ((guint32)k[6])<<16; - b += ((guint32)k[7])<<24; + b += ((guint32)k[5]) << 8; + b += ((guint32)k[6]) << 16; + b += ((guint32)k[7]) << 24; c += k[8]; - c += ((guint32)k[9])<<8; - c += ((guint32)k[10])<<16; - c += ((guint32)k[11])<<24; - mix(a,b,c); + c += ((guint32)k[9]) << 8; + c += ((guint32)k[10]) << 16; + c += ((guint32)k[11]) << 24; + mix (a,b,c); length -= 12; k += 12; } @@ -1021,20 +1124,20 @@ kv_elt_hash_func (gconstpointer e) /*-------------------------------- last block: affect all 32 bits of (c) */ switch (length) /* all the case statements fall through */ { - case 12: c+=((guint32)k[11])<<24; - case 11: c+=((guint32)k[10])<<16; - case 10: c+=((guint32)k[9])<<8; - case 9 : c+=k[8]; - case 8 : b+=((guint32)k[7])<<24; - case 7 : b+=((guint32)k[6])<<16; - case 6 : b+=((guint32)k[5])<<8; - case 5 : b+=k[4]; - case 4 : a+=((guint32)k[3])<<24; - case 3 : a+=((guint32)k[2])<<16; - case 2 : a+=((guint32)k[1])<<8; - case 1 : a+=k[0]; - break; - case 0 : return c; /* zero length strings require no mixing */ + case 12: c += ((guint32)k[11]) << 24; + case 11: c += ((guint32)k[10]) << 16; + case 10: c += ((guint32)k[9]) << 8; + case 9: c += k[8]; + case 8: b += ((guint32)k[7]) << 24; + case 7: b += ((guint32)k[6]) << 16; + case 6: b += ((guint32)k[5]) << 8; + case 5: b += k[4]; + case 4: a += ((guint32)k[3]) << 24; + case 3: a += ((guint32)k[2]) << 16; + case 2: a += ((guint32)k[1]) << 8; + case 1: a += k[0]; + break; + case 0: return c; /* zero length strings require no mixing */ } } @@ -1045,8 +1148,8 @@ kv_elt_hash_func (gconstpointer e) gboolean kv_elt_compare_func (gconstpointer e1, gconstpointer e2) { - struct rspamd_kv_element *elt1 = (struct rspamd_kv_element *) e1, - *elt2 = (struct rspamd_kv_element *) e2; + struct rspamd_kv_element *elt1 = (struct rspamd_kv_element *) e1, + *elt2 = (struct rspamd_kv_element *) e2; if (elt1->keylen == elt2->keylen) { return memcmp (elt1->p, elt2->p, elt1->keylen) == 0; @@ -1058,13 +1161,16 @@ kv_elt_compare_func (gconstpointer e1, gconstpointer e2) /** * Create new hash kv cache */ -struct rspamd_kv_cache* +struct rspamd_kv_cache * rspamd_kv_hash_new (void) { - struct rspamd_kv_hash_cache *new; + struct rspamd_kv_hash_cache *new; new = g_slice_alloc (sizeof (struct rspamd_kv_hash_cache)); - new->hash = g_hash_table_new_full (kv_elt_hash_func, kv_elt_compare_func, NULL, NULL); + new->hash = g_hash_table_new_full (kv_elt_hash_func, + kv_elt_compare_func, + NULL, + NULL); new->init_func = NULL; new->insert_func = rspamd_kv_hash_insert; new->lookup_func = rspamd_kv_hash_lookup; @@ -1080,13 +1186,13 @@ rspamd_kv_hash_new (void) * Radix cache hash table */ struct rspamd_kv_radix_cache { - cache_init init_func; /*< this callback is called on kv storage initialization */ - cache_insert insert_func; /*< this callback is called when element is inserted */ - cache_replace replace_func; /*< this callback is called when element is replace */ - cache_lookup lookup_func; /*< this callback is used for lookup of element */ - cache_delete delete_func; /*< this callback is called when an element is deleted */ - cache_steal steal_func; /*< this callback is used to replace duplicates in cache */ - cache_destroy destroy_func; /*< this callback is used for destroying all elements inside cache */ + cache_init init_func; /*< this callback is called on kv storage initialization */ + cache_insert insert_func; /*< this callback is called when element is inserted */ + cache_replace replace_func; /*< this callback is called when element is replace */ + cache_lookup lookup_func; /*< this callback is used for lookup of element */ + cache_delete delete_func; /*< this callback is called when an element is deleted */ + cache_steal steal_func; /*< this callback is used to replace duplicates in cache */ + cache_destroy destroy_func; /*< this callback is used for destroying all elements inside cache */ radix_tree_t *tree; }; @@ -1096,7 +1202,7 @@ struct rspamd_kv_radix_cache { static guint32 rspamd_kv_radix_validate (gpointer key, guint keylen) { - struct in_addr addr; + struct in_addr addr; if (inet_aton (key, &addr) == 0) { return 0; @@ -1108,12 +1214,16 @@ rspamd_kv_radix_validate (gpointer key, guint keylen) /** * Insert an element inside cache */ -static struct rspamd_kv_element* -rspamd_kv_radix_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, gpointer value, gsize len) +static struct rspamd_kv_element * +rspamd_kv_radix_insert (struct rspamd_kv_cache *c, + gpointer key, + guint keylen, + gpointer value, + gsize len) { - struct rspamd_kv_element *elt; - struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; - guint32 rkey = rspamd_kv_radix_validate (key, keylen); + struct rspamd_kv_element *elt; + struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; + guint32 rkey = rspamd_kv_radix_validate (key, keylen); if (rkey == 0) { return NULL; @@ -1121,12 +1231,13 @@ rspamd_kv_radix_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, g elt = (struct rspamd_kv_element *)radix32tree_find (cache->tree, rkey); if ((uintptr_t)elt == RADIX_NO_VALUE) { - elt = g_slice_alloc (sizeof (struct rspamd_kv_element) + len + keylen + 1); + elt = g_slice_alloc ( + sizeof (struct rspamd_kv_element) + len + keylen + 1); elt->age = time (NULL); elt->keylen = keylen; elt->size = len; elt->flags = 0; - memcpy (ELT_KEY (elt), key, keylen + 1); + memcpy (ELT_KEY (elt), key, keylen + 1); memcpy (ELT_DATA (elt), value, len); elt->p = &elt->data; radix32tree_insert (cache->tree, rkey, 0xffffffff, (uintptr_t)elt); @@ -1140,12 +1251,13 @@ rspamd_kv_radix_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, g /* Free it by self */ g_slice_free1 (ELT_SIZE (elt), elt); } - elt = g_slice_alloc (sizeof (struct rspamd_kv_element) + len + keylen + 1); + elt = g_slice_alloc ( + sizeof (struct rspamd_kv_element) + len + keylen + 1); elt->age = time (NULL); elt->keylen = keylen; elt->size = len; elt->flags = 0; - memcpy (ELT_KEY (elt), key, keylen + 1); + memcpy (ELT_KEY (elt), key, keylen + 1); memcpy (ELT_DATA (elt), value, len); elt->p = &elt->data; radix32tree_insert (cache->tree, rkey, 0xffffffff, (uintptr_t)elt); @@ -1157,12 +1269,12 @@ rspamd_kv_radix_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, g /** * Lookup an item inside radix */ -static struct rspamd_kv_element* +static struct rspamd_kv_element * rspamd_kv_radix_lookup (struct rspamd_kv_cache *c, gpointer key, guint keylen) { - struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; - guint32 rkey = rspamd_kv_radix_validate (key, keylen); - struct rspamd_kv_element *elt; + struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; + guint32 rkey = rspamd_kv_radix_validate (key, keylen); + struct rspamd_kv_element *elt; elt = (struct rspamd_kv_element *)radix32tree_find (cache->tree, rkey); if ((uintptr_t)elt == RADIX_NO_VALUE) { @@ -1176,11 +1288,14 @@ rspamd_kv_radix_lookup (struct rspamd_kv_cache *c, gpointer key, guint keylen) * Replace an element inside cache */ static gboolean -rspamd_kv_radix_replace (struct rspamd_kv_cache *c, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_kv_radix_replace (struct rspamd_kv_cache *c, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; - guint32 rkey = rspamd_kv_radix_validate (key, keylen); - struct rspamd_kv_element *oldelt; + struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; + guint32 rkey = rspamd_kv_radix_validate (key, keylen); + struct rspamd_kv_element *oldelt; oldelt = (struct rspamd_kv_element *)radix32tree_find (cache->tree, rkey); if ((uintptr_t)oldelt != RADIX_NO_VALUE) { @@ -1206,9 +1321,9 @@ rspamd_kv_radix_replace (struct rspamd_kv_cache *c, gpointer key, guint keylen, static struct rspamd_kv_element * rspamd_kv_radix_delete (struct rspamd_kv_cache *c, gpointer key, guint keylen) { - struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; - struct rspamd_kv_element *elt; - guint32 rkey = rspamd_kv_radix_validate (key, keylen); + struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; + struct rspamd_kv_element *elt; + guint32 rkey = rspamd_kv_radix_validate (key, keylen); elt = (struct rspamd_kv_element *)radix32tree_find (cache->tree, rkey); if ((uintptr_t)elt != RADIX_NO_VALUE) { @@ -1226,8 +1341,8 @@ rspamd_kv_radix_delete (struct rspamd_kv_cache *c, gpointer key, guint keylen) static void rspamd_kv_radix_steal (struct rspamd_kv_cache *c, struct rspamd_kv_element *elt) { - struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; - guint32 rkey = rspamd_kv_radix_validate (ELT_KEY (elt), elt->keylen); + struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; + guint32 rkey = rspamd_kv_radix_validate (ELT_KEY (elt), elt->keylen); radix32tree_delete (cache->tree, rkey, 0xffffffff); @@ -1239,7 +1354,7 @@ rspamd_kv_radix_steal (struct rspamd_kv_cache *c, struct rspamd_kv_element *elt) static void rspamd_kv_radix_destroy (struct rspamd_kv_cache *c) { - struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; + struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c; radix_tree_free (cache->tree); g_slice_free1 (sizeof (struct rspamd_kv_radix_cache), cache); @@ -1248,10 +1363,10 @@ rspamd_kv_radix_destroy (struct rspamd_kv_cache *c) /** * Create new radix kv cache */ -struct rspamd_kv_cache* +struct rspamd_kv_cache * rspamd_kv_radix_new (void) { - struct rspamd_kv_radix_cache *new; + struct rspamd_kv_radix_cache *new; new = g_slice_alloc (sizeof (struct rspamd_kv_radix_cache)); new->tree = radix_tree_create (); @@ -1272,13 +1387,13 @@ rspamd_kv_radix_new (void) * KV cache hash table */ struct rspamd_kv_judy_cache { - cache_init init_func; /*< this callback is called on kv storage initialization */ - cache_insert insert_func; /*< this callback is called when element is inserted */ - cache_replace replace_func; /*< this callback is called when element is replace */ - cache_lookup lookup_func; /*< this callback is used for lookup of element */ - cache_delete delete_func; /*< this callback is called when an element is deleted */ - cache_steal steal_func; /*< this callback is used to replace duplicates in cache */ - cache_destroy destroy_func; /*< this callback is used for destroying all elements inside cache */ + cache_init init_func; /*< this callback is called on kv storage initialization */ + cache_insert insert_func; /*< this callback is called when element is inserted */ + cache_replace replace_func; /*< this callback is called when element is replace */ + cache_lookup lookup_func; /*< this callback is used for lookup of element */ + cache_delete delete_func; /*< this callback is called when an element is deleted */ + cache_steal steal_func; /*< this callback is used to replace duplicates in cache */ + cache_destroy destroy_func; /*< this callback is used for destroying all elements inside cache */ Pvoid_t judy; }; @@ -1286,11 +1401,11 @@ struct rspamd_kv_judy_cache { /** * Lookup an item inside judy */ -static struct rspamd_kv_element* +static struct rspamd_kv_element * rspamd_kv_judy_lookup (struct rspamd_kv_cache *c, gpointer key, guint keylen) { - struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; - struct rspamd_kv_element *elt = NULL, **pelt; + struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; + struct rspamd_kv_element *elt = NULL, **pelt; JHSG (pelt, cache->judy, key, keylen); if (pelt != NULL) { @@ -1305,9 +1420,9 @@ rspamd_kv_judy_lookup (struct rspamd_kv_cache *c, gpointer key, guint keylen) static struct rspamd_kv_element * rspamd_kv_judy_delete (struct rspamd_kv_cache *c, gpointer key, guint keylen) { - struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; - struct rspamd_kv_element *elt; - gint rc; + struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; + struct rspamd_kv_element *elt; + gint rc; elt = rspamd_kv_judy_lookup (c, key, keylen); if (elt) { @@ -1322,8 +1437,8 @@ rspamd_kv_judy_delete (struct rspamd_kv_cache *c, gpointer key, guint keylen) static void rspamd_kv_judy_steal (struct rspamd_kv_cache *c, struct rspamd_kv_element *elt) { - struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; - gint rc; + struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; + gint rc; JHSD (rc, cache->judy, ELT_KEY (elt), elt->keylen); } @@ -1331,19 +1446,24 @@ rspamd_kv_judy_steal (struct rspamd_kv_cache *c, struct rspamd_kv_element *elt) /** * Insert an element inside cache */ -static struct rspamd_kv_element* -rspamd_kv_judy_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, gpointer value, gsize len) +static struct rspamd_kv_element * +rspamd_kv_judy_insert (struct rspamd_kv_cache *c, + gpointer key, + guint keylen, + gpointer value, + gsize len) { - struct rspamd_kv_element *elt, **pelt; - struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; + struct rspamd_kv_element *elt, **pelt; + struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; if ((elt = rspamd_kv_judy_lookup (c, key, keylen)) == NULL) { - elt = g_slice_alloc (sizeof (struct rspamd_kv_element) + len + keylen + 1); + elt = g_slice_alloc ( + sizeof (struct rspamd_kv_element) + len + keylen + 1); elt->age = time (NULL); elt->keylen = keylen; elt->size = len; elt->flags = 0; - memcpy (ELT_KEY (elt), key, keylen); + memcpy (ELT_KEY (elt), key, keylen); memcpy (ELT_DATA (elt), value, len); JHSI (pelt, cache->judy, ELT_KEY (elt), elt->keylen); elt->p = &elt->data; @@ -1358,12 +1478,13 @@ rspamd_kv_judy_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, gp /* Free it by self */ g_slice_free1 (ELT_SIZE (elt), elt); } - elt = g_slice_alloc0 (sizeof (struct rspamd_kv_element) + len + keylen + 1); + elt = g_slice_alloc0 ( + sizeof (struct rspamd_kv_element) + len + keylen + 1); elt->age = time (NULL); elt->keylen = keylen; elt->size = len; elt->flags = 0; - memcpy (ELT_KEY (elt), key, keylen); + memcpy (ELT_KEY (elt), key, keylen); memcpy (ELT_DATA (elt), value, len); elt->p = &elt->data; JHSI (pelt, cache->judy, ELT_KEY (elt), elt->keylen); @@ -1377,10 +1498,13 @@ rspamd_kv_judy_insert (struct rspamd_kv_cache *c, gpointer key, guint keylen, gp * Replace an element inside cache */ static gboolean -rspamd_kv_judy_replace (struct rspamd_kv_cache *c, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_kv_judy_replace (struct rspamd_kv_cache *c, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; - struct rspamd_kv_element *oldelt, **pelt; + struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; + struct rspamd_kv_element *oldelt, **pelt; if ((oldelt = rspamd_kv_judy_lookup (c, key, keylen)) != NULL) { rspamd_kv_judy_steal (c, elt); @@ -1406,8 +1530,8 @@ rspamd_kv_judy_replace (struct rspamd_kv_cache *c, gpointer key, guint keylen, s static void rspamd_kv_judy_destroy (struct rspamd_kv_cache *c) { - struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; - glong bytes; + struct rspamd_kv_judy_cache *cache = (struct rspamd_kv_judy_cache *)c; + glong bytes; JHSFA (bytes, cache->judy); g_slice_free1 (sizeof (struct rspamd_kv_judy_cache), cache); @@ -1416,10 +1540,10 @@ rspamd_kv_judy_destroy (struct rspamd_kv_cache *c) /** * Judy tree */ -struct rspamd_kv_cache* +struct rspamd_kv_cache * rspamd_kv_judy_new (void) { - struct rspamd_kv_judy_cache *new; + struct rspamd_kv_judy_cache *new; new = g_slice_alloc (sizeof (struct rspamd_kv_judy_cache)); new->judy = NULL; diff --git a/src/kvstorage.h b/src/kvstorage.h index 05ff866e6..91db10df3 100644 --- a/src/kvstorage.h +++ b/src/kvstorage.h @@ -47,34 +47,46 @@ struct rspamd_kv_element; /* Callbacks for cache */ typedef void (*cache_init)(struct rspamd_kv_cache *cache); -typedef struct rspamd_kv_element* (*cache_insert)(struct rspamd_kv_cache *cache, - gpointer key, guint keylen, gpointer value, gsize len); -typedef gboolean (*cache_replace)(struct rspamd_kv_cache *cache, gpointer key, guint keylen, - struct rspamd_kv_element *elt); -typedef struct rspamd_kv_element* (*cache_lookup)(struct rspamd_kv_cache *cache, gpointer key, guint keylen); -typedef struct rspamd_kv_element* (*cache_delete)(struct rspamd_kv_cache *cache, gpointer key, guint keylen); -typedef void (*cache_steal)(struct rspamd_kv_cache *cache, struct rspamd_kv_element* elt); +typedef struct rspamd_kv_element * (*cache_insert)(struct rspamd_kv_cache *cache, + gpointer key, guint keylen, gpointer value, gsize len); +typedef gboolean (*cache_replace)(struct rspamd_kv_cache *cache, gpointer key, + guint keylen, + struct rspamd_kv_element *elt); +typedef struct rspamd_kv_element * (*cache_lookup)(struct rspamd_kv_cache *cache, + gpointer key, guint keylen); +typedef struct rspamd_kv_element * (*cache_delete)(struct rspamd_kv_cache *cache, + gpointer key, guint keylen); +typedef void (*cache_steal)(struct rspamd_kv_cache *cache, + struct rspamd_kv_element * elt); typedef void (*cache_destroy)(struct rspamd_kv_cache *cache); /* Callbacks for backend */ typedef void (*backend_init)(struct rspamd_kv_backend *backend); -typedef gboolean (*backend_insert)(struct rspamd_kv_backend *backend, gpointer key, guint keylen, - struct rspamd_kv_element *elt); -typedef gboolean (*backend_replace)(struct rspamd_kv_backend *backend, gpointer key, guint keylen, - struct rspamd_kv_element *elt); -typedef struct rspamd_kv_element* (*backend_lookup)(struct rspamd_kv_backend *backend, gpointer key, - guint keylen); -typedef void (*backend_delete)(struct rspamd_kv_backend *backend, gpointer key, guint keylen); +typedef gboolean (*backend_insert)(struct rspamd_kv_backend *backend, + gpointer key, guint keylen, + struct rspamd_kv_element *elt); +typedef gboolean (*backend_replace)(struct rspamd_kv_backend *backend, + gpointer key, guint keylen, + struct rspamd_kv_element *elt); +typedef struct rspamd_kv_element * (*backend_lookup)(struct rspamd_kv_backend * + backend, gpointer key, + guint keylen); +typedef void (*backend_delete)(struct rspamd_kv_backend *backend, gpointer key, + guint keylen); typedef gboolean (*backend_sync)(struct rspamd_kv_backend *backend); -typedef gboolean (*backend_incref)(struct rspamd_kv_backend *backend, gpointer key, guint keylen); +typedef gboolean (*backend_incref)(struct rspamd_kv_backend *backend, + gpointer key, guint keylen); typedef void (*backend_destroy)(struct rspamd_kv_backend *backend); /* Callbacks for expire */ typedef void (*expire_init)(struct rspamd_kv_expire *expire); -typedef void (*expire_insert)(struct rspamd_kv_expire *expire, struct rspamd_kv_element *elt); -typedef void (*expire_delete)(struct rspamd_kv_expire *expire, struct rspamd_kv_element *elt); -typedef gboolean (*expire_step)(struct rspamd_kv_expire *expire, struct rspamd_kv_storage *storage, - time_t now, gboolean forced); +typedef void (*expire_insert)(struct rspamd_kv_expire *expire, + struct rspamd_kv_element *elt); +typedef void (*expire_delete)(struct rspamd_kv_expire *expire, + struct rspamd_kv_element *elt); +typedef gboolean (*expire_step)(struct rspamd_kv_expire *expire, + struct rspamd_kv_storage *storage, + time_t now, gboolean forced); typedef void (*expire_destroy)(struct rspamd_kv_expire *expire); @@ -93,47 +105,48 @@ enum rspamd_kv_flags { #define ELT_DATA(elt) (gchar *)(elt)->data + (elt)->keylen + 1 #define ELT_LONG(elt) *((glong *)((elt)->data + (elt)->keylen + 1)) #define ELT_KEY(elt) (gchar *)(elt)->data -#define ELT_SIZE(elt) elt->size + sizeof(struct rspamd_kv_element) + elt->keylen + 1 +#define ELT_SIZE(elt) elt->size + sizeof(struct rspamd_kv_element) + \ + elt->keylen + 1 /* Common structures description */ struct rspamd_kv_element { - time_t age; /*< age of element */ - guint32 expire; /*< expire of element */ - gint flags; /*< element flags */ - gsize size; /*< size of element */ - TAILQ_ENTRY (rspamd_kv_element) entry; /*< list entry */ - guint keylen; /*< length of key */ - - gpointer p; /*< pointer to data */ - gchar data[1]; /*< expandable data */ + time_t age; /*< age of element */ + guint32 expire; /*< expire of element */ + gint flags; /*< element flags */ + gsize size; /*< size of element */ + TAILQ_ENTRY (rspamd_kv_element) entry; /*< list entry */ + guint keylen; /*< length of key */ + + gpointer p; /*< pointer to data */ + gchar data[1]; /*< expandable data */ }; struct rspamd_kv_cache { - cache_init init_func; /*< this callback is called on kv storage initialization */ - cache_insert insert_func; /*< this callback is called when element is inserted */ - cache_replace replace_func; /*< this callback is called when element is replace */ - cache_lookup lookup_func; /*< this callback is used for lookup of element */ - cache_delete delete_func; /*< this callback is called when an element is deleted */ - cache_steal steal_func; /*< this callback is used to replace duplicates in cache */ - cache_destroy destroy_func; /*< this callback is used for destroying all elements inside cache */ + cache_init init_func; /*< this callback is called on kv storage initialization */ + cache_insert insert_func; /*< this callback is called when element is inserted */ + cache_replace replace_func; /*< this callback is called when element is replace */ + cache_lookup lookup_func; /*< this callback is used for lookup of element */ + cache_delete delete_func; /*< this callback is called when an element is deleted */ + cache_steal steal_func; /*< this callback is used to replace duplicates in cache */ + cache_destroy destroy_func; /*< this callback is used for destroying all elements inside cache */ }; struct rspamd_kv_backend { - backend_init init_func; /*< this callback is called on kv storage initialization */ - backend_insert insert_func; /*< this callback is called when element is inserted */ - backend_replace replace_func; /*< this callback is called when element is replaced */ - backend_lookup lookup_func; /*< this callback is used for lookup of element */ - backend_delete delete_func; /*< this callback is called when an element is deleted */ - backend_sync sync_func; /*< this callback is called when backend need to be synced */ - backend_incref incref_func; /*< this callback is called when element must be ref'd */ - backend_destroy destroy_func; /*< this callback is used for destroying all elements inside backend */ + backend_init init_func; /*< this callback is called on kv storage initialization */ + backend_insert insert_func; /*< this callback is called when element is inserted */ + backend_replace replace_func; /*< this callback is called when element is replaced */ + backend_lookup lookup_func; /*< this callback is used for lookup of element */ + backend_delete delete_func; /*< this callback is called when an element is deleted */ + backend_sync sync_func; /*< this callback is called when backend need to be synced */ + backend_incref incref_func; /*< this callback is called when element must be ref'd */ + backend_destroy destroy_func; /*< this callback is used for destroying all elements inside backend */ }; struct rspamd_kv_expire { - expire_init init_func; /*< this callback is called on kv storage initialization */ - expire_insert insert_func; /*< this callback is called when element is inserted */ - expire_step step_func; /*< this callback is used when cache is full */ - expire_delete delete_func; /*< this callback is called when an element is deleted */ - expire_destroy destroy_func; /*< this callback is used for destroying all elements inside expire */ + expire_init init_func; /*< this callback is called on kv storage initialization */ + expire_insert insert_func; /*< this callback is called when element is inserted */ + expire_step step_func; /*< this callback is used when cache is full */ + expire_delete delete_func; /*< this callback is called when an element is deleted */ + expire_destroy destroy_func; /*< this callback is used for destroying all elements inside expire */ }; /* Main kv storage structure */ @@ -143,61 +156,103 @@ struct rspamd_kv_storage { struct rspamd_kv_backend *backend; struct rspamd_kv_expire *expire; - gsize elts; /*< current elements count in a storage */ - gsize max_elts; /*< maximum number of elements in a storage */ + gsize elts; /*< current elements count in a storage */ + gsize max_elts; /*< maximum number of elements in a storage */ - gsize memory; /*< memory eaten */ - gsize max_memory; /*< memory limit */ + gsize memory; /*< memory eaten */ + gsize max_memory; /*< memory limit */ - gint id; /* char ID */ - gchar *name; /* numeric ID */ + gint id; /* char ID */ + gchar *name; /* numeric ID */ - gboolean no_overwrite; /* do not overwrite data with the same keys */ + gboolean no_overwrite; /* do not overwrite data with the same keys */ #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30)) - GRWLock rwlock; /* rwlock in new glib */ + GRWLock rwlock; /* rwlock in new glib */ #else - GStaticRWLock rwlock; /* rwlock for threaded access */ + GStaticRWLock rwlock; /* rwlock for threaded access */ #endif }; /** Create new kv storage */ -struct rspamd_kv_storage *rspamd_kv_storage_new (gint id, const gchar *name, - struct rspamd_kv_cache *cache, struct rspamd_kv_backend *backend, - struct rspamd_kv_expire *expire, - gsize max_elts, gsize max_memory, gboolean no_overwrite); +struct rspamd_kv_storage * rspamd_kv_storage_new (gint id, const gchar *name, + struct rspamd_kv_cache *cache, struct rspamd_kv_backend *backend, + struct rspamd_kv_expire *expire, + gsize max_elts, gsize max_memory, gboolean no_overwrite); /** Insert new element to the kv storage */ -gboolean rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, gpointer key, guint keylen, gpointer data, gsize len, gint flags, guint expire); +gboolean rspamd_kv_storage_insert (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + gpointer data, + gsize len, + gint flags, + guint expire); /** Insert element only in cache */ -gboolean rspamd_kv_storage_insert_cache (struct rspamd_kv_storage *storage, gpointer key, guint keylen, - gpointer data, gsize len, gint flags, guint expire, struct rspamd_kv_element **pelt); +gboolean rspamd_kv_storage_insert_cache (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + gpointer data, + gsize len, + gint flags, + guint expire, + struct rspamd_kv_element **pelt); /** Replace an element in the kv storage */ -gboolean rspamd_kv_storage_replace (struct rspamd_kv_storage *storage, gpointer key, guint keylen, struct rspamd_kv_element *elt); +gboolean rspamd_kv_storage_replace (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt); /** Increment value in kvstorage */ -gboolean rspamd_kv_storage_increment (struct rspamd_kv_storage *storage, gpointer key, guint keylen, glong *value); +gboolean rspamd_kv_storage_increment (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + glong *value); /** Lookup an element inside kv storage */ -struct rspamd_kv_element* rspamd_kv_storage_lookup (struct rspamd_kv_storage *storage, gpointer key, guint keylen, time_t now); +struct rspamd_kv_element * rspamd_kv_storage_lookup ( + struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + time_t now); /** Expire an element from kv storage */ -struct rspamd_kv_element* rspamd_kv_storage_delete (struct rspamd_kv_storage *storage, gpointer key, guint keylen); +struct rspamd_kv_element * rspamd_kv_storage_delete ( + struct rspamd_kv_storage *storage, + gpointer key, + guint keylen); /** Destroy kv storage */ void rspamd_kv_storage_destroy (struct rspamd_kv_storage *storage); /** Insert array */ -gboolean rspamd_kv_storage_insert_array (struct rspamd_kv_storage *storage, gpointer key, guint keylen, guint elt_size, gpointer data, gsize len, gint flags, guint expire); +gboolean rspamd_kv_storage_insert_array (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + guint elt_size, + gpointer data, + gsize len, + gint flags, + guint expire); /** Set element inside array */ -gboolean rspamd_kv_storage_set_array (struct rspamd_kv_storage *storage, gpointer key, guint keylen, guint elt_num, - gpointer data, gsize len, time_t now); +gboolean rspamd_kv_storage_set_array (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + guint elt_num, + gpointer data, + gsize len, + time_t now); /** Get element inside array */ -gboolean rspamd_kv_storage_get_array (struct rspamd_kv_storage *storage, gpointer key, guint keylen, guint elt_num, - gpointer *data, gsize *len, time_t now); +gboolean rspamd_kv_storage_get_array (struct rspamd_kv_storage *storage, + gpointer key, + guint keylen, + guint elt_num, + gpointer *data, + gsize *len, + time_t now); /* Hash table functions */ guint kv_elt_hash_func (gconstpointer e); @@ -206,23 +261,23 @@ gboolean kv_elt_compare_func (gconstpointer e1, gconstpointer e2); /** * LRU expire */ -struct rspamd_kv_expire* rspamd_lru_expire_new (void); +struct rspamd_kv_expire * rspamd_lru_expire_new (void); /** * Ordinary hash */ -struct rspamd_kv_cache* rspamd_kv_hash_new (void); +struct rspamd_kv_cache * rspamd_kv_hash_new (void); /** * Radix tree */ -struct rspamd_kv_cache* rspamd_kv_radix_new (void); +struct rspamd_kv_cache * rspamd_kv_radix_new (void); #ifdef WITH_JUDY /** * Judy tree */ -struct rspamd_kv_cache* rspamd_kv_judy_new (void); +struct rspamd_kv_cache * rspamd_kv_judy_new (void); #endif #endif /* KVSTORAGE_H_ */ diff --git a/src/kvstorage_bdb.c b/src/kvstorage_bdb.c index 7970291f6..df2a5ba19 100644 --- a/src/kvstorage_bdb.c +++ b/src/kvstorage_bdb.c @@ -40,15 +40,15 @@ struct bdb_op { /* Main bdb structure */ struct rspamd_bdb_backend { - backend_init init_func; /*< this callback is called on kv storage initialization */ - backend_insert insert_func; /*< this callback is called when element is inserted */ - backend_replace replace_func; /*< this callback is called when element is replaced */ - backend_lookup lookup_func; /*< this callback is used for lookup of element */ - backend_delete delete_func; /*< this callback is called when an element is deleted */ - backend_sync sync_func; /*< this callback is called when backend need to be synced */ - backend_destroy destroy_func; /*< this callback is used for destroying all elements inside backend */ - DB_ENV *envp; /*< db environment */ - DB *dbp; /*< db pointer */ + backend_init init_func; /*< this callback is called on kv storage initialization */ + backend_insert insert_func; /*< this callback is called when element is inserted */ + backend_replace replace_func; /*< this callback is called when element is replaced */ + backend_lookup lookup_func; /*< this callback is used for lookup of element */ + backend_delete delete_func; /*< this callback is called when an element is deleted */ + backend_sync sync_func; /*< this callback is called when backend need to be synced */ + backend_destroy destroy_func; /*< this callback is used for destroying all elements inside backend */ + DB_ENV *envp; /*< db environment */ + DB *dbp; /*< db pointer */ gchar *filename; gchar *dirname; guint sync_ops; @@ -59,16 +59,19 @@ struct rspamd_bdb_backend { /* Process single bdb operation */ static gboolean -bdb_process_single_op (struct rspamd_bdb_backend *db, DB_TXN *txn, struct bdb_op *op) +bdb_process_single_op (struct rspamd_bdb_backend *db, + DB_TXN *txn, + struct bdb_op *op) { - DBT db_key, db_data; + DBT db_key, db_data; - memset (&db_key, 0, sizeof(DBT)); + memset (&db_key, 0, sizeof(DBT)); memset (&db_data, 0, sizeof(DBT)); db_key.size = op->elt->keylen; db_key.data = ELT_KEY (op->elt); - db_data.size = op->elt->size + sizeof (struct rspamd_kv_element) + op->elt->keylen + 1; + db_data.size = op->elt->size + sizeof (struct rspamd_kv_element) + + op->elt->keylen + 1; db_data.data = op->elt; switch (op->op) { @@ -96,14 +99,14 @@ bdb_process_single_op (struct rspamd_bdb_backend *db, DB_TXN *txn, struct bdb_op static gboolean bdb_process_queue (struct rspamd_kv_backend *backend) { - struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; - struct bdb_op *op; - GList *cur; + struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; + struct bdb_op *op; + GList *cur; cur = db->ops_queue->head; while (cur) { op = cur->data; - if (! bdb_process_single_op (db, NULL, op)) { + if (!bdb_process_single_op (db, NULL, op)) { return FALSE; } cur = g_list_next (cur); @@ -113,7 +116,8 @@ bdb_process_queue (struct rspamd_kv_backend *backend) cur = db->ops_queue->head; while (cur) { op = cur->data; - if (op->op == BDB_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != 0) { + if (op->op == BDB_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != + 0) { /* Also clean memory */ g_slice_free1 (ELT_SIZE (op->elt), op->elt); } @@ -132,9 +136,9 @@ bdb_process_queue (struct rspamd_kv_backend *backend) static void rspamd_bdb_init (struct rspamd_kv_backend *backend) { - struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; - guint32 flags; - gint ret; + struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; + guint32 flags; + gint ret; if ((ret = db_env_create (&db->envp, 0)) != 0) { /* Cannot create environment */ @@ -142,9 +146,9 @@ rspamd_bdb_init (struct rspamd_kv_backend *backend) } flags = DB_INIT_MPOOL | - DB_CREATE | /* Create the environment if it does not already exist. */ - DB_INIT_LOCK | /* Initialize locking. */ - DB_THREAD; /* Use threads */ + DB_CREATE | /* Create the environment if it does not already exist. */ + DB_INIT_LOCK | /* Initialize locking. */ + DB_THREAD; /* Use threads */ if ((ret = db->envp->open (db->envp, db->dirname, flags, 0)) != 0) { /* Cannot open environment */ @@ -168,7 +172,9 @@ rspamd_bdb_init (struct rspamd_kv_backend *backend) goto err; } - if ((ret = db->dbp->open (db->dbp, NULL, db->filename, NULL, DB_HASH, flags, 0)) != 0) { + if ((ret = + db->dbp->open (db->dbp, NULL, db->filename, NULL, DB_HASH, flags, + 0)) != 0) { goto err; } @@ -187,10 +193,13 @@ err: } static gboolean -rspamd_bdb_insert (struct rspamd_kv_backend *backend, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_bdb_insert (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; - struct bdb_op *op; + struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; + struct bdb_op *op; if (!db->initialized) { return FALSE; @@ -204,7 +213,8 @@ rspamd_bdb_insert (struct rspamd_kv_backend *backend, gpointer key, guint keylen g_queue_push_head (db->ops_queue, op); g_hash_table_insert (db->ops_hash, elt, op); - if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= db->sync_ops) { + if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= + db->sync_ops) { return bdb_process_queue (backend); } @@ -212,10 +222,13 @@ rspamd_bdb_insert (struct rspamd_kv_backend *backend, gpointer key, guint keylen } static gboolean -rspamd_bdb_replace (struct rspamd_kv_backend *backend, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_bdb_replace (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; - struct bdb_op *op; + struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; + struct bdb_op *op; if (!db->initialized) { return FALSE; @@ -229,21 +242,23 @@ rspamd_bdb_replace (struct rspamd_kv_backend *backend, gpointer key, guint keyle g_queue_push_head (db->ops_queue, op); g_hash_table_insert (db->ops_hash, elt, op); - if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= db->sync_ops) { + if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= + db->sync_ops) { return bdb_process_queue (backend); } return TRUE; } -static struct rspamd_kv_element* -rspamd_bdb_lookup (struct rspamd_kv_backend *backend, gpointer key, guint keylen) +static struct rspamd_kv_element * +rspamd_bdb_lookup (struct rspamd_kv_backend *backend, gpointer key, + guint keylen) { - struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; - struct bdb_op *op; - DBT db_key, db_data; - struct rspamd_kv_element *elt = NULL; - struct rspamd_kv_element search_elt; + struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; + struct bdb_op *op; + DBT db_key, db_data; + struct rspamd_kv_element *elt = NULL; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -260,7 +275,7 @@ rspamd_bdb_lookup (struct rspamd_kv_backend *backend, gpointer key, guint keylen return op->elt; } - memset (&db_key, 0, sizeof(DBT)); + memset (&db_key, 0, sizeof(DBT)); memset (&db_data, 0, sizeof(DBT)); db_key.size = keylen; db_key.data = key; @@ -275,12 +290,13 @@ rspamd_bdb_lookup (struct rspamd_kv_backend *backend, gpointer key, guint keylen } static void -rspamd_bdb_delete (struct rspamd_kv_backend *backend, gpointer key, guint keylen) +rspamd_bdb_delete (struct rspamd_kv_backend *backend, gpointer key, + guint keylen) { - struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; - struct bdb_op *op; - struct rspamd_kv_element *elt; - struct rspamd_kv_element search_elt; + struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; + struct bdb_op *op; + struct rspamd_kv_element *elt; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -306,7 +322,8 @@ rspamd_bdb_delete (struct rspamd_kv_backend *backend, gpointer key, guint keylen g_queue_push_head (db->ops_queue, op); g_hash_table_insert (db->ops_hash, elt, op); - if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= db->sync_ops) { + if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= + db->sync_ops) { bdb_process_queue (backend); } @@ -316,7 +333,7 @@ rspamd_bdb_delete (struct rspamd_kv_backend *backend, gpointer key, guint keylen static void rspamd_bdb_destroy (struct rspamd_kv_backend *backend) { - struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; + struct rspamd_bdb_backend *db = (struct rspamd_bdb_backend *)backend; if (db->initialized) { bdb_process_queue (backend); @@ -338,9 +355,9 @@ rspamd_bdb_destroy (struct rspamd_kv_backend *backend) struct rspamd_kv_backend * rspamd_kv_bdb_new (const gchar *filename, guint sync_ops) { - struct rspamd_bdb_backend *new; - struct stat st; - gchar *dirname; + struct rspamd_bdb_backend *new; + struct stat st; + gchar *dirname; if (filename == NULL) { return NULL; diff --git a/src/kvstorage_bdb.h b/src/kvstorage_bdb.h index c6dd925b5..d71f1f65f 100644 --- a/src/kvstorage_bdb.h +++ b/src/kvstorage_bdb.h @@ -31,7 +31,8 @@ #ifdef WITH_DB /* Create new bdb backend */ -struct rspamd_kv_backend* rspamd_kv_bdb_new (const gchar *filename, guint sync_ops); +struct rspamd_kv_backend * rspamd_kv_bdb_new (const gchar *filename, + guint sync_ops); #endif diff --git a/src/kvstorage_config.c b/src/kvstorage_config.c index 362a47f49..f236c2b4b 100644 --- a/src/kvstorage_config.c +++ b/src/kvstorage_config.c @@ -68,7 +68,7 @@ struct kvstorage_config_parser { static void kvstorage_config_destroy (gpointer k) { - struct kvstorage_config *kconf = k; + struct kvstorage_config *kconf = k; if (kconf->name) { g_free (kconf->name); @@ -83,12 +83,14 @@ kvstorage_config_destroy (gpointer k) /* Init kvstorage */ static void -kvstorage_init_callback (const gpointer key, const gpointer value, gpointer unused) +kvstorage_init_callback (const gpointer key, + const gpointer value, + gpointer unused) { - struct kvstorage_config *kconf = value; - struct rspamd_kv_cache *cache; - struct rspamd_kv_backend *backend = NULL; - struct rspamd_kv_expire *expire = NULL; + struct kvstorage_config *kconf = value; + struct rspamd_kv_cache *cache; + struct rspamd_kv_backend *backend = NULL; + struct rspamd_kv_expire *expire = NULL; switch (kconf->cache.type) { case KVSTORAGE_TYPE_CACHE_HASH: @@ -113,17 +115,22 @@ kvstorage_init_callback (const gpointer key, const gpointer value, gpointer unus backend = NULL; break; case KVSTORAGE_TYPE_BACKEND_FILE: - backend = rspamd_kv_file_new (kconf->backend.filename, kconf->backend.sync_ops, - FILE_STORAGE_LEVELS, kconf->backend.do_fsync, kconf->backend.do_ref); + backend = rspamd_kv_file_new (kconf->backend.filename, + kconf->backend.sync_ops, + FILE_STORAGE_LEVELS, + kconf->backend.do_fsync, + kconf->backend.do_ref); break; #ifdef WITH_DB case KVSTORAGE_TYPE_BACKEND_BDB: - backend = rspamd_kv_bdb_new (kconf->backend.filename, kconf->backend.sync_ops); + backend = rspamd_kv_bdb_new (kconf->backend.filename, + kconf->backend.sync_ops); break; #endif #ifdef WITH_SQLITE case KVSTORAGE_TYPE_BACKEND_SQLITE: - backend = rspamd_kv_sqlite_new (kconf->backend.filename, kconf->backend.sync_ops); + backend = rspamd_kv_sqlite_new (kconf->backend.filename, + kconf->backend.sync_ops); break; #endif } @@ -134,20 +141,27 @@ kvstorage_init_callback (const gpointer key, const gpointer value, gpointer unus break; } - kconf->storage = rspamd_kv_storage_new (kconf->id, kconf->name, cache, backend, expire, - kconf->cache.max_elements, kconf->cache.max_memory, kconf->cache.no_overwrite); + kconf->storage = rspamd_kv_storage_new (kconf->id, + kconf->name, + cache, + backend, + expire, + kconf->cache.max_elements, + kconf->cache.max_memory, + kconf->cache.no_overwrite); } /* XML parse callbacks */ /* Called for open tags <foo bar="baz"> */ -void kvstorage_xml_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) +void +kvstorage_xml_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) { - struct kvstorage_config_parser *kv_parser = user_data; + struct kvstorage_config_parser *kv_parser = user_data; switch (kv_parser->state) { case KVSTORAGE_STATE_INIT: @@ -159,10 +173,12 @@ void kvstorage_xml_start_element (GMarkupParseContext *context, if (kv_parser->pool != NULL) { rspamd_mempool_delete (kv_parser->pool); } - kv_parser->pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + kv_parser->pool = + rspamd_mempool_new (rspamd_mempool_suggest_size ()); /* Create new kvstorage_config */ - kv_parser->current_storage = g_malloc0 (sizeof (struct kvstorage_config)); + kv_parser->current_storage = + g_malloc0 (sizeof (struct kvstorage_config)); kv_parser->current_storage->id = last_id++; } if (g_ascii_strcasecmp (element_name, "type") == 0) { @@ -199,8 +215,9 @@ void kvstorage_xml_start_element (GMarkupParseContext *context, } else { if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected", - element_name); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected", + element_name); } kv_parser->state = KVSTORAGE_STATE_ERROR; } @@ -228,8 +245,9 @@ void kvstorage_xml_start_element (GMarkupParseContext *context, } else { if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected in backend definition", - element_name); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected in backend definition", + element_name); } kv_parser->state = KVSTORAGE_STATE_ERROR; } @@ -241,8 +259,9 @@ void kvstorage_xml_start_element (GMarkupParseContext *context, } else { if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected in expire definition", - element_name); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected in expire definition", + element_name); } kv_parser->state = KVSTORAGE_STATE_ERROR; } @@ -254,24 +273,27 @@ void kvstorage_xml_start_element (GMarkupParseContext *context, } -#define CHECK_TAG(s) \ -do { \ -if (g_ascii_strcasecmp (element_name, kv_parser->cur_elt) == 0) { \ - kv_parser->state = (s); \ -} \ -else { \ - if (*error == NULL) *error = g_error_new (xml_error_quark (), XML_UNMATCHED_TAG, "element %s is unexpected in this state, expected %s", element_name, kv_parser->cur_elt); \ - kv_parser->state = KVSTORAGE_STATE_ERROR; \ -} \ -} while (0) +#define CHECK_TAG(s) \ + do { \ + if (g_ascii_strcasecmp (element_name, kv_parser->cur_elt) == 0) { \ + kv_parser->state = (s); \ + } \ + else { \ + if (*error == NULL) *error = g_error_new ( \ + xml_error_quark (), XML_UNMATCHED_TAG, "element %s is unexpected in this state, expected %s", element_name, \ + kv_parser->cur_elt); \ + kv_parser->state = KVSTORAGE_STATE_ERROR; \ + } \ + } while (0) /* Called for close tags </foo> */ -void kvstorage_xml_end_element (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) +void +kvstorage_xml_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) { - struct kvstorage_config_parser *kv_parser = user_data; + struct kvstorage_config_parser *kv_parser = user_data; switch (kv_parser->state) { case KVSTORAGE_STATE_INIT: @@ -281,8 +303,9 @@ void kvstorage_xml_end_element (GMarkupParseContext *context, return; } if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "end element %s is unexpected, expected start element", - element_name); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "end element %s is unexpected, expected start element", + element_name); } kv_parser->state = KVSTORAGE_STATE_ERROR; break; @@ -310,8 +333,9 @@ void kvstorage_xml_end_element (GMarkupParseContext *context, } else { if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected", - element_name); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected", + element_name); } kv_parser->state = KVSTORAGE_STATE_ERROR; } @@ -322,8 +346,9 @@ void kvstorage_xml_end_element (GMarkupParseContext *context, } else { if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected", - element_name); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected", + element_name); } kv_parser->state = KVSTORAGE_STATE_ERROR; } @@ -336,18 +361,19 @@ void kvstorage_xml_end_element (GMarkupParseContext *context, #undef CHECK_TAG /* text is not nul-terminated */ -void kvstorage_xml_text (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) +void +kvstorage_xml_text (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) { - struct kvstorage_config_parser *kv_parser = user_data; - gchar *err_str; + struct kvstorage_config_parser *kv_parser = user_data; + gchar *err_str; /* Strip space symbols */ while (*text && g_ascii_isspace (*text)) { - text ++; + text++; } if (*text == '\0') { /* Skip empty text */ @@ -358,7 +384,9 @@ void kvstorage_xml_text (GMarkupParseContext *context, case KVSTORAGE_STATE_INIT: case KVSTORAGE_STATE_PARAM: if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "text is unexpected, expected start element"); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, + "text is unexpected, expected start element"); } kv_parser->state = KVSTORAGE_STATE_ERROR; break; @@ -366,12 +394,14 @@ void kvstorage_xml_text (GMarkupParseContext *context, kv_parser->current_storage->id = strtoul (text, &err_str, 10); if ((gsize)(err_str - text) != text_len) { if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "invalid number: %*s", (int)text_len, text); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "invalid number: %*s", + (int)text_len, text); } kv_parser->state = KVSTORAGE_STATE_ERROR; } else { - last_id ++; + last_id++; last_id = MAX (kv_parser->current_storage->id, last_id); } break; @@ -380,77 +410,103 @@ void kvstorage_xml_text (GMarkupParseContext *context, rspamd_strlcpy (kv_parser->current_storage->name, text, text_len + 1); break; case KVSTORAGE_STATE_CACHE_MAX_ELTS: - kv_parser->current_storage->cache.max_elements = rspamd_config_parse_limit (text, text_len); + kv_parser->current_storage->cache.max_elements = + rspamd_config_parse_limit (text, text_len); break; case KVSTORAGE_STATE_CACHE_MAX_MEM: - kv_parser->current_storage->cache.max_memory = rspamd_config_parse_limit (text, text_len); + kv_parser->current_storage->cache.max_memory = + rspamd_config_parse_limit (text, text_len); break; case KVSTORAGE_STATE_CACHE_NO_OVERWRITE: - kv_parser->current_storage->cache.no_overwrite = rspamd_config_parse_flag (text); + kv_parser->current_storage->cache.no_overwrite = + rspamd_config_parse_flag (text); break; case KVSTORAGE_STATE_CACHE_TYPE: - if (g_ascii_strncasecmp (text, "hash", MIN (text_len, sizeof ("hash") - 1)) == 0) { + if (g_ascii_strncasecmp (text, "hash", + MIN (text_len, sizeof ("hash") - 1)) == 0) { kv_parser->current_storage->cache.type = KVSTORAGE_TYPE_CACHE_HASH; } - else if (g_ascii_strncasecmp (text, "radix", MIN (text_len, sizeof ("radix") - 1)) == 0) { + else if (g_ascii_strncasecmp (text, "radix", + MIN (text_len, sizeof ("radix") - 1)) == 0) { kv_parser->current_storage->cache.type = KVSTORAGE_TYPE_CACHE_RADIX; } #ifdef WITH_JUDY - else if (g_ascii_strncasecmp (text, "judy", MIN (text_len, sizeof ("judy") - 1)) == 0) { + else if (g_ascii_strncasecmp (text, "judy", + MIN (text_len, sizeof ("judy") - 1)) == 0) { kv_parser->current_storage->cache.type = KVSTORAGE_TYPE_CACHE_JUDY; } #endif else { if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "invalid cache type: %*s", (int)text_len, text); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "invalid cache type: %*s", + (int)text_len, text); } kv_parser->state = KVSTORAGE_STATE_ERROR; } break; case KVSTORAGE_STATE_BACKEND_TYPE: - if (g_ascii_strncasecmp (text, "null", MIN (text_len, sizeof ("null") - 1)) == 0) { - kv_parser->current_storage->backend.type = KVSTORAGE_TYPE_BACKEND_NULL; + if (g_ascii_strncasecmp (text, "null", + MIN (text_len, sizeof ("null") - 1)) == 0) { + kv_parser->current_storage->backend.type = + KVSTORAGE_TYPE_BACKEND_NULL; } - else if (g_ascii_strncasecmp (text, "file", MIN (text_len, sizeof ("file") - 1)) == 0) { - kv_parser->current_storage->backend.type = KVSTORAGE_TYPE_BACKEND_FILE; + else if (g_ascii_strncasecmp (text, "file", + MIN (text_len, sizeof ("file") - 1)) == 0) { + kv_parser->current_storage->backend.type = + KVSTORAGE_TYPE_BACKEND_FILE; } #ifdef WITH_DB - else if (g_ascii_strncasecmp (text, "bdb", MIN (text_len, sizeof ("bdb") - 1)) == 0) { - kv_parser->current_storage->backend.type = KVSTORAGE_TYPE_BACKEND_BDB; + else if (g_ascii_strncasecmp (text, "bdb", + MIN (text_len, sizeof ("bdb") - 1)) == 0) { + kv_parser->current_storage->backend.type = + KVSTORAGE_TYPE_BACKEND_BDB; } #endif #ifdef WITH_SQLITE - else if (g_ascii_strncasecmp (text, "sqlite", MIN (text_len, sizeof ("sqlite") - 1)) == 0) { - kv_parser->current_storage->backend.type = KVSTORAGE_TYPE_BACKEND_SQLITE; + else if (g_ascii_strncasecmp (text, "sqlite", + MIN (text_len, sizeof ("sqlite") - 1)) == 0) { + kv_parser->current_storage->backend.type = + KVSTORAGE_TYPE_BACKEND_SQLITE; } #endif else { if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "invalid backend type: %*s", (int)text_len, text); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "invalid backend type: %*s", + (int)text_len, text); } kv_parser->state = KVSTORAGE_STATE_ERROR; } break; case KVSTORAGE_STATE_BACKEND_FILENAME: kv_parser->current_storage->backend.filename = g_malloc (text_len + 1); - rspamd_strlcpy (kv_parser->current_storage->backend.filename, text, text_len + 1); + rspamd_strlcpy (kv_parser->current_storage->backend.filename, + text, + text_len + 1); break; case KVSTORAGE_STATE_BACKEND_SYNC_OPS: - kv_parser->current_storage->backend.sync_ops = rspamd_config_parse_limit (text, text_len); + kv_parser->current_storage->backend.sync_ops = + rspamd_config_parse_limit (text, text_len); break; case KVSTORAGE_STATE_BACKEND_DO_FSYNC: - kv_parser->current_storage->backend.do_fsync = rspamd_config_parse_flag (text); + kv_parser->current_storage->backend.do_fsync = + rspamd_config_parse_flag (text); break; case KVSTORAGE_STATE_BACKEND_DO_REF: - kv_parser->current_storage->backend.do_ref = rspamd_config_parse_flag (text); + kv_parser->current_storage->backend.do_ref = rspamd_config_parse_flag ( + text); break; case KVSTORAGE_STATE_EXPIRE_TYPE: - if (g_ascii_strncasecmp (text, "lru", MIN (text_len, sizeof ("lru") - 1)) == 0) { + if (g_ascii_strncasecmp (text, "lru", + MIN (text_len, sizeof ("lru") - 1)) == 0) { kv_parser->current_storage->expire.type = KVSTORAGE_TYPE_EXPIRE_LRU; } else { if (*error == NULL) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "invalid expire type: %*s", (int)text_len, text); + *error = g_error_new ( + xml_error_quark (), XML_EXTRA_ELEMENT, "invalid expire type: %*s", + (int)text_len, text); } kv_parser->state = KVSTORAGE_STATE_ERROR; } @@ -463,12 +519,12 @@ void kvstorage_xml_text (GMarkupParseContext *context, } /* Called on error, including one set by other -* methods in the vtable. The GError should not be freed. -*/ + * methods in the vtable. The GError should not be freed. + */ void -kvstorage_xml_error (GMarkupParseContext *context, - GError *error, - gpointer user_data) +kvstorage_xml_error (GMarkupParseContext *context, + GError *error, + gpointer user_data) { msg_err ("kvstorage xml parser error: %s", error->message); } @@ -479,9 +535,11 @@ kvstorage_xml_error (GMarkupParseContext *context, static void kvstorage_cleanup (gpointer ud) { - struct kvstorage_config_parser *kv_parser = ud; + struct kvstorage_config_parser *kv_parser = ud; - g_hash_table_insert (storages, &kv_parser->current_storage->id, kv_parser->current_storage); + g_hash_table_insert (storages, + &kv_parser->current_storage->id, + kv_parser->current_storage); kv_parser->state = KVSTORAGE_STATE_INIT; g_hash_table_foreach (storages, kvstorage_init_callback, NULL); kv_parser->current_storage = NULL; @@ -493,16 +551,22 @@ kvstorage_cleanup (gpointer ud) void init_kvstorage_config (void) { - GMarkupParser *parser; - struct kvstorage_config_parser *kv_parser; + GMarkupParser *parser; + struct kvstorage_config_parser *kv_parser; if (storages == NULL) { - storages = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, kvstorage_config_destroy); + storages = g_hash_table_new_full (g_int_hash, + g_int_equal, + NULL, + kvstorage_config_destroy); } else { /* Create new global table */ g_hash_table_destroy (storages); - storages = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, kvstorage_config_destroy); + storages = g_hash_table_new_full (g_int_hash, + g_int_equal, + NULL, + kvstorage_config_destroy); } /* Create and register subparser */ @@ -520,7 +584,7 @@ init_kvstorage_config (void) } /* Get configuration for kvstorage with specified ID */ -struct kvstorage_config* +struct kvstorage_config * get_kvstorage_config (gint id) { if (storages == NULL) { diff --git a/src/kvstorage_config.h b/src/kvstorage_config.h index 095ae3ab2..f94d934b3 100644 --- a/src/kvstorage_config.h +++ b/src/kvstorage_config.h @@ -93,7 +93,7 @@ struct kvstorage_config { void init_kvstorage_config (void); /* Get configuration for kvstorage with specified ID */ -struct kvstorage_config* get_kvstorage_config (gint id); +struct kvstorage_config * get_kvstorage_config (gint id); void destroy_kvstorage_config (void); diff --git a/src/kvstorage_file.c b/src/kvstorage_file.c index 2857e680b..a8550b77e 100644 --- a/src/kvstorage_file.c +++ b/src/kvstorage_file.c @@ -40,14 +40,14 @@ struct file_op { /* Main file structure */ struct rspamd_file_backend { - backend_init init_func; /*< this callback is called on kv storage initialization */ - backend_insert insert_func; /*< this callback is called when element is inserted */ - backend_replace replace_func; /*< this callback is called when element is replaced */ - backend_lookup lookup_func; /*< this callback is used for lookup of element */ - backend_delete delete_func; /*< this callback is called when an element is deleted */ - backend_sync sync_func; /*< this callback is called when backend need to be synced */ - backend_incref incref_func; /*< this callback is called when element must be ref'd */ - backend_destroy destroy_func; /*< this callback is used for destroying all elements inside backend */ + backend_init init_func; /*< this callback is called on kv storage initialization */ + backend_insert insert_func; /*< this callback is called when element is inserted */ + backend_replace replace_func; /*< this callback is called when element is replaced */ + backend_lookup lookup_func; /*< this callback is used for lookup of element */ + backend_delete delete_func; /*< this callback is called when an element is deleted */ + backend_sync sync_func; /*< this callback is called when backend need to be synced */ + backend_incref incref_func; /*< this callback is called when element must be ref'd */ + backend_destroy destroy_func; /*< this callback is used for destroying all elements inside backend */ gchar *filename; gchar *dirname; guint dirlen; @@ -60,15 +60,21 @@ struct rspamd_file_backend { gboolean initialized; }; -static const gchar hexdigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; +static const gchar hexdigits[] = +{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', + 'f'}; /* Generate file name for operation */ static gboolean -get_file_name (struct rspamd_file_backend *db, gchar *key, guint keylen, gchar *filebuf, guint buflen) +get_file_name (struct rspamd_file_backend *db, + gchar *key, + guint keylen, + gchar *filebuf, + guint buflen) { - gchar *p = filebuf, *end = filebuf + buflen, - *k = key, t; - guint i; + gchar *p = filebuf, *end = filebuf + buflen, + *k = key, t; + guint i; /* First copy backend dirname to file buf */ if (buflen <= db->dirlen) { @@ -77,7 +83,7 @@ get_file_name (struct rspamd_file_backend *db, gchar *key, guint keylen, gchar * memcpy (p, db->dirname, db->dirlen); p += db->dirlen; *p++ = G_DIR_SEPARATOR; - for (i = 0; i < MIN (keylen, db->levels); i ++) { + for (i = 0; i < MIN (keylen, db->levels); i++) { if (p == end) { /* Filebuf is not large enough */ return FALSE; @@ -85,7 +91,7 @@ get_file_name (struct rspamd_file_backend *db, gchar *key, guint keylen, gchar * t = *k; *p++ = hexdigits[(t & 0xf) ^ ((t & 0xf0) >> 4)]; *p++ = G_DIR_SEPARATOR; - k ++; + k++; } /* Now we have directory, append base64 encoded filename */ k = key; @@ -99,7 +105,7 @@ get_file_name (struct rspamd_file_backend *db, gchar *key, guint keylen, gchar * t = *k; *p++ = hexdigits[(t >> 4) & 0xf]; *p++ = hexdigits[t & 0xf]; - k ++; + k++; } *p = '\0'; @@ -110,7 +116,7 @@ get_file_name (struct rspamd_file_backend *db, gchar *key, guint keylen, gchar * static guint32 file_get_ref (gint fd) { - guint32 target; + guint32 target; if (read (fd, &target, sizeof (guint32)) != sizeof (guint32)) { return 0; @@ -136,12 +142,12 @@ file_set_ref (gint fd, guint32 ref) static gint file_open_fd (const gchar *path, gsize *len, gint flags) { - gint fd; - struct stat st; + gint fd; + struct stat st; if ((flags & O_CREAT) != 0) { /* Open file */ - if ((fd = open (path, flags, S_IRUSR|S_IWUSR|S_IRGRP)) != -1) { + if ((fd = open (path, flags, S_IRUSR | S_IWUSR | S_IRGRP)) != -1) { rspamd_fallocate (fd, 0, *len); #ifdef HAVE_FADVISE posix_fadvise (fd, 0, *len, POSIX_FADV_SEQUENTIAL); @@ -170,16 +176,19 @@ file_open_fd (const gchar *path, gsize *len, gint flags) /* Process single file operation */ static gboolean -file_process_single_op (struct rspamd_file_backend *db, struct file_op *op, gint *pfd) +file_process_single_op (struct rspamd_file_backend *db, + struct file_op *op, + gint *pfd) { - gchar filebuf[PATH_MAX]; - gint fd; - gsize len; - struct iovec iov[2]; - guint32 ref; + gchar filebuf[PATH_MAX]; + gint fd; + gsize len; + struct iovec iov[2]; + guint32 ref; /* Get filename */ - if (!get_file_name (db, ELT_KEY (op->elt), op->elt->keylen, filebuf, sizeof (filebuf))) { + if (!get_file_name (db, ELT_KEY (op->elt), op->elt->keylen, filebuf, + sizeof (filebuf))) { return FALSE; } @@ -205,7 +214,7 @@ file_process_single_op (struct rspamd_file_backend *db, struct file_op *op, gint else { /* Decrease ref */ lseek (fd, 0, SEEK_SET); - if (! file_set_ref (fd, --ref)) { + if (!file_set_ref (fd, --ref)) { *pfd = fd; return FALSE; } @@ -217,7 +226,8 @@ file_process_single_op (struct rspamd_file_backend *db, struct file_op *op, gint } } else { - if ((fd = file_open_fd (filebuf, &len, O_CREAT|O_WRONLY|O_TRUNC)) == -1) { + if ((fd = + file_open_fd (filebuf, &len, O_CREAT | O_WRONLY | O_TRUNC)) == -1) { *pfd = -1; return FALSE; } @@ -249,9 +259,9 @@ file_process_single_op (struct rspamd_file_backend *db, struct file_op *op, gint static void file_sync_fds (gint *fds, gint len, gboolean do_fsync) { - gint i, fd; + gint i, fd; - for (i = 0; i < len; i ++) { + for (i = 0; i < len; i++) { fd = fds[i]; if (fd != -1) { if (do_fsync) { @@ -270,10 +280,10 @@ file_sync_fds (gint *fds, gint len, gboolean do_fsync) static gboolean file_process_queue (struct rspamd_kv_backend *backend) { - struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; - struct file_op *op; - GList *cur; - gint *fds, i = 0, len; + struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; + struct file_op *op; + GList *cur; + gint *fds, i = 0, len; len = g_queue_get_length (db->ops_queue); if (len == 0) { @@ -285,12 +295,12 @@ file_process_queue (struct rspamd_kv_backend *backend) cur = db->ops_queue->head; while (cur) { op = cur->data; - if (! file_process_single_op (db, op, &fds[i])) { + if (!file_process_single_op (db, op, &fds[i])) { file_sync_fds (fds, i, db->do_fsync); g_slice_free1 (len * sizeof (gint), fds); return FALSE; } - i ++; + i++; cur = g_list_next (cur); } @@ -302,8 +312,9 @@ file_process_queue (struct rspamd_kv_backend *backend) cur = db->ops_queue->head; while (cur) { op = cur->data; - if (op->op == FILE_OP_DELETE || ((op->elt->flags & KV_ELT_NEED_FREE) != 0 && - (op->elt->flags & KV_ELT_NEED_INSERT) == 0)) { + if (op->op == FILE_OP_DELETE || + ((op->elt->flags & KV_ELT_NEED_FREE) != 0 && + (op->elt->flags & KV_ELT_NEED_INSERT) == 0)) { /* Also clean memory */ g_slice_free1 (ELT_SIZE (op->elt), op->elt); } @@ -326,16 +337,17 @@ file_process_queue (struct rspamd_kv_backend *backend) static gboolean rspamd_recursive_mkdir (guint levels) { - guint i; - gchar nbuf[5]; + guint i; + gchar nbuf[5]; /* Create directories for backend */ if (levels > 0) { /* Create 16 directories */ - for (i = 0; i < 16; i ++) { + for (i = 0; i < 16; i++) { rspamd_snprintf (nbuf, sizeof (nbuf), "./%c", hexdigits[i]); if (mkdir (nbuf, 0755) != 0 && errno != EEXIST) { - msg_info ("cannot create directory %s: %s", nbuf, strerror (errno)); + msg_info ("cannot create directory %s: %s", nbuf, + strerror (errno)); return FALSE; } else if (levels > 1) { @@ -343,7 +355,7 @@ rspamd_recursive_mkdir (guint levels) msg_err ("chdir to %s failed: %s", nbuf, strerror (errno)); return FALSE; } - if (! rspamd_recursive_mkdir (levels - 1)) { + if (!rspamd_recursive_mkdir (levels - 1)) { return FALSE; } if (chdir ("../") == -1) { @@ -361,8 +373,8 @@ rspamd_recursive_mkdir (guint levels) static void rspamd_file_init (struct rspamd_kv_backend *backend) { - struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; - gchar pathbuf[PATH_MAX]; + struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; + gchar pathbuf[PATH_MAX]; /* Save current directory */ if (getcwd (pathbuf, sizeof (pathbuf) - 1) == NULL) { @@ -397,11 +409,14 @@ err: } static gboolean -rspamd_file_insert (struct rspamd_kv_backend *backend, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_file_insert (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; - struct file_op *op; - struct rspamd_kv_element search_elt; + struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; + struct file_op *op; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -412,13 +427,14 @@ rspamd_file_insert (struct rspamd_kv_backend *backend, gpointer key, guint keyle if ((op = g_hash_table_lookup (db->ops_hash, &search_elt)) != NULL) { /* We found another op with such key in this queue */ - if (op->op == FILE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != 0) { + if (op->op == FILE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != + 0) { /* Also clean memory */ g_hash_table_steal (db->ops_hash, &search_elt); g_slice_free1 (ELT_SIZE (op->elt), op->elt); } op->op = FILE_OP_INSERT; - op->ref ++; + op->ref++; op->elt = elt; elt->flags |= KV_ELT_DIRTY; g_hash_table_insert (db->ops_hash, elt, op); @@ -434,7 +450,8 @@ rspamd_file_insert (struct rspamd_kv_backend *backend, gpointer key, guint keyle g_hash_table_insert (db->ops_hash, elt, op); } - if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= db->sync_ops) { + if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= + db->sync_ops) { return file_process_queue (backend); } @@ -442,11 +459,14 @@ rspamd_file_insert (struct rspamd_kv_backend *backend, gpointer key, guint keyle } static gboolean -rspamd_file_replace (struct rspamd_kv_backend *backend, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_file_replace (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; - struct file_op *op; - struct rspamd_kv_element search_elt; + struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; + struct file_op *op; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -456,7 +476,8 @@ rspamd_file_replace (struct rspamd_kv_backend *backend, gpointer key, guint keyl } if ((op = g_hash_table_lookup (db->ops_hash, &search_elt)) != NULL) { /* We found another op with such key in this queue */ - if (op->op == FILE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != 0) { + if (op->op == FILE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != + 0) { /* Also clean memory */ g_hash_table_steal (db->ops_hash, &search_elt); g_slice_free1 (ELT_SIZE (op->elt), op->elt); @@ -477,23 +498,26 @@ rspamd_file_replace (struct rspamd_kv_backend *backend, gpointer key, guint keyl g_hash_table_insert (db->ops_hash, elt, op); } - if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= db->sync_ops) { + if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= + db->sync_ops) { return file_process_queue (backend); } return TRUE; } -static struct rspamd_kv_element* -rspamd_file_lookup (struct rspamd_kv_backend *backend, gpointer key, guint keylen) +static struct rspamd_kv_element * +rspamd_file_lookup (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen) { - struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; - struct file_op *op; - struct rspamd_kv_element *elt = NULL; - gchar filebuf[PATH_MAX]; - gint fd; - struct rspamd_kv_element search_elt; - gsize len; + struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; + struct file_op *op; + struct rspamd_kv_element *elt = NULL; + gchar filebuf[PATH_MAX]; + gint fd; + struct rspamd_kv_element search_elt; + gsize len; search_elt.keylen = keylen; search_elt.p = key; @@ -533,21 +557,23 @@ rspamd_file_lookup (struct rspamd_kv_backend *backend, gpointer key, guint keyle close (fd); - elt->flags &= ~(KV_ELT_DIRTY|KV_ELT_NEED_FREE); + elt->flags &= ~(KV_ELT_DIRTY | KV_ELT_NEED_FREE); return elt; } static void -rspamd_file_delete (struct rspamd_kv_backend *backend, gpointer key, guint keylen) +rspamd_file_delete (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen) { - struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; - gchar filebuf[PATH_MAX]; - struct rspamd_kv_element search_elt; - struct file_op *op; - gsize len; - gint fd; - guint32 ref; + struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; + gchar filebuf[PATH_MAX]; + struct rspamd_kv_element search_elt; + struct file_op *op; + gsize len; + gint fd; + guint32 ref; if (!db->initialized) { return; @@ -559,7 +585,7 @@ rspamd_file_delete (struct rspamd_kv_backend *backend, gpointer key, guint keyle if ((op = g_hash_table_lookup (db->ops_hash, &search_elt)) != NULL) { op->op = FILE_OP_DELETE; if (op->ref > 0) { - op->ref --; + op->ref--; } return; } @@ -589,15 +615,17 @@ rspamd_file_delete (struct rspamd_kv_backend *backend, gpointer key, guint keyle } static gboolean -rspamd_file_incref (struct rspamd_kv_backend *backend, gpointer key, guint keylen) +rspamd_file_incref (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen) { - struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; - gchar filebuf[PATH_MAX]; - struct rspamd_kv_element search_elt; - struct file_op *op; - gsize len; - gint fd; - guint32 ref; + struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; + gchar filebuf[PATH_MAX]; + struct rspamd_kv_element search_elt; + struct file_op *op; + gsize len; + gint fd; + guint32 ref; if (!db->initialized) { return FALSE; @@ -610,7 +638,7 @@ rspamd_file_incref (struct rspamd_kv_backend *backend, gpointer key, guint keyle search_elt.p = key; /* First search in ops queue */ if ((op = g_hash_table_lookup (db->ops_hash, &search_elt)) != NULL) { - op->ref ++; + op->ref++; if (op->op == FILE_OP_DELETE) { op->op = FILE_OP_INSERT; } @@ -644,7 +672,7 @@ rspamd_file_incref (struct rspamd_kv_backend *backend, gpointer key, guint keyle static void rspamd_file_destroy (struct rspamd_kv_backend *backend) { - struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; + struct rspamd_file_backend *db = (struct rspamd_file_backend *)backend; if (db->initialized) { file_process_queue (backend); @@ -661,11 +689,15 @@ rspamd_file_destroy (struct rspamd_kv_backend *backend) /* Create new file backend */ struct rspamd_kv_backend * -rspamd_kv_file_new (const gchar *filename, guint sync_ops, guint levels, gboolean do_fsync, gboolean do_ref) +rspamd_kv_file_new (const gchar *filename, + guint sync_ops, + guint levels, + gboolean do_fsync, + gboolean do_ref) { - struct rspamd_file_backend *new; - struct stat st; - gchar *dirname; + struct rspamd_file_backend *new; + struct stat st; + gchar *dirname; if (filename == NULL) { return NULL; diff --git a/src/kvstorage_file.h b/src/kvstorage_file.h index 2b4c0f33d..4e97f467b 100644 --- a/src/kvstorage_file.h +++ b/src/kvstorage_file.h @@ -29,8 +29,11 @@ #include "kvstorage.h" /* Create new file backend */ -struct rspamd_kv_backend* rspamd_kv_file_new (const gchar *filename, guint sync_ops, - guint levels, gboolean do_fsync, gboolean do_ref); +struct rspamd_kv_backend * rspamd_kv_file_new (const gchar *filename, + guint sync_ops, + guint levels, + gboolean do_fsync, + gboolean do_ref); #endif /* KVSTORAGE_FILE_H_ */ diff --git a/src/kvstorage_server.c b/src/kvstorage_server.c index 75ada2c77..ecf86f7b3 100644 --- a/src/kvstorage_server.c +++ b/src/kvstorage_server.c @@ -45,22 +45,31 @@ static sig_atomic_t do_reopen_log = 0; static sig_atomic_t soft_wanna_die = 0; /* Logging functions */ -#define thr_err(...) do { \ - g_mutex_lock (thr->log_mtx); \ - rspamd_common_log_function(rspamd_main->logger, G_LOG_LEVEL_CRITICAL, __FUNCTION__, __VA_ARGS__); \ - g_mutex_unlock (thr->log_mtx); \ +#define thr_err(...) do { \ + g_mutex_lock (thr->log_mtx); \ + rspamd_common_log_function (rspamd_main->logger, \ + G_LOG_LEVEL_CRITICAL, \ + __FUNCTION__, \ + __VA_ARGS__); \ + g_mutex_unlock (thr->log_mtx); \ } while (0) -#define thr_warn(...) do { \ - g_mutex_lock (thr->log_mtx); \ - rspamd_common_log_function(rspamd_main->logger, G_LOG_LEVEL_WARNING, __FUNCTION__, __VA_ARGS__); \ - g_mutex_unlock (thr->log_mtx); \ +#define thr_warn(...) do { \ + g_mutex_lock (thr->log_mtx); \ + rspamd_common_log_function (rspamd_main->logger, \ + G_LOG_LEVEL_WARNING, \ + __FUNCTION__, \ + __VA_ARGS__); \ + g_mutex_unlock (thr->log_mtx); \ } while (0) -#define thr_info(...) do { \ - g_mutex_lock (thr->log_mtx); \ - rspamd_common_log_function(rspamd_main->logger, G_LOG_LEVEL_INFO, __FUNCTION__, __VA_ARGS__); \ - g_mutex_unlock (thr->log_mtx); \ +#define thr_info(...) do { \ + g_mutex_lock (thr->log_mtx); \ + rspamd_common_log_function (rspamd_main->logger, \ + G_LOG_LEVEL_INFO, \ + __FUNCTION__, \ + __VA_ARGS__); \ + g_mutex_unlock (thr->log_mtx); \ } while (0) /* Init functions */ @@ -68,14 +77,14 @@ gpointer init_keystorage (void); void start_keystorage (struct rspamd_worker *worker); worker_t keystorage_worker = { - "keystorage", /* Name */ - init_keystorage, /* Init function */ - start_keystorage, /* Start function */ - TRUE, /* Has socket */ - FALSE, /* Non unique */ - TRUE, /* Non threaded */ - FALSE, /* Non killable */ - SOCK_STREAM /* TCP socket */ + "keystorage", /* Name */ + init_keystorage, /* Init function */ + start_keystorage, /* Start function */ + TRUE, /* Has socket */ + FALSE, /* Non unique */ + TRUE, /* Non threaded */ + FALSE, /* Non killable */ + SOCK_STREAM /* TCP socket */ }; #ifndef HAVE_SA_SIGINFO @@ -103,8 +112,8 @@ sig_handler (gint signo, siginfo_t *info, void *unused) gpointer init_keystorage (void) { - struct kvstorage_worker_ctx *ctx; - GQuark type; + struct kvstorage_worker_ctx *ctx; + GQuark type; type = g_quark_try_string ("keystorage"); ctx = g_malloc0 (sizeof (struct kvstorage_worker_ctx)); @@ -114,9 +123,9 @@ init_keystorage (void) ctx->timeout_raw = 300000; register_worker_opt (type, "timeout", xml_handle_seconds, ctx, - G_STRUCT_OFFSET (struct kvstorage_worker_ctx, timeout_raw)); + G_STRUCT_OFFSET (struct kvstorage_worker_ctx, timeout_raw)); register_worker_opt (type, "redis", xml_handle_boolean, ctx, - G_STRUCT_OFFSET (struct kvstorage_worker_ctx, is_redis)); + G_STRUCT_OFFSET (struct kvstorage_worker_ctx, is_redis)); return ctx; } @@ -124,7 +133,7 @@ init_keystorage (void) static gboolean config_kvstorage_worker (struct rspamd_worker *worker) { - struct kvstorage_worker_ctx *ctx = worker->ctx; + struct kvstorage_worker_ctx *ctx = worker->ctx; /* Init timeval */ msec_to_tv (ctx->timeout_raw, &ctx->io_timeout); @@ -153,18 +162,18 @@ parse_kvstorage_command (struct kvstorage_session *session, gchar *c, guint len) if (len == 3) { /* Set or get command */ if ((c[0] == 'g' || c[0] == 'G') && - (c[1] == 'e' || c[1] == 'E') && - (c[2] == 't' || c[2] == 'T')) { + (c[1] == 'e' || c[1] == 'E') && + (c[2] == 't' || c[2] == 'T')) { session->command = KVSTORAGE_CMD_GET; } else if ((c[0] == 's' || c[0] == 'S') && - (c[1] == 'e' || c[1] == 'E') && - (c[2] == 't' || c[2] == 'T')) { + (c[1] == 'e' || c[1] == 'E') && + (c[2] == 't' || c[2] == 'T')) { session->command = KVSTORAGE_CMD_SET; } else if ((c[0] == 'd' || c[0] == 'D') && - (c[1] == 'e' || c[1] == 'E') && - (c[2] == 'l' || c[2] == 'L')) { + (c[1] == 'e' || c[1] == 'E') && + (c[2] == 'l' || c[2] == 'L')) { session->command = KVSTORAGE_CMD_DELETE; } else { @@ -174,51 +183,52 @@ parse_kvstorage_command (struct kvstorage_session *session, gchar *c, guint len) } else if (len == 4) { if ((c[0] == 'i' || c[0] == 'I') && - (c[1] == 'n' || c[1] == 'N') && - (c[2] == 'c' || c[2] == 'C') && - (c[3] == 'r' || c[3] == 'R')) { + (c[1] == 'n' || c[1] == 'N') && + (c[2] == 'c' || c[2] == 'C') && + (c[3] == 'r' || c[3] == 'R')) { session->command = KVSTORAGE_CMD_INCR; session->arg_data.value = 1; } else if ((c[0] == 'd' || c[0] == 'D') && - (c[1] == 'e' || c[1] == 'E') && - (c[2] == 'c' || c[2] == 'C') && - (c[3] == 'r' || c[3] == 'R')) { + (c[1] == 'e' || c[1] == 'E') && + (c[2] == 'c' || c[2] == 'C') && + (c[3] == 'r' || c[3] == 'R')) { session->command = KVSTORAGE_CMD_DECR; session->arg_data.value = -1; } else if (g_ascii_strncasecmp (c, "quit", 4) == 0) { session->command = KVSTORAGE_CMD_QUIT; } - else if (g_ascii_strncasecmp (c, "sync", 4) == 0 || g_ascii_strncasecmp (c, "save", 4) == 0) { + else if (g_ascii_strncasecmp (c, "sync", + 4) == 0 || g_ascii_strncasecmp (c, "save", 4) == 0) { session->command = KVSTORAGE_CMD_SYNC; } } else if (len == 6) { if ((c[0] == 'i' || c[0] == 'I') && - (c[1] == 'n' || c[1] == 'N') && - (c[2] == 'c' || c[2] == 'C') && - (c[3] == 'r' || c[3] == 'R') && - (c[4] == 'b' || c[4] == 'B') && - (c[5] == 'y' || c[5] == 'Y')) { + (c[1] == 'n' || c[1] == 'N') && + (c[2] == 'c' || c[2] == 'C') && + (c[3] == 'r' || c[3] == 'R') && + (c[4] == 'b' || c[4] == 'B') && + (c[5] == 'y' || c[5] == 'Y')) { session->command = KVSTORAGE_CMD_INCR; session->arg_data.value = 1; } else if ((c[0] == 'd' || c[0] == 'D') && - (c[1] == 'e' || c[1] == 'E') && - (c[2] == 'c' || c[2] == 'C') && - (c[3] == 'r' || c[3] == 'R') && - (c[4] == 'b' || c[4] == 'B') && - (c[5] == 'y' || c[5] == 'Y')) { + (c[1] == 'e' || c[1] == 'E') && + (c[2] == 'c' || c[2] == 'C') && + (c[3] == 'r' || c[3] == 'R') && + (c[4] == 'b' || c[4] == 'B') && + (c[5] == 'y' || c[5] == 'Y')) { session->command = KVSTORAGE_CMD_DECR; session->arg_data.value = -1; } else if ((c[0] == 'd' || c[0] == 'D') && - (c[1] == 'e' || c[1] == 'E') && - (c[2] == 'l' || c[2] == 'L') && - (c[3] == 'e' || c[3] == 'E') && - (c[4] == 't' || c[4] == 'T') && - (c[5] == 'e' || c[5] == 'E')) { + (c[1] == 'e' || c[1] == 'E') && + (c[2] == 'l' || c[2] == 'L') && + (c[3] == 'e' || c[3] == 'E') && + (c[4] == 't' || c[4] == 'T') && + (c[5] == 'e' || c[5] == 'E')) { session->command = KVSTORAGE_CMD_DELETE; } else if (g_ascii_strncasecmp (c, "select", 6) == 0) { @@ -238,9 +248,9 @@ parse_kvstorage_command (struct kvstorage_session *session, gchar *c, guint len) static gboolean parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) { - gchar *p, *c, *end; - gint state = 0, next_state = 0; - gboolean is_redis; + gchar *p, *c, *end; + gint state = 0, next_state = 0; + gboolean is_redis; p = in->begin; end = in->begin + in->len; @@ -253,7 +263,7 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) case 0: /* At this state we try to read identifier of storage */ if (g_ascii_isdigit (*p)) { - p ++; + p++; } else { if (g_ascii_isspace (*p) && p != c) { @@ -284,7 +294,7 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) case 1: /* At this state we parse command */ if (g_ascii_isalpha (*p) && p != end) { - p ++; + p++; } else { if (parse_kvstorage_command (session, c, p - c)) { @@ -315,20 +325,21 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) case 2: /* Read and store key */ if (!g_ascii_isspace (*p) && end != p) { - p ++; + p++; } else { if (p == c) { return FALSE; } else { - session->key = rspamd_mempool_alloc (session->pool, p - c + 1); + session->key = rspamd_mempool_alloc (session->pool, + p - c + 1); rspamd_strlcpy (session->key, c, p - c + 1); session->keylen = p - c; /* Now we must select next state based on command */ if (session->command == KVSTORAGE_CMD_SET || - session->command == KVSTORAGE_CMD_INCR || - session->command == KVSTORAGE_CMD_DECR) { + session->command == KVSTORAGE_CMD_INCR || + session->command == KVSTORAGE_CMD_DECR) { /* Read flags */ state = 99; if (is_redis) { @@ -355,7 +366,7 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) case 3: /* Read flags */ if (g_ascii_isdigit (*p)) { - p ++; + p++; } else { if (g_ascii_isspace (*p)) { @@ -377,7 +388,7 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) case 4: /* Read exptime */ if (g_ascii_isdigit (*p)) { - p ++; + p++; } else { if (g_ascii_isspace (*p)) { @@ -393,7 +404,7 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) case 5: /* Read size or incr/decr values */ if (g_ascii_isdigit (*p)) { - p ++; + p++; } else { if (g_ascii_isspace (*p) || p >= end - 1) { @@ -404,7 +415,8 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) if (p != c) { session->arg_data.value = strtoul (c, NULL, 10); if (session->command == KVSTORAGE_CMD_DECR) { - session->arg_data.value = -session->arg_data.value; + session->arg_data.value = + -session->arg_data.value; } } else if (session->command == KVSTORAGE_CMD_INCR) { @@ -424,7 +436,7 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) case 6: /* Read index of storage */ if (g_ascii_isdigit (*p)) { - p ++; + p++; } else { if (g_ascii_isspace (*p) || end == p) { @@ -439,7 +451,7 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) case 7: /* Read arguments count */ if (g_ascii_isdigit (*p)) { - p ++; + p++; } else { if (g_ascii_isspace (*p) || end == p) { @@ -457,7 +469,7 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) case 99: /* Skip spaces state */ if (g_ascii_isspace (*p)) { - p ++; + p++; } else { c = p; @@ -478,33 +490,44 @@ parse_kvstorage_line (struct kvstorage_session *session, f_str_t *in) static gboolean kvstorage_process_command (struct kvstorage_session *session, gboolean is_redis) { - gint r; - gchar outbuf[BUFSIZ], intbuf[sizeof ("9223372036854775807")]; - gboolean res; - struct rspamd_kv_element *elt; - guint eltlen; - glong longval; + gint r; + gchar outbuf[BUFSIZ], intbuf[sizeof ("9223372036854775807")]; + gboolean res; + struct rspamd_kv_element *elt; + guint eltlen; + glong longval; if (session->command == KVSTORAGE_CMD_SET) { session->state = KVSTORAGE_STATE_READ_DATA; - rspamd_set_dispatcher_policy (session->dispather, BUFFER_CHARACTER, session->arg_data.length); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_CHARACTER, + session->arg_data.length); } else if (session->command == KVSTORAGE_CMD_GET) { - elt = rspamd_kv_storage_lookup (session->cf->storage, session->key, session->keylen, session->now); + elt = rspamd_kv_storage_lookup (session->cf->storage, + session->key, + session->keylen, + session->now); if (elt == NULL) { RW_R_UNLOCK (&session->cf->storage->rwlock); if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, ERROR_NOT_FOUND, - sizeof (ERROR_NOT_FOUND) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + ERROR_NOT_FOUND, + sizeof (ERROR_NOT_FOUND) - 1, + FALSE, + TRUE); } else { return rspamd_dispatcher_write (session->dispather, "$-1" CRLF, - sizeof ("$-1" CRLF) - 1, FALSE, TRUE); + sizeof ("$-1" CRLF) - 1, FALSE, TRUE); } } else { if (elt->flags & KV_ELT_INTEGER) { - eltlen = rspamd_snprintf (intbuf, sizeof (intbuf), "%l", ELT_LONG (elt)); + eltlen = rspamd_snprintf (intbuf, + sizeof (intbuf), + "%l", + ELT_LONG (elt)); } else { @@ -512,34 +535,43 @@ kvstorage_process_command (struct kvstorage_session *session, gboolean is_redis) } if (!is_redis) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "VALUE %s %ud %ud" CRLF, - ELT_KEY (elt), elt->flags, eltlen); + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "VALUE %s %ud %ud" CRLF, + ELT_KEY (elt), + elt->flags, + eltlen); } else { r = rspamd_snprintf (outbuf, sizeof (outbuf), "$%ud" CRLF, eltlen); } if (!rspamd_dispatcher_write (session->dispather, outbuf, - r, TRUE, FALSE)) { + r, TRUE, FALSE)) { RW_R_UNLOCK (&session->cf->storage->rwlock); return FALSE; } if (elt->flags & KV_ELT_INTEGER) { - if (!rspamd_dispatcher_write (session->dispather, intbuf, eltlen, TRUE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispather, intbuf, + eltlen, TRUE, TRUE)) { RW_R_UNLOCK (&session->cf->storage->rwlock); return FALSE; } } else { - if (!rspamd_dispatcher_write (session->dispather, ELT_DATA(elt), eltlen, TRUE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispather, + ELT_DATA (elt), eltlen, TRUE, TRUE)) { RW_R_UNLOCK (&session->cf->storage->rwlock); return FALSE; } } session->elt = elt; if (!is_redis) { - res = rspamd_dispatcher_write (session->dispather, CRLF "END" CRLF, - sizeof (CRLF "END" CRLF) - 1, FALSE, TRUE); + res = rspamd_dispatcher_write (session->dispather, + CRLF "END" CRLF, + sizeof (CRLF "END" CRLF) - 1, + FALSE, + TRUE); } else { res = rspamd_dispatcher_write (session->dispather, CRLF, @@ -553,42 +585,58 @@ kvstorage_process_command (struct kvstorage_session *session, gboolean is_redis) } } else if (session->command == KVSTORAGE_CMD_DELETE) { - elt = rspamd_kv_storage_delete (session->cf->storage, session->key, session->keylen); + elt = rspamd_kv_storage_delete (session->cf->storage, + session->key, + session->keylen); if (elt != NULL) { if ((elt->flags & KV_ELT_DIRTY) == 0) { /* Free memory if backend has deleted this element */ g_slice_free1 (ELT_SIZE (elt), elt); } if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, "DELETED" CRLF, - sizeof ("DELETED" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "DELETED" CRLF, + sizeof ("DELETED" CRLF) - 1, + FALSE, + TRUE); } else { return rspamd_dispatcher_write (session->dispather, ":1" CRLF, - sizeof (":1" CRLF) - 1, FALSE, TRUE); + sizeof (":1" CRLF) - 1, FALSE, TRUE); } } else { if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, ERROR_NOT_FOUND, - sizeof (ERROR_NOT_FOUND) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + ERROR_NOT_FOUND, + sizeof (ERROR_NOT_FOUND) - 1, + FALSE, + TRUE); } else { return rspamd_dispatcher_write (session->dispather, ":0" CRLF, - sizeof (":0" CRLF) - 1, FALSE, TRUE); + sizeof (":0" CRLF) - 1, FALSE, TRUE); } } } - else if (session->command == KVSTORAGE_CMD_INCR || session->command == KVSTORAGE_CMD_DECR) { + else if (session->command == KVSTORAGE_CMD_INCR || session->command == + KVSTORAGE_CMD_DECR) { longval = session->arg_data.value; - if (!rspamd_kv_storage_increment (session->cf->storage, session->key, session->keylen, &longval)) { + if (!rspamd_kv_storage_increment (session->cf->storage, session->key, + session->keylen, &longval)) { if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, ERROR_NOT_FOUND, - sizeof (ERROR_NOT_FOUND) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + ERROR_NOT_FOUND, + sizeof (ERROR_NOT_FOUND) - 1, + FALSE, + TRUE); } else { - return rspamd_dispatcher_write (session->dispather, "-ERR not found" CRLF, - sizeof ("-ERR not found" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "-ERR not found" CRLF, + sizeof ("-ERR not found" CRLF) - 1, + FALSE, + TRUE); } } else { @@ -601,41 +649,61 @@ kvstorage_process_command (struct kvstorage_session *session, gboolean is_redis) longval); } if (!rspamd_dispatcher_write (session->dispather, outbuf, - r, FALSE, FALSE)) { + r, FALSE, FALSE)) { return FALSE; } } } else if (session->command == KVSTORAGE_CMD_SYNC) { - if (session->cf->storage->backend == NULL || session->cf->storage->backend->sync_func == NULL) { + if (session->cf->storage->backend == NULL || + session->cf->storage->backend->sync_func == NULL) { if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, ERROR_COMMON, - sizeof (ERROR_COMMON) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + ERROR_COMMON, + sizeof (ERROR_COMMON) - 1, + FALSE, + TRUE); } else { - return rspamd_dispatcher_write (session->dispather, "-ERR unsupported" CRLF, - sizeof ("-ERR unsupported" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "-ERR unsupported" CRLF, + sizeof ("-ERR unsupported" CRLF) - 1, + FALSE, + TRUE); } } else { - if (session->cf->storage->backend->sync_func (session->cf->storage->backend)) { + if (session->cf->storage->backend->sync_func (session->cf->storage-> + backend)) { if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, "SYNCED" CRLF, - sizeof ("SYNCED" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "SYNCED" CRLF, + sizeof ("SYNCED" CRLF) - 1, + FALSE, + TRUE); } else { - return rspamd_dispatcher_write (session->dispather, "+OK" CRLF, - sizeof ("+OK" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "+OK" CRLF, + sizeof ("+OK" CRLF) - 1, + FALSE, + TRUE); } } else { if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, "NOT_SYNCED" CRLF, - sizeof ("NOT_SYNCED" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "NOT_SYNCED" CRLF, + sizeof ("NOT_SYNCED" CRLF) - 1, + FALSE, + TRUE); } else { - return rspamd_dispatcher_write (session->dispather, "-ERR not synced" CRLF, - sizeof ("-ERR not synced" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "-ERR not synced" CRLF, + sizeof ("-ERR not synced" CRLF) - 1, + FALSE, + TRUE); } } } @@ -643,11 +711,11 @@ kvstorage_process_command (struct kvstorage_session *session, gboolean is_redis) else if (session->command == KVSTORAGE_CMD_SELECT) { if (!is_redis) { return rspamd_dispatcher_write (session->dispather, "SELECTED" CRLF, - sizeof ("SELECTED" CRLF) - 1, FALSE, TRUE); + sizeof ("SELECTED" CRLF) - 1, FALSE, TRUE); } else { return rspamd_dispatcher_write (session->dispather, "+OK" CRLF, - sizeof ("+OK" CRLF) - 1, FALSE, TRUE); + sizeof ("+OK" CRLF) - 1, FALSE, TRUE); } } else if (session->command == KVSTORAGE_CMD_QUIT) { @@ -662,8 +730,8 @@ kvstorage_process_command (struct kvstorage_session *session, gboolean is_redis) static gboolean kvstorage_read_arglen (f_str_t *in, guint *len) { - gchar *p = in->begin, *end = in->begin + in->len, *c; - gint state = 0; + gchar *p = in->begin, *end = in->begin + in->len, *c; + gint state = 0; c = p; while (p < end) { @@ -673,14 +741,14 @@ kvstorage_read_arglen (f_str_t *in, guint *len) return FALSE; } else { - p ++; + p++; c = p; state = 1; } break; case 1: if (g_ascii_isdigit (*p) && p != end - 1) { - p ++; + p++; } else { if (p != end - 1) { @@ -731,12 +799,12 @@ kvstorage_check_argnum (struct kvstorage_session *session) static gboolean kvstorage_read_socket (f_str_t * in, void *arg) { - struct kvstorage_session *session = (struct kvstorage_session *) arg; - struct kvstorage_worker_thread *thr; - gint r; - guint arglen = 0; - gchar outbuf[BUFSIZ]; - gboolean is_redis; + struct kvstorage_session *session = (struct kvstorage_session *) arg; + struct kvstorage_worker_thread *thr; + gint r; + guint arglen = 0; + gchar outbuf[BUFSIZ]; + gboolean is_redis; if (in->len == 0) { /* Skip empty commands */ @@ -749,16 +817,22 @@ kvstorage_read_socket (f_str_t * in, void *arg) case KVSTORAGE_STATE_READ_CMD: /* Update timestamp */ session->now = time (NULL); - if (! parse_kvstorage_line (session, in)) { + if (!parse_kvstorage_line (session, in)) { thr_info ("%ud: unknown command: %V", thr->id, in); if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, ERROR_UNKNOWN_COMMAND, - sizeof (ERROR_UNKNOWN_COMMAND) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + ERROR_UNKNOWN_COMMAND, + sizeof (ERROR_UNKNOWN_COMMAND) - 1, + FALSE, + TRUE); } else { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "-ERR unknown command '%V'" CRLF, in); + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "-ERR unknown command '%V'" CRLF, + in); return rspamd_dispatcher_write (session->dispather, outbuf, - r, FALSE, TRUE); + r, FALSE, TRUE); } } else { @@ -766,12 +840,18 @@ kvstorage_read_socket (f_str_t * in, void *arg) if (session->cf == NULL) { thr_info ("%ud: bad keystorage: %ud", thr->id, session->id); if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, ERROR_INVALID_KEYSTORAGE, - sizeof (ERROR_INVALID_KEYSTORAGE) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + ERROR_INVALID_KEYSTORAGE, + sizeof (ERROR_INVALID_KEYSTORAGE) - 1, + FALSE, + TRUE); } else { - return rspamd_dispatcher_write (session->dispather, "-ERR unknown keystorage" CRLF, - sizeof ("-ERR unknown keystorage" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "-ERR unknown keystorage" CRLF, + sizeof ("-ERR unknown keystorage" CRLF) - 1, + FALSE, + TRUE); } } if (session->state != KVSTORAGE_STATE_READ_ARGLEN) { @@ -780,44 +860,59 @@ kvstorage_read_socket (f_str_t * in, void *arg) } break; case KVSTORAGE_STATE_READ_ARGLEN: - if (! kvstorage_read_arglen (in, &arglen)) { + if (!kvstorage_read_arglen (in, &arglen)) { session->state = KVSTORAGE_STATE_READ_CMD; - r = rspamd_snprintf (outbuf, sizeof (outbuf), "-ERR unknown arglen '%V'" CRLF, in); + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "-ERR unknown arglen '%V'" CRLF, + in); return rspamd_dispatcher_write (session->dispather, outbuf, - r, FALSE, TRUE); + r, FALSE, TRUE); } else { session->state = KVSTORAGE_STATE_READ_ARG; - rspamd_set_dispatcher_policy (session->dispather, BUFFER_CHARACTER, arglen); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_CHARACTER, + arglen); } break; case KVSTORAGE_STATE_READ_ARG: if (session->argnum == 0) { /* Read command */ - if (! parse_kvstorage_command (session, in->begin, in->len)) { + if (!parse_kvstorage_command (session, in->begin, in->len)) { session->state = KVSTORAGE_STATE_READ_CMD; - r = rspamd_snprintf (outbuf, sizeof (outbuf), "-ERR unknown command '%V'" CRLF, in); + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "-ERR unknown command '%V'" CRLF, + in); return rspamd_dispatcher_write (session->dispather, outbuf, - r, FALSE, TRUE); + r, FALSE, TRUE); } else { - if (! kvstorage_check_argnum (session)) { + if (!kvstorage_check_argnum (session)) { session->state = KVSTORAGE_STATE_READ_CMD; - r = rspamd_snprintf (outbuf, sizeof (outbuf), "-ERR invalid argnum for command '%V': %ud" CRLF, - in, session->argc); + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "-ERR invalid argnum for command '%V': %ud" CRLF, + in, + session->argc); return rspamd_dispatcher_write (session->dispather, outbuf, - r, FALSE, TRUE); + r, FALSE, TRUE); } else { if (session->argnum == session->argc - 1) { session->state = KVSTORAGE_STATE_READ_CMD; - rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_LINE, + -1); return kvstorage_process_command (session, TRUE); } else { - session->argnum ++; + session->argnum++; session->state = KVSTORAGE_STATE_READ_ARGLEN; - rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_LINE, + -1); } } } @@ -829,21 +924,28 @@ kvstorage_read_socket (f_str_t * in, void *arg) session->keylen = in->len; if (session->argnum == session->argc - 1) { session->state = KVSTORAGE_STATE_READ_CMD; - rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_LINE, + -1); return kvstorage_process_command (session, TRUE); } else { - session->argnum ++; + session->argnum++; session->state = KVSTORAGE_STATE_READ_ARGLEN; - rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_LINE, + -1); } } else { /* Special case for select command */ session->state = KVSTORAGE_STATE_READ_CMD; - rspamd_strlcpy (outbuf, in->begin, MIN (sizeof (outbuf), in->len)); + rspamd_strlcpy (outbuf, in->begin, MIN (sizeof (outbuf), + in->len)); session->id = strtoul (outbuf, NULL, 10); - rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_LINE, + -1); return kvstorage_process_command (session, TRUE); } } @@ -851,25 +953,37 @@ kvstorage_read_socket (f_str_t * in, void *arg) /* We get datablock for set command */ if (session->command == KVSTORAGE_CMD_SET && session->argc == 3) { session->state = KVSTORAGE_STATE_READ_CMD; - rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); - if (rspamd_kv_storage_insert (session->cf->storage, session->key, session->keylen, - in->begin, in->len, - session->flags, session->expire)) { - return rspamd_dispatcher_write (session->dispather, "+OK" CRLF, - sizeof ("+OK" CRLF) - 1, FALSE, TRUE); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_LINE, + -1); + if (rspamd_kv_storage_insert (session->cf->storage, + session->key, session->keylen, + in->begin, in->len, + session->flags, session->expire)) { + return rspamd_dispatcher_write (session->dispather, + "+OK" CRLF, + sizeof ("+OK" CRLF) - 1, + FALSE, + TRUE); } else { - return rspamd_dispatcher_write (session->dispather, "-ERR not stored" CRLF, - sizeof ("-ERR not stored" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "-ERR not stored" CRLF, + sizeof ("-ERR not stored" CRLF) - 1, + FALSE, + TRUE); } } - else if (session->command == KVSTORAGE_CMD_SET && session->argc == 4) { + else if (session->command == KVSTORAGE_CMD_SET && session->argc == + 4) { /* It is expire argument */ session->state = KVSTORAGE_STATE_READ_CMD; rspamd_strtol (in->begin, in->len, (glong *)&session->expire); - session->argnum ++; + session->argnum++; session->state = KVSTORAGE_STATE_READ_ARGLEN; - rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_LINE, + -1); } else { session->state = KVSTORAGE_STATE_READ_CMD; @@ -877,7 +991,9 @@ kvstorage_read_socket (f_str_t * in, void *arg) if (session->command == KVSTORAGE_CMD_DECR) { session->arg_data.value = -session->arg_data.value; } - rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_LINE, + -1); return kvstorage_process_command (session, TRUE); } } @@ -885,16 +1001,25 @@ kvstorage_read_socket (f_str_t * in, void *arg) /* We get datablock for set command */ if (session->command == KVSTORAGE_CMD_SET && session->argc == 4) { session->state = KVSTORAGE_STATE_READ_CMD; - rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); - if (rspamd_kv_storage_insert (session->cf->storage, session->key, session->keylen, - in->begin, in->len, - session->flags, session->expire)) { - return rspamd_dispatcher_write (session->dispather, "+OK" CRLF, - sizeof ("+OK" CRLF) - 1, FALSE, TRUE); + rspamd_set_dispatcher_policy (session->dispather, + BUFFER_LINE, + -1); + if (rspamd_kv_storage_insert (session->cf->storage, + session->key, session->keylen, + in->begin, in->len, + session->flags, session->expire)) { + return rspamd_dispatcher_write (session->dispather, + "+OK" CRLF, + sizeof ("+OK" CRLF) - 1, + FALSE, + TRUE); } else { - return rspamd_dispatcher_write (session->dispather, "-ERR not stored" CRLF, - sizeof ("-ERR not stored" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "-ERR not stored" CRLF, + sizeof ("-ERR not stored" CRLF) - 1, + FALSE, + TRUE); } } } @@ -902,26 +1027,36 @@ kvstorage_read_socket (f_str_t * in, void *arg) case KVSTORAGE_STATE_READ_DATA: session->state = KVSTORAGE_STATE_READ_CMD; rspamd_set_dispatcher_policy (session->dispather, BUFFER_LINE, -1); - if (rspamd_kv_storage_insert (session->cf->storage, session->key, session->keylen, - in->begin, in->len, - session->flags, session->expire)) { + if (rspamd_kv_storage_insert (session->cf->storage, session->key, + session->keylen, + in->begin, in->len, + session->flags, session->expire)) { if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, "STORED" CRLF, - sizeof ("STORED" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "STORED" CRLF, + sizeof ("STORED" CRLF) - 1, + FALSE, + TRUE); } else { return rspamd_dispatcher_write (session->dispather, "+OK" CRLF, - sizeof ("+OK" CRLF) - 1, FALSE, TRUE); + sizeof ("+OK" CRLF) - 1, FALSE, TRUE); } } else { if (!is_redis) { - return rspamd_dispatcher_write (session->dispather, ERROR_NOT_STORED, - sizeof (ERROR_NOT_STORED) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + ERROR_NOT_STORED, + sizeof (ERROR_NOT_STORED) - 1, + FALSE, + TRUE); } else { - return rspamd_dispatcher_write (session->dispather, "-ERR not stored" CRLF, - sizeof ("-ERR not stored" CRLF) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispather, + "-ERR not stored" CRLF, + sizeof ("-ERR not stored" CRLF) - 1, + FALSE, + TRUE); } } @@ -937,17 +1072,18 @@ kvstorage_read_socket (f_str_t * in, void *arg) static gboolean kvstorage_write_socket (void *arg) { - struct kvstorage_session *session = (struct kvstorage_session *) arg; + struct kvstorage_session *session = (struct kvstorage_session *) arg; if (session->elt) { if ((session->elt->flags & KV_ELT_NEED_INSERT) != 0) { /* Insert to cache and free element */ session->elt->flags &= ~KV_ELT_NEED_INSERT; RW_R_UNLOCK (&session->cf->storage->rwlock); - rspamd_kv_storage_insert_cache (session->cf->storage, ELT_KEY (session->elt), - session->elt->keylen, ELT_DATA (session->elt), - session->elt->size, session->elt->flags, - session->elt->expire, NULL); + rspamd_kv_storage_insert_cache (session->cf->storage, + ELT_KEY (session->elt), + session->elt->keylen, ELT_DATA (session->elt), + session->elt->size, session->elt->flags, + session->elt->expire, NULL); g_free (session->elt); session->elt = NULL; return TRUE; @@ -966,8 +1102,8 @@ kvstorage_write_socket (void *arg) static void kvstorage_err_socket (GError * err, void *arg) { - struct kvstorage_session *session = (struct kvstorage_session *) arg; - struct kvstorage_worker_thread *thr; + struct kvstorage_session *session = (struct kvstorage_session *) arg; + struct kvstorage_worker_thread *thr; thr = session->thr; if (err->code != -1) { @@ -990,14 +1126,15 @@ kvstorage_err_socket (GError * err, void *arg) static void thr_accept_socket (gint fd, short what, void *arg) { - struct kvstorage_worker_thread *thr = (struct kvstorage_worker_thread *)arg; - union sa_union su; - socklen_t addrlen = sizeof (su.ss); - gint nfd; - struct kvstorage_session *session; + struct kvstorage_worker_thread *thr = (struct kvstorage_worker_thread *)arg; + union sa_union su; + socklen_t addrlen = sizeof (su.ss); + gint nfd; + struct kvstorage_session *session; g_mutex_lock (thr->accept_mtx); - if ((nfd = accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) { + if ((nfd = + accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) { thr_warn ("%ud: accept failed: %s", thr->id, strerror (errno)); g_mutex_unlock (thr->accept_mtx); return; @@ -1014,9 +1151,14 @@ thr_accept_socket (gint fd, short what, void *arg) session->state = KVSTORAGE_STATE_READ_CMD; session->thr = thr; session->sock = nfd; - session->dispather = rspamd_create_dispatcher (thr->ev_base, nfd, BUFFER_LINE, - kvstorage_read_socket, kvstorage_write_socket, - kvstorage_err_socket, thr->tv, session); + session->dispather = rspamd_create_dispatcher (thr->ev_base, + nfd, + BUFFER_LINE, + kvstorage_read_socket, + kvstorage_write_socket, + kvstorage_err_socket, + thr->tv, + session); g_mutex_unlock (thr->accept_mtx); session->elt = NULL; @@ -1026,7 +1168,7 @@ thr_accept_socket (gint fd, short what, void *arg) } else if (su.ss.ss_family == AF_INET) { memcpy (&session->client_addr, &su.s4.sin_addr, - sizeof (struct in_addr)); + sizeof (struct in_addr)); } } @@ -1036,8 +1178,8 @@ thr_accept_socket (gint fd, short what, void *arg) static void thr_term_socket (gint fd, short what, void *arg) { - struct kvstorage_worker_thread *thr = (struct kvstorage_worker_thread *)arg; - struct timeval tv; + struct kvstorage_worker_thread *thr = (struct kvstorage_worker_thread *)arg; + struct timeval tv; if (read (fd, &tv, sizeof (struct timeval)) != sizeof (struct timeval)) { thr_err ("cannot read data from socket: %s", strerror (errno)); @@ -1055,18 +1197,26 @@ thr_term_socket (gint fd, short what, void *arg) static gpointer kvstorage_thread (gpointer ud) { - struct kvstorage_worker_thread *thr = ud; + struct kvstorage_worker_thread *thr = ud; /* Block signals as it is dispatcher deity */ sigprocmask (SIG_BLOCK, thr->signals, NULL); /* Init thread specific events */ thr->ev_base = event_init (); - event_set (&thr->bind_ev, thr->worker->cf->listen_sock, EV_READ | EV_PERSIST, thr_accept_socket, (void *)thr); + event_set (&thr->bind_ev, + thr->worker->cf->listen_sock, + EV_READ | EV_PERSIST, + thr_accept_socket, + (void *)thr); event_base_set (thr->ev_base, &thr->bind_ev); event_add (&thr->bind_ev, NULL); - event_set (&thr->term_ev, thr->term_sock[0], EV_READ | EV_PERSIST, thr_term_socket, (void *)thr); + event_set (&thr->term_ev, + thr->term_sock[0], + EV_READ | EV_PERSIST, + thr_term_socket, + (void *)thr); event_base_set (thr->ev_base, &thr->term_ev); event_add (&thr->term_ev, NULL); @@ -1079,12 +1229,17 @@ kvstorage_thread (gpointer ud) * Create new thread, set it detached */ static struct kvstorage_worker_thread * -create_kvstorage_thread (struct rspamd_worker *worker, struct kvstorage_worker_ctx *ctx, guint id, sigset_t *signals) +create_kvstorage_thread (struct rspamd_worker *worker, + struct kvstorage_worker_ctx *ctx, + guint id, + sigset_t *signals) { - struct kvstorage_worker_thread *new; - GError *err = NULL; + struct kvstorage_worker_thread *new; + GError *err = NULL; - new = rspamd_mempool_alloc (ctx->pool, sizeof (struct kvstorage_worker_thread)); + new = + rspamd_mempool_alloc (ctx->pool, + sizeof (struct kvstorage_worker_thread)); new->ctx = ctx; new->worker = worker; new->tv = &ctx->io_timeout; @@ -1102,10 +1257,14 @@ create_kvstorage_thread (struct rspamd_worker *worker, struct kvstorage_worker_c #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) new->thr = g_thread_create (kvstorage_thread, new, FALSE, &err); #else - gchar *name; + gchar *name; - name = rspamd_mempool_alloc (ctx->pool, sizeof ("kvstorage_thread") + sizeof ("4294967296") - 1); - rspamd_snprintf (name, sizeof ("kvstorage_thread") + sizeof ("4294967296") - 1, "kvstorage_thread%d", id); + name = rspamd_mempool_alloc (ctx->pool, + sizeof ("kvstorage_thread") + sizeof ("4294967296") - 1); + rspamd_snprintf (name, + sizeof ("kvstorage_thread") + sizeof ("4294967296") - 1, + "kvstorage_thread%d", + id); new->thr = g_thread_new (name, kvstorage_thread, new); #endif @@ -1125,17 +1284,18 @@ create_kvstorage_thread (struct rspamd_worker *worker, struct kvstorage_worker_c void start_keystorage (struct rspamd_worker *worker) { - struct sigaction signals; - struct kvstorage_worker_ctx *ctx = worker->ctx; - guint i; - struct kvstorage_worker_thread *thr; - struct timeval tv; - GList *cur; + struct sigaction signals; + struct kvstorage_worker_ctx *ctx = worker->ctx; + guint i; + struct kvstorage_worker_thread *thr; + struct timeval tv; + GList *cur; gperf_profiler_init (worker->srv->cfg, "kvstorage"); if (!g_thread_supported ()) { - msg_err ("threads support is not supported on your system so kvstorage is not functionable"); + msg_err ( + "threads support is not supported on your system so kvstorage is not functionable"); exit (EXIT_SUCCESS); } /* Create socketpair */ @@ -1148,7 +1308,8 @@ start_keystorage (struct rspamd_worker *worker) #if _EVENT_NUMERIC_VERSION > 0x02000000 if (evthread_use_pthreads () == -1) { - msg_err ("threads support is not supported in your libevent so kvstorage is not functionable"); + msg_err ( + "threads support is not supported in your libevent so kvstorage is not functionable"); exit (EXIT_SUCCESS); } #endif @@ -1176,7 +1337,7 @@ start_keystorage (struct rspamd_worker *worker) #endif /* Start workers threads */ - for (i = 0; i < worker->cf->count; i ++) { + for (i = 0; i < worker->cf->count; i++) { thr = create_kvstorage_thread (worker, ctx, i, &signals.sa_mask); if (thr != NULL) { ctx->threads = g_list_prepend (ctx->threads, thr); @@ -1185,7 +1346,7 @@ start_keystorage (struct rspamd_worker *worker) sigprocmask (SIG_BLOCK, &signals.sa_mask, NULL); /* Signal processing cycle */ - for (;;) { + for (;; ) { msg_debug ("calling sigsuspend"); sigemptyset (&signals.sa_mask); sigsuspend (&signals.sa_mask); @@ -1197,9 +1358,11 @@ start_keystorage (struct rspamd_worker *worker) cur = ctx->threads; while (cur) { thr = cur->data; - while (write (thr->term_sock[1], &tv, sizeof (struct timeval)) == -1) { + while (write (thr->term_sock[1], &tv, + sizeof (struct timeval)) == -1) { if (errno != EAGAIN) { - msg_err ("write to term socket failed: %s", strerror (errno)); + msg_err ("write to term socket failed: %s", + strerror (errno)); abort (); } } @@ -1211,13 +1374,16 @@ start_keystorage (struct rspamd_worker *worker) soft_wanna_die = 0; tv.tv_sec = SOFT_SHUTDOWN_TIME; tv.tv_usec = 0; - msg_info ("worker's shutdown is pending in %d sec", SOFT_SHUTDOWN_TIME); + msg_info ("worker's shutdown is pending in %d sec", + SOFT_SHUTDOWN_TIME); cur = ctx->threads; while (cur) { thr = cur->data; - while (write (thr->term_sock[1], &tv, sizeof (struct timeval)) == -1) { + while (write (thr->term_sock[1], &tv, + sizeof (struct timeval)) == -1) { if (errno != EAGAIN) { - msg_err ("write to term socket failed: %s", strerror (errno)); + msg_err ("write to term socket failed: %s", + strerror (errno)); abort (); } } diff --git a/src/kvstorage_sqlite.c b/src/kvstorage_sqlite.c index 7a3a25fcf..c9b504974 100644 --- a/src/kvstorage_sqlite.c +++ b/src/kvstorage_sqlite.c @@ -30,8 +30,10 @@ #include <sqlite3.h> #define TABLE_NAME "kvstorage" -#define CREATE_TABLE_SQL "CREATE TABLE " TABLE_NAME " (key TEXT CONSTRAINT _key PRIMARY KEY, data BLOB)" -#define SET_SQL "INSERT OR REPLACE INTO " TABLE_NAME " (key, data) VALUES (?1, ?2)" +#define CREATE_TABLE_SQL "CREATE TABLE " TABLE_NAME \ + " (key TEXT CONSTRAINT _key PRIMARY KEY, data BLOB)" +#define SET_SQL "INSERT OR REPLACE INTO " TABLE_NAME \ + " (key, data) VALUES (?1, ?2)" #define GET_SQL "SELECT data FROM " TABLE_NAME " WHERE key = ?1" #define DELETE_SQL "DELETE FROM " TABLE_NAME " WHERE key = ?1" @@ -46,13 +48,13 @@ struct sqlite_op { /* Main sqlite structure */ struct rspamd_sqlite_backend { - backend_init init_func; /*< this callback is called on kv storage initialization */ - backend_insert insert_func; /*< this callback is called when element is inserted */ - backend_replace replace_func; /*< this callback is called when element is replaced */ - backend_lookup lookup_func; /*< this callback is used for lookup of element */ - backend_delete delete_func; /*< this callback is called when an element is deleted */ - backend_sync sync_func; /*< this callback is called when backend need to be synced */ - backend_destroy destroy_func; /*< this callback is used for destroying all elements inside backend */ + backend_init init_func; /*< this callback is called on kv storage initialization */ + backend_insert insert_func; /*< this callback is called when element is inserted */ + backend_replace replace_func; /*< this callback is called when element is replaced */ + backend_lookup lookup_func; /*< this callback is used for lookup of element */ + backend_delete delete_func; /*< this callback is called when an element is deleted */ + backend_sync sync_func; /*< this callback is called when backend need to be synced */ + backend_destroy destroy_func; /*< this callback is used for destroying all elements inside backend */ sqlite3 *dbp; gchar *filename; gchar *dirname; @@ -67,16 +69,19 @@ struct rspamd_sqlite_backend { /* Process single sqlite operation */ static gboolean -sqlite_process_single_op (struct rspamd_sqlite_backend *db, struct sqlite_op *op) +sqlite_process_single_op (struct rspamd_sqlite_backend *db, + struct sqlite_op *op) { - gboolean res = FALSE; + gboolean res = FALSE; op->elt->flags &= ~KV_ELT_DIRTY; switch (op->op) { case SQLITE_OP_INSERT: case SQLITE_OP_REPLACE: - if (sqlite3_bind_text (db->set_stmt, 1, ELT_KEY (op->elt), op->elt->keylen, SQLITE_STATIC) == SQLITE_OK && - sqlite3_bind_blob (db->set_stmt, 2, op->elt, ELT_SIZE (op->elt), SQLITE_STATIC) == SQLITE_OK) { + if (sqlite3_bind_text (db->set_stmt, 1, ELT_KEY (op->elt), + op->elt->keylen, SQLITE_STATIC) == SQLITE_OK && + sqlite3_bind_blob (db->set_stmt, 2, op->elt, ELT_SIZE (op->elt), + SQLITE_STATIC) == SQLITE_OK) { if (sqlite3_step (db->set_stmt) == SQLITE_DONE) { res = TRUE; } @@ -84,7 +89,8 @@ sqlite_process_single_op (struct rspamd_sqlite_backend *db, struct sqlite_op *op sqlite3_reset (db->set_stmt); break; case SQLITE_OP_DELETE: - if (sqlite3_bind_text (db->delete_stmt, 1, ELT_KEY (op->elt), op->elt->keylen, SQLITE_STATIC) == SQLITE_OK) { + if (sqlite3_bind_text (db->delete_stmt, 1, ELT_KEY (op->elt), + op->elt->keylen, SQLITE_STATIC) == SQLITE_OK) { if (sqlite3_step (db->delete_stmt) == SQLITE_DONE) { res = TRUE; } @@ -103,14 +109,14 @@ sqlite_process_single_op (struct rspamd_sqlite_backend *db, struct sqlite_op *op static gboolean sqlite_process_queue (struct rspamd_kv_backend *backend) { - struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; - struct sqlite_op *op; - GList *cur; + struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; + struct sqlite_op *op; + GList *cur; cur = db->ops_queue->head; while (cur) { op = cur->data; - if (! sqlite_process_single_op (db, op)) { + if (!sqlite_process_single_op (db, op)) { return FALSE; } cur = g_list_next (cur); @@ -120,7 +126,8 @@ sqlite_process_queue (struct rspamd_kv_backend *backend) cur = db->ops_queue->head; while (cur) { op = cur->data; - if (op->op == SQLITE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != 0) { + if (op->op == SQLITE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != + 0) { /* Also clean memory */ g_slice_free1 (ELT_SIZE (op->elt), op->elt); } @@ -139,10 +146,15 @@ sqlite_process_queue (struct rspamd_kv_backend *backend) static gboolean rspamd_sqlite_create_table (struct rspamd_sqlite_backend *db) { - gint ret; - sqlite3_stmt *stmt = NULL; - - ret = sqlite3_prepare_v2 (db->dbp, CREATE_TABLE_SQL, sizeof (CREATE_TABLE_SQL) - 1, &stmt, NULL); + gint ret; + sqlite3_stmt *stmt = NULL; + + ret = + sqlite3_prepare_v2 (db->dbp, + CREATE_TABLE_SQL, + sizeof (CREATE_TABLE_SQL) - 1, + &stmt, + NULL); if (ret != SQLITE_OK) { if (stmt != NULL) { sqlite3_finalize (stmt); @@ -164,11 +176,11 @@ rspamd_sqlite_create_table (struct rspamd_sqlite_backend *db) static void rspamd_sqlite_init (struct rspamd_kv_backend *backend) { - struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; - guint32 flags; - gint ret, r; - gchar sqlbuf[BUFSIZ]; - sqlite3_stmt *stmt = NULL; + struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; + guint32 flags; + gint ret, r; + gchar sqlbuf[BUFSIZ]; + sqlite3_stmt *stmt = NULL; /* Set multi-threaded mode */ if (sqlite3_config (SQLITE_CONFIG_MULTITHREAD) != SQLITE_OK) { @@ -176,8 +188,8 @@ rspamd_sqlite_init (struct rspamd_kv_backend *backend) } flags = SQLITE_OPEN_READWRITE | - SQLITE_OPEN_CREATE | - SQLITE_OPEN_NOMUTEX; + SQLITE_OPEN_CREATE | + SQLITE_OPEN_NOMUTEX; ret = sqlite3_open_v2 (db->filename, &db->dbp, flags, NULL); @@ -185,7 +197,9 @@ rspamd_sqlite_init (struct rspamd_kv_backend *backend) goto err; } /* Now check if we have table */ - r = rspamd_snprintf (sqlbuf, sizeof (sqlbuf), "SELECT * FROM " TABLE_NAME " LIMIT 1"); + r = rspamd_snprintf (sqlbuf, + sizeof (sqlbuf), + "SELECT * FROM " TABLE_NAME " LIMIT 1"); ret = sqlite3_prepare_v2 (db->dbp, sqlbuf, r, &stmt, NULL); if (ret == SQLITE_ERROR) { @@ -209,15 +223,27 @@ rspamd_sqlite_init (struct rspamd_kv_backend *backend) sqlite3_finalize (stmt); /* Prepare required statements */ - ret = sqlite3_prepare_v2 (db->dbp, GET_SQL, sizeof (GET_SQL) - 1, &db->get_stmt, NULL); + ret = sqlite3_prepare_v2 (db->dbp, + GET_SQL, + sizeof (GET_SQL) - 1, + &db->get_stmt, + NULL); if (ret != SQLITE_OK) { goto err; } - ret = sqlite3_prepare_v2 (db->dbp, SET_SQL, sizeof (SET_SQL) - 1, &db->set_stmt, NULL); + ret = sqlite3_prepare_v2 (db->dbp, + SET_SQL, + sizeof (SET_SQL) - 1, + &db->set_stmt, + NULL); if (ret != SQLITE_OK) { goto err; } - ret = sqlite3_prepare_v2 (db->dbp, DELETE_SQL, sizeof (DELETE_SQL) - 1, &db->delete_stmt, NULL); + ret = sqlite3_prepare_v2 (db->dbp, + DELETE_SQL, + sizeof (DELETE_SQL) - 1, + &db->delete_stmt, + NULL); if (ret != SQLITE_OK) { goto err; } @@ -245,11 +271,14 @@ err: } static gboolean -rspamd_sqlite_insert (struct rspamd_kv_backend *backend, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_sqlite_insert (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; - struct sqlite_op *op; - struct rspamd_kv_element search_elt; + struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; + struct sqlite_op *op; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -260,7 +289,8 @@ rspamd_sqlite_insert (struct rspamd_kv_backend *backend, gpointer key, guint key if ((op = g_hash_table_lookup (db->ops_hash, &search_elt)) != NULL) { /* We found another op with such key in this queue */ - if (op->op == SQLITE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != 0) { + if (op->op == SQLITE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != + 0) { /* Also clean memory */ g_slice_free1 (ELT_SIZE (op->elt), op->elt); } @@ -277,7 +307,8 @@ rspamd_sqlite_insert (struct rspamd_kv_backend *backend, gpointer key, guint key g_hash_table_insert (db->ops_hash, elt, op); } - if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= db->sync_ops) { + if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= + db->sync_ops) { return sqlite_process_queue (backend); } @@ -285,17 +316,21 @@ rspamd_sqlite_insert (struct rspamd_kv_backend *backend, gpointer key, guint key } static gboolean -rspamd_sqlite_replace (struct rspamd_kv_backend *backend, gpointer key, guint keylen, struct rspamd_kv_element *elt) +rspamd_sqlite_replace (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen, + struct rspamd_kv_element *elt) { - struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; - struct sqlite_op *op; + struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; + struct sqlite_op *op; if (!db->initialized) { return FALSE; } if ((op = g_hash_table_lookup (db->ops_hash, elt)) != NULL) { /* We found another op with such key in this queue */ - if (op->op == SQLITE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != 0) { + if (op->op == SQLITE_OP_DELETE || (op->elt->flags & KV_ELT_NEED_FREE) != + 0) { /* Also clean memory */ g_slice_free1 (ELT_SIZE (op->elt), op->elt); } @@ -312,22 +347,25 @@ rspamd_sqlite_replace (struct rspamd_kv_backend *backend, gpointer key, guint ke g_hash_table_insert (db->ops_hash, elt, op); } - if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= db->sync_ops) { + if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= + db->sync_ops) { return sqlite_process_queue (backend); } return TRUE; } -static struct rspamd_kv_element* -rspamd_sqlite_lookup (struct rspamd_kv_backend *backend, gpointer key, guint keylen) +static struct rspamd_kv_element * +rspamd_sqlite_lookup (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen) { - struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; - struct sqlite_op *op; - struct rspamd_kv_element *elt = NULL; - gint l; - gconstpointer d; - struct rspamd_kv_element search_elt; + struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; + struct sqlite_op *op; + struct rspamd_kv_element *elt = NULL; + gint l; + gconstpointer d; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -344,7 +382,8 @@ rspamd_sqlite_lookup (struct rspamd_kv_backend *backend, gpointer key, guint key return op->elt; } - if (sqlite3_bind_text (db->get_stmt, 1, key, keylen, SQLITE_STATIC) == SQLITE_OK) { + if (sqlite3_bind_text (db->get_stmt, 1, key, keylen, + SQLITE_STATIC) == SQLITE_OK) { if (sqlite3_step (db->get_stmt) == SQLITE_ROW) { l = sqlite3_column_bytes (db->get_stmt, 0); elt = g_malloc (l); @@ -359,12 +398,14 @@ rspamd_sqlite_lookup (struct rspamd_kv_backend *backend, gpointer key, guint key } static void -rspamd_sqlite_delete (struct rspamd_kv_backend *backend, gpointer key, guint keylen) +rspamd_sqlite_delete (struct rspamd_kv_backend *backend, + gpointer key, + guint keylen) { - struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; - struct sqlite_op *op; - struct rspamd_kv_element *elt; - struct rspamd_kv_element search_elt; + struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; + struct sqlite_op *op; + struct rspamd_kv_element *elt; + struct rspamd_kv_element search_elt; search_elt.keylen = keylen; search_elt.p = key; @@ -390,7 +431,8 @@ rspamd_sqlite_delete (struct rspamd_kv_backend *backend, gpointer key, guint key g_queue_push_head (db->ops_queue, op); g_hash_table_insert (db->ops_hash, elt, op); - if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= db->sync_ops) { + if (db->sync_ops > 0 && g_queue_get_length (db->ops_queue) >= + db->sync_ops) { sqlite_process_queue (backend); } @@ -400,7 +442,7 @@ rspamd_sqlite_delete (struct rspamd_kv_backend *backend, gpointer key, guint key static void rspamd_sqlite_destroy (struct rspamd_kv_backend *backend) { - struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; + struct rspamd_sqlite_backend *db = (struct rspamd_sqlite_backend *)backend; if (db->initialized) { sqlite_process_queue (backend); @@ -426,9 +468,9 @@ rspamd_sqlite_destroy (struct rspamd_kv_backend *backend) struct rspamd_kv_backend * rspamd_kv_sqlite_new (const gchar *filename, guint sync_ops) { - struct rspamd_sqlite_backend *new; - struct stat st; - gchar *dirname; + struct rspamd_sqlite_backend *new; + struct stat st; + gchar *dirname; if (filename == NULL) { return NULL; diff --git a/src/kvstorage_sqlite.h b/src/kvstorage_sqlite.h index cea14df26..0ed0fd1ea 100644 --- a/src/kvstorage_sqlite.h +++ b/src/kvstorage_sqlite.h @@ -31,7 +31,8 @@ #ifdef WITH_SQLITE /* Create new sqlite backend */ -struct rspamd_kv_backend* rspamd_kv_sqlite_new (const gchar *filename, guint sync_ops); +struct rspamd_kv_backend * rspamd_kv_sqlite_new (const gchar *filename, + guint sync_ops); #endif diff --git a/src/legacy_controller.c b/src/legacy_controller.c index 05b1794cd..a03480462 100644 --- a/src/legacy_controller.c +++ b/src/legacy_controller.c @@ -53,14 +53,14 @@ gpointer init_controller (struct rspamd_config *cfg); void start_controller (struct rspamd_worker *worker); worker_t controller_worker = { - "controller", /* Name */ - init_controller, /* Init function */ - start_controller, /* Start function */ - TRUE, /* Has socket */ - FALSE, /* Non unique */ - FALSE, /* Non threaded */ - TRUE, /* Killable */ - SOCK_STREAM /* TCP socket */ + "controller", /* Name */ + init_controller, /* Init function */ + start_controller, /* Start function */ + TRUE, /* Has socket */ + FALSE, /* Non unique */ + FALSE, /* Non threaded */ + TRUE, /* Killable */ + SOCK_STREAM /* TCP socket */ }; enum command_type { @@ -85,26 +85,26 @@ enum command_type { }; struct controller_command { - gchar *command; - gboolean privilleged; - enum command_type type; + gchar *command; + gboolean privilleged; + enum command_type type; }; struct custom_controller_command { - const gchar *command; - gboolean privilleged; - gboolean require_message; - controller_func_t handler; + const gchar *command; + gboolean privilleged; + gboolean require_message; + controller_func_t handler; }; struct rspamd_controller_ctx { - char *password; - guint32 timeout; - struct rspamd_dns_resolver *resolver; - struct event_base *ev_base; - struct event rrd_event; - struct rspamd_rrd_file *rrd_file; - struct rspamd_main *srv; + char *password; + guint32 timeout; + struct rspamd_dns_resolver *resolver; + struct event_base *ev_base; + struct event rrd_event; + struct rspamd_rrd_file *rrd_file; + struct rspamd_main *srv; }; static struct controller_command commands[] = { @@ -128,20 +128,20 @@ static struct controller_command commands[] = { {"add_action", TRUE, COMMAND_ADD_ACTION} }; -static GList *custom_commands = NULL; +static GList *custom_commands = NULL; -static time_t start_time; +static time_t start_time; -static gchar greetingbuf[1024]; +static gchar greetingbuf[1024]; -static gboolean controller_write_socket (void *arg); +static gboolean controller_write_socket (void *arg); static void free_session (void *ud) { - GList *part; - struct mime_part *p; - struct controller_session *session = ud; + GList *part; + struct mime_part *p; + struct controller_session *session = ud; msg_debug ("freeing session %p", session); @@ -165,16 +165,19 @@ free_session (void *ud) static gboolean restful_write_reply (gint error_code, const gchar *err_message, - const gchar *buf, gsize buflen, rspamd_io_dispatcher_t *d) + const gchar *buf, gsize buflen, rspamd_io_dispatcher_t *d) { - static gchar hbuf[256]; - gint r; + static gchar hbuf[256]; + gint r; r = rspamd_snprintf (hbuf, sizeof (hbuf), "HTTP/1.0 %d %s" CRLF "Version: " RVERSION CRLF, error_code, err_message ? err_message : "OK"); if (buflen > 0) { - r += rspamd_snprintf (hbuf + r, sizeof (hbuf) - r, "Content-Length: %z" CRLF, buflen); + r += rspamd_snprintf (hbuf + r, + sizeof (hbuf) - r, + "Content-Length: %z" CRLF, + buflen); } r += rspamd_snprintf (hbuf + r, sizeof (hbuf) - r, CRLF); @@ -195,16 +198,19 @@ restful_write_reply (gint error_code, const gchar *err_message, static gboolean restful_write_reply_string (gint error_code, const gchar *err_message, - GString *buf, rspamd_io_dispatcher_t *d) + GString *buf, rspamd_io_dispatcher_t *d) { - static gchar hbuf[256]; - gint r; + static gchar hbuf[256]; + gint r; r = rspamd_snprintf (hbuf, sizeof (hbuf), "HTTP/1.0 %d %s" CRLF "Version: " RVERSION CRLF, error_code, err_message ? err_message : "OK"); if (buf->len > 0) { - r += rspamd_snprintf (hbuf + r, sizeof (hbuf) - r, "Content-Length: %z" CRLF, buf->len); + r += rspamd_snprintf (hbuf + r, + sizeof (hbuf) - r, + "Content-Length: %z" CRLF, + buf->len); } r += rspamd_snprintf (hbuf + r, sizeof (hbuf) - r, CRLF); @@ -226,18 +232,25 @@ restful_write_reply_string (gint error_code, const gchar *err_message, static gint check_auth (struct controller_command *cmd, struct controller_session *session) { - gchar out_buf[128]; - gint r; + gchar out_buf[128]; + gint r; if (cmd->privilleged && !session->authorized) { if (!session->restful) { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "not authorized" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "not authorized" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return 0; } } else { - (void)restful_write_reply (403, "Not authorized", NULL, 0, session->dispatcher); + (void)restful_write_reply (403, + "Not authorized", + NULL, + 0, + session->dispatcher); } return 0; } @@ -246,19 +259,21 @@ check_auth (struct controller_command *cmd, struct controller_session *session) } static gboolean -write_whole_statfile (struct controller_session *session, gchar *symbol, struct rspamd_classifier_config *ccf) +write_whole_statfile (struct controller_session *session, + gchar *symbol, + struct rspamd_classifier_config *ccf) { - stat_file_t *statfile; - struct rspamd_statfile_config *st; - gchar out_buf[BUFSIZ]; - guint i; - guint64 rev, ti, len, pos, blocks; - gchar *out; - struct rspamd_binlog_element log_elt; - struct stat_file_block *stat_elt; + stat_file_t *statfile; + struct rspamd_statfile_config *st; + gchar out_buf[BUFSIZ]; + guint i; + guint64 rev, ti, len, pos, blocks; + gchar *out; + struct rspamd_binlog_element log_elt; + struct stat_file_block *stat_elt; statfile = get_statfile_by_symbol (session->worker->srv->statfile_pool, ccf, - symbol, &st, FALSE); + symbol, &st, FALSE); if (statfile == NULL) { return FALSE; } @@ -270,14 +285,17 @@ write_whole_statfile (struct controller_session *session, gchar *symbol, struct ti = time (NULL); statfile_set_revision (statfile, rev, ti); } - msg_info ("send a whole statfile %s with version %uL to slave", symbol, rev); + msg_info ("send a whole statfile %s with version %uL to slave", symbol, + rev); blocks = statfile_get_total_blocks (statfile); len = blocks * sizeof (struct rspamd_binlog_element); out = rspamd_mempool_alloc (session->session_pool, len); - for (i = 0, pos = 0; i < blocks; i ++) { - stat_elt = (struct stat_file_block *)((u_char *)statfile->map + statfile->seek_pos + i * sizeof (struct stat_file_block)); + for (i = 0, pos = 0; i < blocks; i++) { + stat_elt = + (struct stat_file_block *)((u_char *)statfile->map + + statfile->seek_pos + i * sizeof (struct stat_file_block)); if (fabs (stat_elt->value) > 0.001) { /* Write only those values which value is not 0 */ log_elt.h1 = stat_elt->hash1; @@ -289,29 +307,35 @@ write_whole_statfile (struct controller_session *session, gchar *symbol, struct } } - i = rspamd_snprintf (out_buf, sizeof (out_buf), "%uL %uL %uL" CRLF, rev, ti, pos); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, i, TRUE, FALSE)) { + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "%uL %uL %uL" CRLF, + rev, + ti, + pos); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, TRUE, + FALSE)) { return FALSE; } if (!rspamd_dispatcher_write (session->dispatcher, out, pos, TRUE, TRUE)) { return FALSE; } - + return TRUE; } static gboolean process_sync_command (struct controller_session *session, gchar **args) { - gchar out_buf[BUFSIZ], *arg, *err_str, *symbol; - gint r; - guint64 rev, time; - struct rspamd_statfile_config *st = NULL; - struct rspamd_classifier_config *ccf; - GList *cur; - struct rspamd_binlog *binlog; - GByteArray *data = NULL; + gchar out_buf[BUFSIZ], *arg, *err_str, *symbol; + gint r; + guint64 rev, time; + struct rspamd_statfile_config *st = NULL; + struct rspamd_classifier_config *ccf; + GList *cur; + struct rspamd_binlog *binlog; + GByteArray *data = NULL; arg = *args; if (!arg || *arg == '\0') { @@ -345,7 +369,7 @@ process_sync_command (struct controller_session *session, gchar **args) msg_info ("bad symbol: %s", symbol); return FALSE; } - + cur = g_list_first (ccf->statfiles); while (cur) { st = cur->data; @@ -355,28 +379,35 @@ process_sync_command (struct controller_session *session, gchar **args) st = NULL; cur = g_list_next (cur); } - if (st == NULL) { + if (st == NULL) { msg_info ("bad symbol: %s", symbol); - return FALSE; - } - + return FALSE; + } + binlog = get_binlog_by_statfile (st); if (binlog == NULL) { msg_info ("cannot open binlog: %s", symbol); - return FALSE; + return FALSE; } - + while (binlog_sync (binlog, rev, &time, &data)) { - rev ++; - r = rspamd_snprintf (out_buf, sizeof (out_buf), "%uL %uL %z" CRLF, rev, time, data->len); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + rev++; + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "%uL %uL %z" CRLF, + rev, + time, + data->len); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, + FALSE)) { if (data != NULL) { g_free (data); } return FALSE; } if (data->data != NULL) { - if (!rspamd_dispatcher_write (session->dispatcher, data->data, data->len, TRUE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, data->data, + data->len, TRUE, FALSE)) { if (data != NULL) { g_free (data); } @@ -402,10 +433,10 @@ process_sync_command (struct controller_session *session, gchar **args) static gboolean process_counters_command (struct controller_session *session) { - GList *cur; - struct cache_item *item; - struct symbols_cache *cache; - GString *out; + GList *cur; + struct cache_item *item; + struct symbols_cache *cache; + GString *out; cache = session->cfg->cache; out = g_string_sized_new (BUFSIZ); @@ -420,8 +451,8 @@ process_counters_command (struct controller_session *session) item = cur->data; if (!item->is_callback) { rspamd_printf_gstring (out, "%s %.2f %d %.3f" CRLF, - item->s->symbol, item->s->weight, - item->s->frequency, item->s->avg_time); + item->s->symbol, item->s->weight, + item->s->frequency, item->s->avg_time); } cur = g_list_next (cur); } @@ -430,15 +461,18 @@ process_counters_command (struct controller_session *session) item = cur->data; if (!item->is_callback) { rspamd_printf_gstring (out, "%s %.2f %d %.3f" CRLF, - item->s->symbol, item->s->weight, - item->s->frequency, item->s->avg_time); + item->s->symbol, item->s->weight, + item->s->frequency, item->s->avg_time); } cur = g_list_next (cur); } } if (!session->restful) { - return rspamd_dispatcher_write_string (session->dispatcher, out, FALSE, TRUE); + return rspamd_dispatcher_write_string (session->dispatcher, + out, + FALSE, + TRUE); } else { return restful_write_reply_string (200, NULL, out, session->dispatcher); @@ -448,27 +482,33 @@ process_counters_command (struct controller_session *session) static gboolean process_stat_command (struct controller_session *session, gboolean do_reset) { - GString *out; - gint i; - guint64 used, total, rev, ham = 0, spam = 0; - time_t ti; - rspamd_mempool_stat_t mem_st; - struct rspamd_classifier_config *ccf; - stat_file_t *statfile; - struct rspamd_statfile_config *st; - GList *cur_cl, *cur_st; - struct rspamd_stat *stat, stat_copy; + GString *out; + gint i; + guint64 used, total, rev, ham = 0, spam = 0; + time_t ti; + rspamd_mempool_stat_t mem_st; + struct rspamd_classifier_config *ccf; + stat_file_t *statfile; + struct rspamd_statfile_config *st; + GList *cur_cl, *cur_st; + struct rspamd_stat *stat, stat_copy; rspamd_mempool_stat (&mem_st); memcpy (&stat_copy, session->worker->srv->stat, sizeof (stat_copy)); stat = &stat_copy; out = g_string_sized_new (BUFSIZ); - rspamd_printf_gstring (out, "Messages scanned: %ud" CRLF, stat->messages_scanned); + rspamd_printf_gstring (out, + "Messages scanned: %ud" CRLF, + stat->messages_scanned); if (stat->messages_scanned > 0) { - for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i ++) { - rspamd_printf_gstring (out, "Messages with action %s: %ud, %.2f%%" CRLF, - str_action_metric (i), stat->actions_stat[i], - (double)stat->actions_stat[i] / (double)stat->messages_scanned * 100.); + for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i++) { + rspamd_printf_gstring (out, + "Messages with action %s: %ud, %.2f%%" CRLF, + str_action_metric ( + i), + stat->actions_stat[i], + (double)stat->actions_stat[i] / (double)stat->messages_scanned * + 100.); if (i < METRIC_ACTION_GREYLIST) { spam += stat->actions_stat[i]; } @@ -479,23 +519,51 @@ process_stat_command (struct controller_session *session, gboolean do_reset) session->worker->srv->stat->actions_stat[i] = 0; } } - rspamd_printf_gstring (out, "Messages treated as spam: %ud, %.2f%%" CRLF, spam, - (double)spam / (double)stat->messages_scanned * 100.); - rspamd_printf_gstring (out, "Messages treated as ham: %ud, %.2f%%" CRLF, ham, - (double)ham / (double)stat->messages_scanned * 100.); - } - rspamd_printf_gstring (out, "Messages learned: %ud" CRLF, stat->messages_learned); - rspamd_printf_gstring (out, "Connections count: %ud" CRLF, stat->connections_count); - rspamd_printf_gstring (out, "Control connections count: %ud" CRLF, stat->control_connections_count); - rspamd_printf_gstring (out, "Pools allocated: %z" CRLF, mem_st.pools_allocated); - rspamd_printf_gstring (out, "Pools freed: %z" CRLF, mem_st.pools_freed); - rspamd_printf_gstring (out, "Bytes allocated: %z" CRLF, mem_st.bytes_allocated); - rspamd_printf_gstring (out, "Memory chunks allocated: %z" CRLF, mem_st.chunks_allocated); - rspamd_printf_gstring (out, "Shared chunks allocated: %z" CRLF, mem_st.shared_chunks_allocated); - rspamd_printf_gstring (out, "Chunks freed: %z" CRLF, mem_st.chunks_freed); - rspamd_printf_gstring (out, "Oversized chunks: %z" CRLF, mem_st.oversized_chunks); - rspamd_printf_gstring (out, "Fuzzy hashes stored: %ud" CRLF, stat->fuzzy_hashes); - rspamd_printf_gstring (out, "Fuzzy hashes expired: %ud" CRLF, stat->fuzzy_hashes_expired); + rspamd_printf_gstring (out, + "Messages treated as spam: %ud, %.2f%%" CRLF, + spam, + (double)spam / (double)stat->messages_scanned * 100.); + rspamd_printf_gstring (out, + "Messages treated as ham: %ud, %.2f%%" CRLF, + ham, + (double)ham / (double)stat->messages_scanned * 100.); + } + rspamd_printf_gstring (out, + "Messages learned: %ud" CRLF, + stat->messages_learned); + rspamd_printf_gstring (out, + "Connections count: %ud" CRLF, + stat->connections_count); + rspamd_printf_gstring (out, + "Control connections count: %ud" CRLF, + stat->control_connections_count); + rspamd_printf_gstring (out, + "Pools allocated: %z" CRLF, + mem_st.pools_allocated); + rspamd_printf_gstring (out, + "Pools freed: %z" CRLF, + mem_st.pools_freed); + rspamd_printf_gstring (out, + "Bytes allocated: %z" CRLF, + mem_st.bytes_allocated); + rspamd_printf_gstring (out, + "Memory chunks allocated: %z" CRLF, + mem_st.chunks_allocated); + rspamd_printf_gstring (out, + "Shared chunks allocated: %z" CRLF, + mem_st.shared_chunks_allocated); + rspamd_printf_gstring (out, + "Chunks freed: %z" CRLF, + mem_st.chunks_freed); + rspamd_printf_gstring (out, + "Oversized chunks: %z" CRLF, + mem_st.oversized_chunks); + rspamd_printf_gstring (out, + "Fuzzy hashes stored: %ud" CRLF, + stat->fuzzy_hashes); + rspamd_printf_gstring (out, + "Fuzzy hashes expired: %ud" CRLF, + stat->fuzzy_hashes_expired); /* Now write statistics for each statfile */ cur_cl = g_list_first (session->cfg->classifiers); while (cur_cl) { @@ -503,27 +571,42 @@ process_stat_command (struct controller_session *session, gboolean do_reset) cur_st = g_list_first (ccf->statfiles); while (cur_st) { st = cur_st->data; - if ((statfile = statfile_pool_is_open (session->worker->srv->statfile_pool, st->path)) == NULL) { - statfile = statfile_pool_open (session->worker->srv->statfile_pool, st->path, st->size, FALSE); + if ((statfile = + statfile_pool_is_open (session->worker->srv->statfile_pool, + st->path)) == NULL) { + statfile = statfile_pool_open ( + session->worker->srv->statfile_pool, + st->path, + st->size, + FALSE); } if (statfile) { used = statfile_get_used_blocks (statfile); total = statfile_get_total_blocks (statfile); statfile_get_revision (statfile, &rev, &ti); - if (total != (guint64)-1 && used != (guint64)-1) { + if (total != (guint64) - 1 && used != (guint64) - 1) { if (st->label) { rspamd_printf_gstring (out, - "Statfile: %s <%s> (version %uL); length: %Hz; free blocks: %uL; total blocks: %uL; free: %.2f%%" CRLF, - st->symbol, st->label, rev, st->size, - (total - used), total, - (double)((double)(total - used) / (double)total) * 100.); + "Statfile: %s <%s> (version %uL); length: %Hz; free blocks: %uL; total blocks: %uL; free: %.2f%%" CRLF, + st->symbol, + st->label, + rev, + st->size, + (total - used), + total, + (double)((double)(total - + used) / (double)total) * 100.); } else { rspamd_printf_gstring (out, - "Statfile: %s (version %uL); length: %Hz; free blocks: %uL; total blocks: %uL; free: %.2f%%" CRLF, - st->symbol, rev, st->size, - (total - used), total, - (double)((double)(total - used) / (double)total) * 100.); + "Statfile: %s (version %uL); length: %Hz; free blocks: %uL; total blocks: %uL; free: %.2f%%" CRLF, + st->symbol, + rev, + st->size, + (total - used), + total, + (double)((double)(total - + used) / (double)total) * 100.); } } } @@ -540,7 +623,10 @@ process_stat_command (struct controller_session *session, gboolean do_reset) } if (!session->restful) { - return rspamd_dispatcher_write_string (session->dispatcher, out, FALSE, TRUE); + return rspamd_dispatcher_write_string (session->dispatcher, + out, + FALSE, + TRUE); } else { return restful_write_reply_string (200, NULL, out, session->dispatcher); @@ -548,20 +634,30 @@ process_stat_command (struct controller_session *session, gboolean do_reset) } static gboolean -process_dynamic_conf_command (gchar **cmd_args, struct controller_session *session, gboolean is_action) +process_dynamic_conf_command (gchar **cmd_args, + struct controller_session *session, + gboolean is_action) { - struct rspamd_config *cfg = session->cfg; - gchar *arg, *metric, *name, *err_str; - gdouble value; - gboolean res; - guint real_act; + struct rspamd_config *cfg = session->cfg; + gchar *arg, *metric, *name, *err_str; + gdouble value; + gboolean res; + guint real_act; if (cfg->dynamic_conf == NULL) { if (!session->restful) { - return rspamd_dispatcher_write (session->dispatcher, "dynamic config is not specified" CRLF, 0, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispatcher, + "dynamic config is not specified" CRLF, + 0, + FALSE, + TRUE); } else { - return restful_write_reply (500, "dynamic config is not specified", NULL, 0, session->dispatcher); + return restful_write_reply (500, + "dynamic config is not specified", + NULL, + 0, + session->dispatcher); } } @@ -629,84 +725,131 @@ process_dynamic_conf_command (gchar **cmd_args, struct controller_session *sessi res = dump_dynamic_config (cfg); if (res) { if (!session->restful) { - return rspamd_dispatcher_write (session->dispatcher, "OK" CRLF, 0, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispatcher, + "OK" CRLF, + 0, + FALSE, + TRUE); } else { - return restful_write_reply (200, "OK", NULL, 0, session->dispatcher); + return restful_write_reply (200, + "OK", + NULL, + 0, + session->dispatcher); } } else { if (!session->restful) { - return rspamd_dispatcher_write (session->dispatcher, "Error dumping dynamic config" CRLF, 0, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispatcher, + "Error dumping dynamic config" CRLF, + 0, + FALSE, + TRUE); } else { - return restful_write_reply (500, "Error dumping dynamic config", NULL, 0, session->dispatcher); + return restful_write_reply (500, + "Error dumping dynamic config", + NULL, + 0, + session->dispatcher); } } } else { if (!session->restful) { - return rspamd_dispatcher_write (session->dispatcher, "Cannot add dynamic rule" CRLF, 0, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispatcher, + "Cannot add dynamic rule" CRLF, + 0, + FALSE, + TRUE); } else { - return restful_write_reply (500, "Cannot add dynamic rule", NULL, 0, session->dispatcher); + return restful_write_reply (500, + "Cannot add dynamic rule", + NULL, + 0, + session->dispatcher); } } invalid_arguments: if (!session->restful) { - return rspamd_dispatcher_write (session->dispatcher, "Invalid arguments" CRLF, 0, FALSE, TRUE); + return rspamd_dispatcher_write (session->dispatcher, + "Invalid arguments" CRLF, + 0, + FALSE, + TRUE); } else { - return restful_write_reply (500, "Invalid arguments", NULL, 0, session->dispatcher); + return restful_write_reply (500, + "Invalid arguments", + NULL, + 0, + session->dispatcher); } } static gboolean -process_command (struct controller_command *cmd, gchar **cmd_args, struct controller_session *session) +process_command (struct controller_command *cmd, + gchar **cmd_args, + struct controller_session *session) { - gchar out_buf[BUFSIZ], *arg, *err_str; - gint r = 0, days, hours, minutes; - time_t uptime; - guint32 size = 0; - struct rspamd_classifier_config *cl; - struct rspamd_controller_ctx *ctx = session->worker->ctx; + gchar out_buf[BUFSIZ], *arg, *err_str; + gint r = 0, days, hours, minutes; + time_t uptime; + guint32 size = 0; + struct rspamd_classifier_config *cl; + struct rspamd_controller_ctx *ctx = session->worker->ctx; switch (cmd->type) { case COMMAND_GET: case COMMAND_POST: session->restful = TRUE; session->state = STATE_HEADER; - session->kwargs = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); + session->kwargs = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); break; case COMMAND_PASSWORD: arg = *cmd_args; if (!arg || *arg == '\0') { msg_debug ("empty password passed"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "password command requires one argument" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "password command requires one argument" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; } if (ctx->password == NULL) { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "password command disabled in config, authorized access granted" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "password command disabled in config, authorized access granted" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; } 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)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "password accepted" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } } else { session->authorized = 0; - r = rspamd_snprintf (out_buf, sizeof (out_buf), "password NOT accepted" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "password NOT accepted" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } } @@ -716,14 +859,18 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro break; case COMMAND_RELOAD: if (check_auth (cmd, session)) { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "reload request sent" CRLF); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "reload request sent" CRLF); if (!session->restful) { - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } } else { - if (! restful_write_reply (200, out_buf, NULL, 0, session->dispatcher)) { + if (!restful_write_reply (200, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } } @@ -742,14 +889,18 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro break; case COMMAND_SHUTDOWN: if (check_auth (cmd, session)) { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "shutdown request sent" CRLF); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "shutdown request sent" CRLF); if (!session->restful) { - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } } else { - if (! restful_write_reply (200, out_buf, NULL, 0, session->dispatcher)) { + if (!restful_write_reply (200, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } } @@ -764,26 +915,48 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro days = uptime / 86400; hours = uptime / 3600 - days * 24; minutes = uptime / 60 - hours * 60 - days * 1440; - r = rspamd_snprintf (out_buf, sizeof (out_buf), "%d day%s %d hour%s %d minute%s" CRLF, days, days > 1 ? "s" : " ", hours, hours > 1 ? "s" : " ", minutes, minutes > 1 ? "s" : " "); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "%d day%s %d hour%s %d minute%s" CRLF, + days, + days > 1 ? "s" : " ", + hours, + hours > 1 ? "s" : " ", + minutes, + minutes > 1 ? "s" : " "); } /* If uptime is less than 1 minute print only seconds */ else if (uptime / 60 == 0) { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "%d second%s" CRLF, (gint)uptime, (gint)uptime > 1 ? "s" : " "); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "%d second%s" CRLF, + (gint)uptime, + (gint)uptime > 1 ? "s" : " "); } /* Else print the minutes and seconds. */ else { hours = uptime / 3600; minutes = uptime / 60 - hours * 60; uptime -= hours * 3600 + minutes * 60; - r = rspamd_snprintf (out_buf, sizeof (out_buf), "%d hour%s %d minute%s %d second%s" CRLF, hours, hours > 1 ? "s" : " ", minutes, minutes > 1 ? "s" : " ", (gint)uptime, uptime > 1 ? "s" : " "); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "%d hour%s %d minute%s %d second%s" CRLF, + hours, + hours > 1 ? "s" : " ", + minutes, + minutes > 1 ? "s" : " ", + (gint)uptime, + uptime > 1 ? "s" : " "); } if (!session->restful) { - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } } else { - if (! restful_write_reply (200, NULL, out_buf, r, session->dispatcher)) { + if (!restful_write_reply (200, NULL, out_buf, r, + session->dispatcher)) { return FALSE; } } @@ -795,8 +968,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro arg = *cmd_args; if (!arg || *arg == '\0') { msg_debug ("no statfile specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, + r, FALSE, FALSE)) { return FALSE; } return TRUE; @@ -804,8 +980,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro arg = *(cmd_args + 1); if (arg == NULL || *arg == '\0') { msg_debug ("no message size specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, + r, FALSE, FALSE)) { return FALSE; } return TRUE; @@ -813,8 +992,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro size = strtoul (arg, &err_str, 10); if (err_str && *err_str != '\0') { msg_debug ("message size is invalid: %s", arg); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn size is invalid" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, + r, FALSE, FALSE)) { return FALSE; } return TRUE; @@ -822,10 +1004,15 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro cl = rspamd_config_find_classifier (session->cfg, *cmd_args); } else { - if ((arg = g_hash_table_lookup (session->kwargs, "classifier")) == NULL) { + if ((arg = + g_hash_table_lookup (session->kwargs, + "classifier")) == NULL) { msg_debug ("no classifier specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } return TRUE; @@ -833,10 +1020,15 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro else { cl = rspamd_config_find_classifier (session->cfg, arg); } - if ((arg = g_hash_table_lookup (session->kwargs, "content-length")) == NULL) { + if ((arg = + g_hash_table_lookup (session->kwargs, + "content-length")) == NULL) { msg_debug ("no size specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } } @@ -844,8 +1036,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro size = strtoul (arg, &err_str, 10); if (err_str && *err_str != '\0') { msg_debug ("message size is invalid: %s", arg); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF); - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn size is invalid" CRLF); + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } return TRUE; @@ -857,7 +1052,9 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro /* By default learn positive */ session->in_class = TRUE; - rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_CHARACTER, size); + rspamd_set_dispatcher_policy (session->dispatcher, + BUFFER_CHARACTER, + size); session->state = STATE_LEARN_SPAM_PRE; } break; @@ -867,8 +1064,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro arg = *cmd_args; if (!arg || *arg == '\0') { msg_debug ("no statfile specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, + r, FALSE, FALSE)) { return FALSE; } return TRUE; @@ -876,8 +1076,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro arg = *(cmd_args + 1); if (arg == NULL || *arg == '\0') { msg_debug ("no message size specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, + r, FALSE, FALSE)) { return FALSE; } return TRUE; @@ -885,8 +1088,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro size = strtoul (arg, &err_str, 10); if (err_str && *err_str != '\0') { msg_debug ("message size is invalid: %s", arg); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn size is invalid" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, + r, FALSE, FALSE)) { return FALSE; } return TRUE; @@ -894,10 +1100,15 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro cl = rspamd_config_find_classifier (session->cfg, *cmd_args); } else { - if ((arg = g_hash_table_lookup (session->kwargs, "classifier")) == NULL) { + if ((arg = + g_hash_table_lookup (session->kwargs, + "classifier")) == NULL) { msg_debug ("no classifier specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } return TRUE; @@ -905,10 +1116,15 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro else { cl = rspamd_config_find_classifier (session->cfg, arg); } - if ((arg = g_hash_table_lookup (session->kwargs, "content-length")) == NULL) { + if ((arg = + g_hash_table_lookup (session->kwargs, + "content-length")) == NULL) { msg_debug ("no size specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF); + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } } @@ -916,8 +1132,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro size = strtoul (arg, &err_str, 10); if (err_str && *err_str != '\0') { msg_debug ("message size is invalid: %s", arg); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF); - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn size is invalid" CRLF); + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } return TRUE; @@ -929,7 +1148,9 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro /* By default learn positive */ session->in_class = FALSE; - rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_CHARACTER, size); + rspamd_set_dispatcher_policy (session->dispatcher, + BUFFER_CHARACTER, + size); session->state = STATE_LEARN_SPAM_PRE; } break; @@ -939,8 +1160,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro arg = *cmd_args; if (!arg || *arg == '\0') { msg_debug ("no statfile specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: stat filename and its size" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn command requires at least two arguments: stat filename and its size" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; @@ -948,8 +1172,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro arg = *(cmd_args + 1); if (arg == NULL || *arg == '\0') { msg_debug ("no message size specified in learn command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: symbol and message size" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn command requires at least two arguments: symbol and message size" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; @@ -957,15 +1184,21 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro size = strtoul (arg, &err_str, 10); if (err_str && *err_str != '\0') { msg_debug ("message size is invalid: %s", arg); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn size is invalid" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; } - session->learn_symbol = rspamd_mempool_strdup (session->session_pool, *cmd_args); - cl = g_hash_table_lookup (session->cfg->classifiers_symbols, *cmd_args); + session->learn_symbol = rspamd_mempool_strdup ( + session->session_pool, + *cmd_args); + cl = g_hash_table_lookup (session->cfg->classifiers_symbols, + *cmd_args); session->learn_classifier = cl; @@ -980,22 +1213,32 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro case 'r': arg = *(cmd_args + 1); if (!arg || *arg == '\0') { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "recipient is not defined" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "recipient is not defined" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, + out_buf, r, FALSE, FALSE)) { return FALSE; } } - session->learn_rcpt = rspamd_mempool_strdup (session->session_pool, arg); + session->learn_rcpt = rspamd_mempool_strdup ( + session->session_pool, + arg); break; case 'f': arg = *(cmd_args + 1); if (!arg || *arg == '\0') { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "from is not defined" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "from is not defined" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, + out_buf, r, FALSE, FALSE)) { return FALSE; } } - session->learn_from = rspamd_mempool_strdup (session->session_pool, arg); + session->learn_from = rspamd_mempool_strdup ( + session->session_pool, + arg); break; case 'n': session->in_class = 0; @@ -1003,8 +1246,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro case 'm': arg = *(cmd_args + 1); if (!arg || *arg == '\0') { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "multiplier is not defined" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "multiplier is not defined" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, + out_buf, r, FALSE, FALSE)) { return FALSE; } } @@ -1013,15 +1259,20 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro } break; default: - r = rspamd_snprintf (out_buf, sizeof (out_buf), "tokenizer is not defined" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "tokenizer is not defined" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, + out_buf, r, FALSE, FALSE)) { return FALSE; } return TRUE; } } } - rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_CHARACTER, size); + rspamd_set_dispatcher_policy (session->dispatcher, + BUFFER_CHARACTER, + size); session->state = STATE_LEARN; } break; @@ -1031,8 +1282,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro arg = *cmd_args; if (!arg || *arg == '\0') { msg_debug ("no statfile specified in weights command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "weights command requires two arguments: statfile and message size" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "weights command requires two arguments: statfile and message size" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; @@ -1040,8 +1294,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro arg = *(cmd_args + 1); if (arg == NULL || *arg == '\0') { msg_debug ("no message size specified in weights command"); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "weights command requires two arguments: statfile and message size" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "weights command requires two arguments: statfile and message size" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; @@ -1049,8 +1306,11 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro size = strtoul (arg, &err_str, 10); if (err_str && *err_str != '\0') { msg_debug ("message size is invalid: %s", arg); - r = rspamd_snprintf (out_buf, sizeof (out_buf), "message size is invalid" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "message size is invalid" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; @@ -1058,8 +1318,12 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro cl = g_hash_table_lookup (session->cfg->classifiers_symbols, *cmd_args); if (cl == NULL) { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "statfile %s is not defined" CRLF, *cmd_args); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "statfile %s is not defined" CRLF, + *cmd_args); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; @@ -1067,39 +1331,45 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro } session->learn_classifier = cl; - rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_CHARACTER, size); + rspamd_set_dispatcher_policy (session->dispatcher, + BUFFER_CHARACTER, + size); session->state = STATE_WEIGHTS; break; case COMMAND_SYNC: if (!process_sync_command (session, cmd_args)) { r = rspamd_snprintf (out_buf, sizeof (out_buf), "FAIL" CRLF); - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return TRUE; } break; case COMMAND_HELP: - r = rspamd_snprintf (out_buf, sizeof (out_buf), - "Rspamd CLI commands (* - privileged command):" CRLF - " help - this help message" CRLF - "(*) learn <statfile> <size> [-r recipient] [-m multiplier] [-f from] [-n] - learn message to specified statfile" CRLF - " quit - quit CLI session" CRLF - " password <password> - authenticate yourself for privileged commands" CRLF - "(*) reload - reload rspamd" CRLF - "(*) shutdown - shutdown rspamd" CRLF - " stat - show different rspamd stat" CRLF - " sync - run synchronization of statfiles" CRLF - " counters - show rspamd counters" CRLF - " uptime - rspamd uptime" CRLF - " weights <statfile> <size> - weight of message in all statfiles" CRLF); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "Rspamd CLI commands (* - privileged command):" CRLF + " help - this help message" CRLF + "(*) learn <statfile> <size> [-r recipient] [-m multiplier] [-f from] [-n] - learn message to specified statfile" CRLF + " quit - quit CLI session" CRLF + " password <password> - authenticate yourself for privileged commands" CRLF + "(*) reload - reload rspamd" CRLF + "(*) shutdown - shutdown rspamd" CRLF + " stat - show different rspamd stat" CRLF + " sync - run synchronization of statfiles" CRLF + " counters - show rspamd counters" CRLF + " uptime - rspamd uptime" CRLF + " weights <statfile> <size> - weight of message in all statfiles" CRLF); if (!session->restful) { - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } } else { - if (! restful_write_reply (200, NULL, out_buf, r, session->dispatcher)) { + if (!restful_write_reply (200, NULL, out_buf, r, + session->dispatcher)) { return FALSE; } } @@ -1122,9 +1392,12 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro } static controller_func_t -parse_custom_command (gchar *line, gchar **cmd_args, struct controller_session *session, gsize len) +parse_custom_command (gchar *line, + gchar **cmd_args, + struct controller_session *session, + gsize len) { - GList *cur; + GList *cur; struct custom_controller_command *cmd; if (len == 0) { @@ -1145,13 +1418,13 @@ parse_custom_command (gchar *line, gchar **cmd_args, struct controller_session * static struct controller_command * parse_normal_command (const gchar *line, gsize len) { - guint i; - struct controller_command *c; + guint i; + struct controller_command *c; if (len == 0) { len = strlen (line); } - for (i = 0; i < G_N_ELEMENTS (commands); i ++) { + for (i = 0; i < G_N_ELEMENTS (commands); i++) { c = &commands[i]; if (g_ascii_strncasecmp (line, c->command, len) == 0) { return c; @@ -1164,10 +1437,10 @@ parse_normal_command (const gchar *line, gsize len) static gboolean process_header (f_str_t *line, struct controller_session *session) { - gchar *headern; - struct controller_command *command; - struct rspamd_controller_ctx *ctx = session->worker->ctx; - controller_func_t custom_handler; + gchar *headern; + struct controller_command *command; + struct rspamd_controller_ctx *ctx = session->worker->ctx; + controller_func_t custom_handler; /* XXX: temporary workaround */ headern = NULL; @@ -1185,7 +1458,9 @@ process_header (f_str_t *line, struct controller_session *session) /* This header is actually command */ command = parse_normal_command (line->begin, line->len); if (command == NULL) { - if ((custom_handler = parse_custom_command (line->begin, NULL, session, line->len)) == NULL) { + if ((custom_handler = + parse_custom_command (line->begin, NULL, session, + line->len)) == NULL) { msg_info ("bad command header: %V", line); return FALSE; } @@ -1201,8 +1476,8 @@ process_header (f_str_t *line, struct controller_session *session) /* Password header */ if (g_ascii_strcasecmp (headern, "password") == 0) { if (ctx->password == NULL || - (line->len == strlen (ctx->password) - && memcmp (line->begin, ctx->password, line->len) == 0)) { + (line->len == strlen (ctx->password) + && memcmp (line->begin, ctx->password, line->len) == 0)) { session->authorized = TRUE; } else { @@ -1212,7 +1487,8 @@ process_header (f_str_t *line, struct controller_session *session) } } - g_hash_table_insert (session->kwargs, headern, fstrcstr (line, session->session_pool)); + g_hash_table_insert (session->kwargs, headern, + fstrcstr (line, session->session_pool)); return TRUE; } @@ -1223,7 +1499,7 @@ process_header (f_str_t *line, struct controller_session *session) static gboolean fin_learn_task (void *arg) { - struct rspamd_task *task = (struct rspamd_task *) arg; + struct rspamd_task *task = (struct rspamd_task *) arg; /* XXX: needs to be reworked */ @@ -1236,33 +1512,34 @@ fin_learn_task (void *arg) static void restore_learn_task (void *arg) { - struct rspamd_task *task = (struct rspamd_task *) arg; + struct rspamd_task *task = (struct rspamd_task *) arg; /* Special state */ } -static gboolean +static gboolean controller_read_socket (f_str_t * in, void *arg) { - struct controller_session *session = (struct controller_session *)arg; - struct classifier_ctx *cls_ctx; - gint len, i, r; - gchar *s, **params, *cmd, out_buf[128]; - struct controller_command *command; - struct rspamd_task *task; - struct mime_text_part *part; - GList *cur = NULL; - GTree *tokens = NULL; - GError *err = NULL; - f_str_t c; - controller_func_t custom_handler; + struct controller_session *session = (struct controller_session *)arg; + struct classifier_ctx *cls_ctx; + gint len, i, r; + gchar *s, **params, *cmd, out_buf[128]; + struct controller_command *command; + struct rspamd_task *task; + struct mime_text_part *part; + GList *cur = NULL; + GTree *tokens = NULL; + GError *err = NULL; + f_str_t c; + controller_func_t custom_handler; switch (session->state) { case STATE_COMMAND: s = fstrcstr (in, session->session_pool); params = g_strsplit_set (s, " ", -1); - rspamd_mempool_add_destructor (session->session_pool, (rspamd_mempool_destruct_t) g_strfreev, params); + rspamd_mempool_add_destructor (session->session_pool, + (rspamd_mempool_destruct_t) g_strfreev, params); len = g_strv_length (params); if (len > 0) { @@ -1270,15 +1547,20 @@ controller_read_socket (f_str_t * in, void *arg) command = parse_normal_command (cmd, 0); if (command != NULL) { - if (! process_command (command, ¶ms[1], session)) { + if (!process_command (command, ¶ms[1], session)) { return FALSE; } } else { - if ((custom_handler = parse_custom_command (cmd, ¶ms[1], session, 0)) == NULL) { + if ((custom_handler = + parse_custom_command (cmd, ¶ms[1], session, + 0)) == NULL) { msg_debug ("'%s'", cmd); - i = rspamd_snprintf (out_buf, sizeof (out_buf), "Unknown command" CRLF); - if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) { + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "Unknown command" CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, + i, FALSE, FALSE)) { return FALSE; } } @@ -1287,9 +1569,12 @@ controller_read_socket (f_str_t * in, void *arg) } } } - if (session->state != STATE_LEARN && session->state != STATE_LEARN_SPAM_PRE - && session->state != STATE_WEIGHTS && session->state != STATE_OTHER && session->state != STATE_HEADER) { - if (!rspamd_dispatcher_write (session->dispatcher, END, sizeof (END) - 1, FALSE, TRUE)) { + if (session->state != STATE_LEARN && session->state != + STATE_LEARN_SPAM_PRE + && session->state != STATE_WEIGHTS && session->state != + STATE_OTHER && session->state != STATE_HEADER) { + if (!rspamd_dispatcher_write (session->dispatcher, END, + sizeof (END) - 1, FALSE, TRUE)) { return FALSE; } if (session->state == STATE_QUIT) { @@ -1303,8 +1588,11 @@ controller_read_socket (f_str_t * in, void *arg) if (in->len == 0) { /* End of headers */ if (session->cmd == NULL && session->custom_handler == NULL) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Bad command" CRLF CRLF); - if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) { + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Bad command" CRLF CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, + FALSE, FALSE)) { return FALSE; } destroy_session (session->s); @@ -1312,7 +1600,7 @@ controller_read_socket (f_str_t * in, void *arg) } /* Perform command */ else if (session->cmd != NULL) { - if (! process_command (session->cmd, NULL, session)) { + if (!process_command (session->cmd, NULL, session)) { msg_debug ("process command failed"); return FALSE; } @@ -1320,16 +1608,21 @@ controller_read_socket (f_str_t * in, void *arg) else { session->custom_handler (NULL, session); } - if (session->state != STATE_LEARN && session->state != STATE_LEARN_SPAM_PRE - && session->state != STATE_WEIGHTS && session->state != STATE_OTHER) { + if (session->state != STATE_LEARN && session->state != + STATE_LEARN_SPAM_PRE + && session->state != STATE_WEIGHTS && session->state != + STATE_OTHER) { msg_debug ("closing restful connection"); destroy_session (session->s); return FALSE; } } else if (!process_header (in, session)) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Bad header" CRLF CRLF); - if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) { + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Bad header" CRLF CRLF); + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, + FALSE, FALSE)) { return FALSE; } destroy_session (session->s); @@ -1349,12 +1642,17 @@ controller_read_socket (f_str_t * in, void *arg) rspamd_task_free (task, FALSE); session->state = STATE_REPLY; if (session->restful) { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Cannot process message" CRLF CRLF); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Cannot process message" CRLF CRLF); } else { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "cannot process message" CRLF); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "cannot process message" CRLF); } - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } return FALSE; @@ -1364,23 +1662,34 @@ controller_read_socket (f_str_t * in, void *arg) rspamd_task_free (task, FALSE); if (err) { if (session->restful) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Learn classifier error: %s" CRLF CRLF, err->message); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Learn classifier error: %s" CRLF CRLF, + err->message); } else { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "learn failed, learn classifier error: %s" CRLF END, err->message); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn failed, learn classifier error: %s" CRLF END, + err->message); } g_error_free (err); } else { if (session->restful) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Learn classifier error: unknown" CRLF CRLF); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Learn classifier error: unknown" CRLF CRLF); } else { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "learn failed, unknown learn classifier error" CRLF END); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn failed, unknown learn classifier error" CRLF END); } } - if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, + FALSE, FALSE)) { return FALSE; } session->state = STATE_REPLY; @@ -1389,13 +1698,18 @@ controller_read_socket (f_str_t * in, void *arg) rspamd_task_free (task, FALSE); if (session->restful) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 200 Learn OK" CRLF CRLF); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 200 Learn OK" CRLF CRLF); } else { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "learn ok" CRLF END); + i = + rspamd_snprintf (out_buf, sizeof (out_buf), + "learn ok" CRLF END); } session->state = STATE_REPLY; - if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, + FALSE)) { return FALSE; } break; @@ -1413,25 +1727,35 @@ controller_read_socket (f_str_t * in, void *arg) msg_warn ("processing of message failed"); session->state = STATE_REPLY; if (session->restful) { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Cannot process message" CRLF CRLF); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Cannot process message" CRLF CRLF); } else { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "cannot process message" CRLF); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "cannot process message" CRLF); } if (!session->restful) { - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } } else { - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } } return FALSE; } /* Set up async session */ - task->s = new_async_session (task->task_pool, fin_learn_task, restore_learn_task, rspamd_task_free_hard, task); + task->s = new_async_session (task->task_pool, + fin_learn_task, + restore_learn_task, + rspamd_task_free_hard, + task); session->learn_task = task; session->state = STATE_LEARN_SPAM; rspamd_dispatcher_pause (session->dispatcher); @@ -1440,19 +1764,25 @@ controller_read_socket (f_str_t * in, void *arg) rspamd_dispatcher_restore (session->dispatcher); session->state = STATE_REPLY; if (session->restful) { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Cannot process message" CRLF CRLF); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Cannot process message" CRLF CRLF); } else { - r = rspamd_snprintf (out_buf, sizeof (out_buf), "cannot process message" CRLF); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "cannot process message" CRLF); } destroy_session (task->s); if (!session->restful) { - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } } else { - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } } @@ -1470,14 +1800,18 @@ controller_read_socket (f_str_t * in, void *arg) msg_warn ("processing of message failed"); rspamd_task_free (task, FALSE); session->state = STATE_REPLY; - r = rspamd_snprintf (out_buf, sizeof (out_buf), "cannot process message" CRLF END); + r = rspamd_snprintf (out_buf, + sizeof (out_buf), + "cannot process message" CRLF END); if (!session->restful) { - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, r, + FALSE, FALSE)) { return FALSE; } } else { - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } } @@ -1494,17 +1828,23 @@ controller_read_socket (f_str_t * in, void *arg) c.begin = part->content->data; c.len = part->content->len; - if (!session->learn_classifier->tokenizer->tokenize_func (session->learn_classifier->tokenizer, - session->session_pool, &c, &tokens, FALSE, part->is_utf, part->urls_offset)) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "weights failed, tokenizer error" CRLF END); + if (!session->learn_classifier->tokenizer->tokenize_func (session-> + learn_classifier->tokenizer, + session->session_pool, &c, &tokens, FALSE, part->is_utf, + part->urls_offset)) { + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "weights failed, tokenizer error" CRLF END); rspamd_task_free (task, FALSE); if (!session->restful) { - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, + r, FALSE, FALSE)) { return FALSE; } } else { - if (! restful_write_reply (500, out_buf, NULL, 0, session->dispatcher)) { + if (!restful_write_reply (500, out_buf, NULL, 0, + session->dispatcher)) { return FALSE; } } @@ -1513,40 +1853,53 @@ controller_read_socket (f_str_t * in, void *arg) } cur = g_list_next (cur); } - + /* Handle messages without text */ if (tokens == NULL) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "weights failed, no tokens can be extracted (no text data)" CRLF END); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "weights failed, no tokens can be extracted (no text data)" CRLF END); rspamd_task_free (task, FALSE); - if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, + FALSE, FALSE)) { return FALSE; } session->state = STATE_REPLY; return TRUE; } - - + + /* Init classifier */ - cls_ctx = session->learn_classifier->classifier->init_func (session->session_pool, session->learn_classifier); - - cur = session->learn_classifier->classifier->weights_func (cls_ctx, session->worker->srv->statfile_pool, - tokens, task); + cls_ctx = session->learn_classifier->classifier->init_func ( + session->session_pool, + session->learn_classifier); + + cur = session->learn_classifier->classifier->weights_func (cls_ctx, + session->worker->srv->statfile_pool, + tokens, + task); i = 0; struct classify_weight *w; while (cur) { w = cur->data; - i += rspamd_snprintf (out_buf + i, sizeof (out_buf) - i, "%s: %G" CRLF, w->name, w->weight); + i += rspamd_snprintf (out_buf + i, + sizeof (out_buf) - i, + "%s: %G" CRLF, + w->name, + w->weight); cur = g_list_next (cur); } i += rspamd_snprintf (out_buf + i, sizeof (out_buf) - i, END); if (i != 0) { - if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, + FALSE, FALSE)) { return FALSE; } } else { - if (!rspamd_dispatcher_write (session->dispatcher, "weights failed: classifier error" CRLF END, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, + "weights failed: classifier error" CRLF END, 0, FALSE, TRUE)) { return FALSE; } } @@ -1583,13 +1936,13 @@ controller_read_socket (f_str_t * in, void *arg) return TRUE; } -static gboolean +static gboolean controller_write_socket (void *arg) { - struct controller_session *session = (struct controller_session *)arg; - gint i; - gchar out_buf[1024]; - GError *err = NULL; + struct controller_session *session = (struct controller_session *)arg; + gint i; + gchar out_buf[1024]; + GError *err = NULL; if (session->state == STATE_QUIT) { /* Free buffers */ @@ -1600,44 +1953,66 @@ controller_write_socket (void *arg) /* Perform actual learn here */ if (session->learn_classifier == NULL) { if (session->restful) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Learn classifier error: %s" CRLF CRLF, "unknown classifier"); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Learn classifier error: %s" CRLF CRLF, + "unknown classifier"); } else { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "learn failed, learn classifier error: %s" CRLF END, "unknown classifier"); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn failed, learn classifier error: %s" CRLF END, + "unknown classifier"); } } else { - if (! learn_task_spam (session->learn_classifier, session->learn_task, session->in_class, &err)) { + if (!learn_task_spam (session->learn_classifier, + session->learn_task, session->in_class, &err)) { if (err) { if (session->restful) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Learn classifier error: %s" CRLF CRLF, err->message); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Learn classifier error: %s" CRLF CRLF, + err->message); } else { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "learn failed, learn classifier error: %s" CRLF END, err->message); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn failed, learn classifier error: %s" CRLF END, + err->message); } g_error_free (err); } else { if (session->restful) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 500 Learn classifier error: unknown" CRLF CRLF); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 500 Learn classifier error: unknown" CRLF CRLF); } else { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "learn failed, learn classifier error: unknown" CRLF END); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn failed, learn classifier error: unknown" CRLF END); } } } else { if (session->restful) { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "HTTP/1.0 200 Learn OK" CRLF CRLF); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "HTTP/1.0 200 Learn OK" CRLF CRLF); } else { - i = rspamd_snprintf (out_buf, sizeof (out_buf), "learn ok" CRLF END); + i = rspamd_snprintf (out_buf, + sizeof (out_buf), + "learn ok" CRLF END); } } } destroy_session (session->learn_task->s); session->state = STATE_REPLY; - if (! rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, + FALSE)) { return FALSE; } if (session->restful) { @@ -1653,7 +2028,9 @@ controller_write_socket (void *arg) } else { session->state = STATE_COMMAND; - rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_LINE, BUFSIZ); + rspamd_set_dispatcher_policy (session->dispatcher, + BUFFER_LINE, + BUFSIZ); } } rspamd_dispatcher_restore (session->dispatcher); @@ -1663,10 +2040,11 @@ controller_write_socket (void *arg) static void controller_err_socket (GError * err, void *arg) { - struct controller_session *session = (struct controller_session *)arg; + struct controller_session *session = (struct controller_session *)arg; if (err->code != EOF) { - msg_info ("abnormally closing control connection, error: %s", err->message); + msg_info ("abnormally closing control connection, error: %s", + err->message); } g_error_free (err); /* Free buffers */ @@ -1676,12 +2054,12 @@ controller_err_socket (GError * err, void *arg) static void accept_socket (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *)arg; - union sa_union su; - struct controller_session *new_session; - struct timeval *io_tv; - gint nfd; - struct rspamd_controller_ctx *ctx; + struct rspamd_worker *worker = (struct rspamd_worker *)arg; + union sa_union su; + struct controller_session *new_session; + struct timeval *io_tv; + gint nfd; + struct rspamd_controller_ctx *ctx; rspamd_inet_addr_t addr; ctx = worker->ctx; @@ -1700,7 +2078,8 @@ accept_socket (gint fd, short what, void *arg) new_session->sock = nfd; new_session->cfg = worker->srv->cfg; new_session->state = STATE_COMMAND; - new_session->session_pool = rspamd_mempool_new (rspamd_mempool_suggest_size () - 1); + new_session->session_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size () - 1); new_session->resolver = ctx->resolver; new_session->ev_base = ctx->ev_base; if (ctx->password == NULL) { @@ -1709,14 +2088,26 @@ accept_socket (gint fd, short what, void *arg) worker->srv->stat->control_connections_count++; /* Set up dispatcher */ - io_tv = rspamd_mempool_alloc (new_session->session_pool, sizeof (struct timeval)); + io_tv = + rspamd_mempool_alloc (new_session->session_pool, + sizeof (struct timeval)); 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, NULL, NULL, free_session, new_session); - - new_session->dispatcher = rspamd_create_dispatcher (ctx->ev_base, nfd, BUFFER_LINE, controller_read_socket, - controller_write_socket, controller_err_socket, io_tv, (void *)new_session); + new_session->s = new_async_session (new_session->session_pool, + NULL, + NULL, + free_session, + new_session); + + new_session->dispatcher = rspamd_create_dispatcher (ctx->ev_base, + nfd, + BUFFER_LINE, + controller_read_socket, + controller_write_socket, + controller_err_socket, + io_tv, + (void *)new_session); if (su.ss.ss_family == AF_UNIX) { msg_info ("accepted connection from unix socket"); @@ -1724,13 +2115,14 @@ accept_socket (gint fd, short what, void *arg) } else if (su.ss.ss_family == AF_INET) { msg_info ("accepted connection from %s port %d", - inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port)); + inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port)); memcpy (&new_session->dispatcher->peer_addr, &su.s4.sin_addr, - sizeof (guint32)); + sizeof (guint32)); } #if 0 /* As we support now restful HTTP like connections, this should not be printed anymore */ - if (! rspamd_dispatcher_write (new_session->dispatcher, greetingbuf, strlen (greetingbuf), FALSE, FALSE)) { + if (!rspamd_dispatcher_write (new_session->dispatcher, greetingbuf, + strlen (greetingbuf), FALSE, FALSE)) { msg_warn ("cannot write greeting"); } #endif @@ -1739,10 +2131,10 @@ accept_socket (gint fd, short what, void *arg) static gboolean create_rrd_file (const gchar *filename, struct rspamd_controller_ctx *ctx) { - GError *err = NULL; - GArray ar; - struct rrd_rra_def rra[5]; - struct rrd_ds_def ds[4]; + GError *err = NULL; + GArray ar; + struct rrd_rra_def rra[5]; + struct rrd_ds_def ds[4]; /* * DS: @@ -1759,29 +2151,32 @@ create_rrd_file (const gchar *filename, struct rspamd_controller_ctx *ctx) * 4) per 2 hours AVERAGE * 5) per day AVERAGE */ - ctx->rrd_file = rspamd_rrd_create (filename, 4, 5, CONTROLLER_RRD_STEP, &err); + ctx->rrd_file = + rspamd_rrd_create (filename, 4, 5, CONTROLLER_RRD_STEP, &err); if (ctx->rrd_file == NULL) { - msg_err ("cannot create rrd file %s, error: %s", filename, err->message); + msg_err ("cannot create rrd file %s, error: %s", filename, + err->message); g_error_free (err); return FALSE; } /* Add all ds and rra */ - rrd_make_default_ds ("spam", CONTROLLER_RRD_STEP, &ds[0]); + rrd_make_default_ds ("spam", CONTROLLER_RRD_STEP, &ds[0]); rrd_make_default_ds ("possible spam", CONTROLLER_RRD_STEP, &ds[1]); - rrd_make_default_ds ("greylist", CONTROLLER_RRD_STEP, &ds[2]); - rrd_make_default_ds ("ham", CONTROLLER_RRD_STEP, &ds[3]); + rrd_make_default_ds ("greylist", CONTROLLER_RRD_STEP, &ds[2]); + rrd_make_default_ds ("ham", CONTROLLER_RRD_STEP, &ds[3]); - rrd_make_default_rra ("AVERAGE", 1, 600, &rra[0]); - rrd_make_default_rra ("AVERAGE", 5, 600, &rra[1]); - rrd_make_default_rra ("AVERAGE", 30, 700, &rra[2]); - rrd_make_default_rra ("AVERAGE", 120, 775, &rra[3]); + rrd_make_default_rra ("AVERAGE", 1, 600, &rra[0]); + rrd_make_default_rra ("AVERAGE", 5, 600, &rra[1]); + rrd_make_default_rra ("AVERAGE", 30, 700, &rra[2]); + rrd_make_default_rra ("AVERAGE", 120, 775, &rra[3]); rrd_make_default_rra ("AVERAGE", 1440, 797, &rra[4]); ar.data = (gchar *)ds; ar.len = sizeof (ds); if (!rspamd_rrd_add_ds (ctx->rrd_file, &ar, &err)) { - msg_err ("cannot create rrd file %s, error: %s", filename, err->message); + msg_err ("cannot create rrd file %s, error: %s", filename, + err->message); g_error_free (err); rspamd_rrd_close (ctx->rrd_file); return FALSE; @@ -1790,7 +2185,8 @@ create_rrd_file (const gchar *filename, struct rspamd_controller_ctx *ctx) ar.data = (gchar *)rra; ar.len = sizeof (rra); if (!rspamd_rrd_add_rra (ctx->rrd_file, &ar, &err)) { - msg_err ("cannot create rrd file %s, error: %s", filename, err->message); + msg_err ("cannot create rrd file %s, error: %s", filename, + err->message); g_error_free (err); rspamd_rrd_close (ctx->rrd_file); return FALSE; @@ -1798,7 +2194,8 @@ create_rrd_file (const gchar *filename, struct rspamd_controller_ctx *ctx) /* Finalize */ if (!rspamd_rrd_finalize (ctx->rrd_file, &err)) { - msg_err ("cannot create rrd file %s, error: %s", filename, err->message); + msg_err ("cannot create rrd file %s, error: %s", filename, + err->message); g_error_free (err); rspamd_rrd_close (ctx->rrd_file); return FALSE; @@ -1810,11 +2207,11 @@ create_rrd_file (const gchar *filename, struct rspamd_controller_ctx *ctx) static void controller_update_rrd (gint fd, short what, void *arg) { - struct rspamd_controller_ctx *ctx = arg; - struct timeval tv; - GArray ar; - gdouble data[4]; - GError *err = NULL; + struct rspamd_controller_ctx *ctx = arg; + struct timeval tv; + GArray ar; + gdouble data[4]; + GError *err = NULL; /* * Data: @@ -1829,14 +2226,16 @@ controller_update_rrd (gint fd, short what, void *arg) /* Fill data */ data[0] = ctx->srv->stat->actions_stat[METRIC_ACTION_REJECT]; - data[1] = ctx->srv->stat->actions_stat[METRIC_ACTION_ADD_HEADER] + ctx->srv->stat->actions_stat[METRIC_ACTION_REWRITE_SUBJECT]; + data[1] = ctx->srv->stat->actions_stat[METRIC_ACTION_ADD_HEADER] + + ctx->srv->stat->actions_stat[METRIC_ACTION_REWRITE_SUBJECT]; data[2] = ctx->srv->stat->actions_stat[METRIC_ACTION_GREYLIST]; data[3] = ctx->srv->stat->actions_stat[METRIC_ACTION_NOACTION]; ar.data = (gchar *)data; ar.len = sizeof (data); if (!rspamd_rrd_add_record (ctx->rrd_file, &ar, &err)) { - msg_err ("cannot add record to rrd database: %s, stop rrd update", err->message); + msg_err ("cannot add record to rrd database: %s, stop rrd update", + err->message); g_error_free (err); } else { @@ -1847,8 +2246,8 @@ controller_update_rrd (gint fd, short what, void *arg) gpointer init_controller (struct rspamd_config *cfg) { - struct rspamd_controller_ctx *ctx; - GQuark type; + struct rspamd_controller_ctx *ctx; + GQuark type; type = g_quark_try_string ("controller"); ctx = g_malloc0 (sizeof (struct rspamd_controller_ctx)); @@ -1856,12 +2255,13 @@ init_controller (struct rspamd_config *cfg) ctx->timeout = CONTROLLER_IO_TIMEOUT * 1000; rspamd_rcl_register_worker_option (cfg, type, "password", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_ctx, password), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_ctx, password), 0); rspamd_rcl_register_worker_option (cfg, type, "timeout", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct rspamd_controller_ctx, timeout), RSPAMD_CL_FLAG_TIME_UINT_32); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct rspamd_controller_ctx, + timeout), RSPAMD_CL_FLAG_TIME_UINT_32); return ctx; } @@ -1869,11 +2269,11 @@ init_controller (struct rspamd_config *cfg) void start_controller (struct rspamd_worker *worker) { - gchar *hostbuf; - gsize hostmax; - struct rspamd_controller_ctx *ctx = worker->ctx; - GError *err = NULL; - struct timeval tv; + gchar *hostbuf; + gsize hostmax; + struct rspamd_controller_ctx *ctx = worker->ctx; + GError *err = NULL; + struct timeval tv; ctx->ev_base = rspamd_prepare_worker (worker, "controller", accept_socket); g_mime_init (0); @@ -1881,8 +2281,10 @@ start_controller (struct rspamd_worker *worker) start_time = time (NULL); /* Start statfile synchronization */ - if (!start_statfile_sync (worker->srv->statfile_pool, worker->srv->cfg, ctx->ev_base)) { - msg_info ("cannot start statfile synchronization, statfiles would not be synchronized"); + if (!start_statfile_sync (worker->srv->statfile_pool, worker->srv->cfg, + ctx->ev_base)) { + msg_info ( + "cannot start statfile synchronization, statfiles would not be synchronized"); } /* Check for rrd */ @@ -1892,7 +2294,9 @@ start_controller (struct rspamd_worker *worker) if (worker->srv->cfg->rrd_file) { ctx->rrd_file = rspamd_rrd_open (worker->srv->cfg->rrd_file, &err); if (ctx->rrd_file == NULL) { - msg_info ("cannot open rrd file: %s, error: %s, trying to create", worker->srv->cfg->rrd_file, err->message); + msg_info ("cannot open rrd file: %s, error: %s, trying to create", + worker->srv->cfg->rrd_file, + err->message); g_error_free (err); /* Try to create rrd file */ if (create_rrd_file (worker->srv->cfg->rrd_file, ctx)) { @@ -1913,10 +2317,16 @@ start_controller (struct rspamd_worker *worker) hostbuf = alloca (hostmax); gethostname (hostbuf, hostmax); hostbuf[hostmax - 1] = '\0'; - rspamd_snprintf (greetingbuf, sizeof (greetingbuf), "Rspamd version %s is running on %s" CRLF, RVERSION, hostbuf); + rspamd_snprintf (greetingbuf, + sizeof (greetingbuf), + "Rspamd version %s is running on %s" CRLF, + RVERSION, + hostbuf); start_map_watch (worker->srv->cfg, ctx->ev_base); - ctx->resolver = dns_resolver_init (worker->srv->logger, ctx->ev_base, worker->srv->cfg); + ctx->resolver = dns_resolver_init (worker->srv->logger, + ctx->ev_base, + worker->srv->cfg); event_base_loop (ctx->ev_base, 0); @@ -1929,7 +2339,10 @@ start_controller (struct rspamd_worker *worker) } void -register_custom_controller_command (const gchar *name, controller_func_t handler, gboolean privilleged, gboolean require_message) +register_custom_controller_command (const gchar *name, + controller_func_t handler, + gboolean privilleged, + gboolean require_message) { struct custom_controller_command *cmd; @@ -1942,6 +2355,6 @@ register_custom_controller_command (const gchar *name, controller_func_t handler custom_commands = g_list_prepend (custom_commands, cmd); } -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/libmime/expressions.c b/src/libmime/expressions.c index 5d19626bb..cce1209aa 100644 --- a/src/libmime/expressions.c +++ b/src/libmime/expressions.c @@ -33,25 +33,45 @@ #include "lua/lua_common.h" #include "diff.h" -gboolean rspamd_compare_encoding (struct rspamd_task *task, GList * args, void *unused); -gboolean rspamd_header_exists (struct rspamd_task *task, GList * args, void *unused); -gboolean rspamd_parts_distance (struct rspamd_task *task, GList * args, void *unused); -gboolean rspamd_recipients_distance (struct rspamd_task *task, GList * args, void *unused); -gboolean rspamd_has_only_html_part (struct rspamd_task *task, GList * args, void *unused); -gboolean rspamd_is_recipients_sorted (struct rspamd_task *task, GList * args, void *unused); -gboolean rspamd_compare_transfer_encoding (struct rspamd_task *task, GList * args, void *unused); -gboolean rspamd_is_html_balanced (struct rspamd_task *task, GList * args, void *unused); -gboolean rspamd_has_html_tag (struct rspamd_task *task, GList * args, void *unused); -gboolean rspamd_has_fake_html (struct rspamd_task *task, GList * args, void *unused); +gboolean rspamd_compare_encoding (struct rspamd_task *task, + GList * args, + void *unused); +gboolean rspamd_header_exists (struct rspamd_task *task, + GList * args, + void *unused); +gboolean rspamd_parts_distance (struct rspamd_task *task, + GList * args, + void *unused); +gboolean rspamd_recipients_distance (struct rspamd_task *task, + GList * args, + void *unused); +gboolean rspamd_has_only_html_part (struct rspamd_task *task, + GList * args, + void *unused); +gboolean rspamd_is_recipients_sorted (struct rspamd_task *task, + GList * args, + void *unused); +gboolean rspamd_compare_transfer_encoding (struct rspamd_task *task, + GList * args, + void *unused); +gboolean rspamd_is_html_balanced (struct rspamd_task *task, + GList * args, + void *unused); +gboolean rspamd_has_html_tag (struct rspamd_task *task, + GList * args, + void *unused); +gboolean rspamd_has_fake_html (struct rspamd_task *task, + GList * args, + void *unused); /* * List of internal functions of rspamd * Sorted by name to use bsearch */ static struct _fl { - const gchar *name; - rspamd_internal_func_t func; - void *user_data; + const gchar *name; + rspamd_internal_func_t func; + void *user_data; } rspamd_functions_list[] = { {"compare_encoding", rspamd_compare_encoding, NULL}, {"compare_parts_distance", rspamd_parts_distance, NULL}, @@ -65,30 +85,32 @@ static struct _fl { {"is_recipients_sorted", rspamd_is_recipients_sorted, NULL} }; -static struct _fl *list_ptr = &rspamd_functions_list[0]; -static guint32 functions_number = sizeof (rspamd_functions_list) / sizeof (struct _fl); -static gboolean list_allocated = FALSE; +static struct _fl *list_ptr = &rspamd_functions_list[0]; +static guint32 functions_number = sizeof (rspamd_functions_list) / + sizeof (struct _fl); +static gboolean list_allocated = FALSE; /* Bsearch routine */ static gint fl_cmp (const void *s1, const void *s2) { - struct _fl *fl1 = (struct _fl *)s1; - struct _fl *fl2 = (struct _fl *)s2; + struct _fl *fl1 = (struct _fl *)s1; + struct _fl *fl2 = (struct _fl *)s2; return strcmp (fl1->name, fl2->name); } /* Cache for regular expressions that are used in functions */ -void * +void * re_cache_check (const gchar *line, rspamd_mempool_t *pool) { - GHashTable *re_cache; - + GHashTable *re_cache; + re_cache = rspamd_mempool_get_variable (pool, "re_cache"); if (re_cache == NULL) { re_cache = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - rspamd_mempool_set_variable (pool, "re_cache", re_cache, (rspamd_mempool_destruct_t)g_hash_table_destroy); + rspamd_mempool_set_variable (pool, "re_cache", re_cache, + (rspamd_mempool_destruct_t)g_hash_table_destroy); return NULL; } return g_hash_table_lookup (re_cache, line); @@ -97,13 +119,14 @@ re_cache_check (const gchar *line, rspamd_mempool_t *pool) void re_cache_add (const gchar *line, void *pointer, rspamd_mempool_t *pool) { - GHashTable *re_cache; - + GHashTable *re_cache; + re_cache = rspamd_mempool_get_variable (pool, "re_cache"); if (re_cache == NULL) { re_cache = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - rspamd_mempool_set_variable (pool, "re_cache", re_cache, (rspamd_mempool_destruct_t)g_hash_table_destroy); + rspamd_mempool_set_variable (pool, "re_cache", re_cache, + (rspamd_mempool_destruct_t)g_hash_table_destroy); } g_hash_table_insert (re_cache, (gpointer)line, pointer); @@ -112,7 +135,7 @@ re_cache_add (const gchar *line, void *pointer, rspamd_mempool_t *pool) void re_cache_del (const gchar *line, rspamd_mempool_t *pool) { - GHashTable *re_cache; + GHashTable *re_cache; re_cache = rspamd_mempool_get_variable (pool, "re_cache"); @@ -126,17 +149,19 @@ re_cache_del (const gchar *line, rspamd_mempool_t *pool) * Functions for parsing expressions */ struct expression_stack { - gchar op; - struct expression_stack *next; + gchar op; + struct expression_stack *next; }; /* - * Push operand or operator to stack + * Push operand or operator to stack */ static struct expression_stack * -push_expression_stack (rspamd_mempool_t * pool, struct expression_stack *head, gchar op) +push_expression_stack (rspamd_mempool_t * pool, + struct expression_stack *head, + gchar op) { - struct expression_stack *new; + struct expression_stack *new; new = rspamd_mempool_alloc (pool, sizeof (struct expression_stack)); new->op = op; new->next = head; @@ -149,8 +174,8 @@ push_expression_stack (rspamd_mempool_t * pool, struct expression_stack *head, g static gchar delete_expression_stack (struct expression_stack **head) { - struct expression_stack *cur; - gchar res; + struct expression_stack *cur; + gchar res; if (*head == NULL) return 0; @@ -185,7 +210,7 @@ logic_priority (gchar a) * Return FALSE if symbol is not operation symbol (operand) * Return TRUE if symbol is operation symbol */ -static gboolean +static gboolean is_operation_symbol (gchar *a) { switch (*a) { @@ -197,19 +222,22 @@ is_operation_symbol (gchar *a) return TRUE; case 'O': case 'o': - if (g_ascii_strncasecmp (a, "or", sizeof ("or") - 1) == 0&& g_ascii_isspace (a[2])) { + if (g_ascii_strncasecmp (a, "or", + sizeof ("or") - 1) == 0 && g_ascii_isspace (a[2])) { return TRUE; } break; case 'A': case 'a': - if (g_ascii_strncasecmp (a, "and", sizeof ("and") - 1) == 0&& g_ascii_isspace (a[3])) { + if (g_ascii_strncasecmp (a, "and", + sizeof ("and") - 1) == 0 && g_ascii_isspace (a[3])) { return TRUE; } break; case 'N': case 'n': - if (g_ascii_strncasecmp (a, "not", sizeof ("not") - 1) == 0 && g_ascii_isspace (a[3])) { + if (g_ascii_strncasecmp (a, "not", + sizeof ("not") - 1) == 0 && g_ascii_isspace (a[3])) { return TRUE; } break; @@ -259,7 +287,7 @@ op_to_char (gchar *a, gchar **next) /* * Return TRUE if symbol can be regexp flag */ -static gboolean +static gboolean is_regexp_flag (gchar a) { switch (a) { @@ -284,9 +312,14 @@ is_regexp_flag (gchar a) } static void -insert_expression (rspamd_mempool_t * pool, struct expression **head, gint type, gchar op, void *operand, const gchar *orig) +insert_expression (rspamd_mempool_t * pool, + struct expression **head, + gint type, + gchar op, + void *operand, + const gchar *orig) { - struct expression *new, *cur; + struct expression *new, *cur; new = rspamd_mempool_alloc (pool, sizeof (struct expression)); new->type = type; @@ -311,11 +344,11 @@ insert_expression (rspamd_mempool_t * pool, struct expression **head, gint type, } } -static struct expression * +static struct expression * maybe_parse_expression (rspamd_mempool_t * pool, gchar *line) { - struct expression *expr; - gchar *p = line; + struct expression *expr; + gchar *p = line; while (*p) { if (is_operation_symbol (p)) { @@ -336,17 +369,17 @@ maybe_parse_expression (rspamd_mempool_t * pool, gchar *line) * Make inverse polish record for specified expression * Memory is allocated from given pool */ -struct expression * +struct expression * parse_expression (rspamd_mempool_t * pool, gchar *line) { - struct expression *expr = NULL; - struct expression_stack *stack = NULL; - struct expression_function *func = NULL; - struct expression *arg; - GQueue *function_stack; - gchar *p, *c, *str, op, newop, *copy, *next; - gboolean in_regexp = FALSE; - gint brackets = 0; + struct expression *expr = NULL; + struct expression_stack *stack = NULL; + struct expression_function *func = NULL; + struct expression *arg; + GQueue *function_stack; + gchar *p, *c, *str, op, newop, *copy, *next; + gboolean in_regexp = FALSE; + gint brackets = 0; enum { SKIP_SPACES, @@ -396,7 +429,12 @@ parse_expression (rspamd_mempool_t * pool, gchar *line) while (stack && stack->op != '(') { op = delete_expression_stack (&stack); if (op != '(') { - insert_expression (pool, &expr, EXPR_OPERATION, op, NULL, copy); + insert_expression (pool, + &expr, + EXPR_OPERATION, + op, + NULL, + copy); } } if (stack) { @@ -421,15 +459,23 @@ parse_expression (rspamd_mempool_t * pool, gchar *line) else { newop = op_to_char (p, &next); if (newop != '\0') { - if (logic_priority (stack->op) < logic_priority (newop)) { + if (logic_priority (stack->op) < + logic_priority (newop)) { stack = push_expression_stack (pool, stack, newop); } else { /* Pop all operations that have higher priority than this one */ - while ((stack != NULL) && (logic_priority (stack->op) >= logic_priority (newop))) { + while ((stack != NULL) && + (logic_priority (stack->op) >= + logic_priority (newop))) { op = delete_expression_stack (&stack); if (op != '(') { - insert_expression (pool, &expr, EXPR_OPERATION, op, NULL, copy); + insert_expression (pool, + &expr, + EXPR_OPERATION, + op, + NULL, + copy); } } stack = push_expression_stack (pool, stack, newop); @@ -459,7 +505,8 @@ parse_expression (rspamd_mempool_t * pool, gchar *line) case READ_REGEXP_FLAGS: if (!is_regexp_flag (*p) || *(p + 1) == '\0') { if (c != p) { - if ((is_regexp_flag (*p) || *p == '/') && *(p + 1) == '\0') { + if ((is_regexp_flag (*p) || *p == + '/') && *(p + 1) == '\0') { p++; } str = rspamd_mempool_alloc (pool, p - c + 2); @@ -467,7 +514,12 @@ parse_expression (rspamd_mempool_t * pool, gchar *line) g_strstrip (str); msg_debug ("found regexp: %s", str); if (strlen (str) > 0) { - insert_expression (pool, &expr, EXPR_REGEXP, 0, str, copy); + insert_expression (pool, + &expr, + EXPR_REGEXP, + 0, + str, + copy); } } c = p; @@ -486,7 +538,9 @@ parse_expression (rspamd_mempool_t * pool, gchar *line) p++; } else if (*p == '(') { - func = rspamd_mempool_alloc (pool, sizeof (struct expression_function)); + func = + rspamd_mempool_alloc (pool, + sizeof (struct expression_function)); func->name = rspamd_mempool_alloc (pool, p - c + 1); func->args = NULL; rspamd_strlcpy (func->name, c, (p - c + 1)); @@ -586,14 +640,14 @@ parse_expression (rspamd_mempool_t * pool, gchar *line) /* * Rspamd regexp utility functions */ -struct rspamd_regexp * +struct rspamd_regexp * parse_regexp (rspamd_mempool_t * pool, const gchar *line, gboolean raw_mode) { - const gchar *begin, *end, *p, *src, *start; - gchar *dbegin, *dend; - struct rspamd_regexp *result, *check; - gint regexp_flags = G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE; - GError *err = NULL; + const gchar *begin, *end, *p, *src, *start; + gchar *dbegin, *dend; + struct rspamd_regexp *result, *check; + gint regexp_flags = G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE; + GError *err = NULL; if (line == NULL) { msg_err ("cannot parse NULL line"); @@ -621,7 +675,7 @@ parse_regexp (rspamd_mempool_t * pool, const gchar *line, gboolean raw_mode) end = p; break; } - p --; + p--; } if (end) { result->header = rspamd_mempool_alloc (pool, end - line + 1); @@ -650,7 +704,9 @@ parse_regexp (rspamd_mempool_t * pool, const gchar *line, gboolean raw_mode) } else { /* We got header name earlier but have not found // expression, so it is invalid regexp */ - msg_warn ("got no header name (eg. header=) but without corresponding regexp, %s", src); + msg_warn ( + "got no header name (eg. header=) but without corresponding regexp, %s", + src); return NULL; } /* Find end */ @@ -695,7 +751,7 @@ parse_regexp (rspamd_mempool_t * pool, const gchar *line, gboolean raw_mode) result->is_raw = TRUE; p++; break; - /* Type flags */ + /* Type flags */ case 'H': if (result->type == REGEXP_NONE) { result->type = REGEXP_HEADER; @@ -728,13 +784,13 @@ parse_regexp (rspamd_mempool_t * pool, const gchar *line, gboolean raw_mode) break; case 'T': result->is_test = TRUE; - p ++; + p++; break; case 'S': result->is_strong = TRUE; - p ++; + p++; break; - /* Stop flags parsing */ + /* Stop flags parsing */ default: p = NULL; break; @@ -751,9 +807,12 @@ parse_regexp (rspamd_mempool_t * pool, const gchar *line, gboolean raw_mode) } /* Avoid multiply regexp structures for similar regexps */ - if ((check = (struct rspamd_regexp *)re_cache_check (result->regexp_text, pool)) != NULL) { + if ((check = + (struct rspamd_regexp *)re_cache_check (result->regexp_text, + pool)) != NULL) { /* Additional check for headers */ - if (result->type == REGEXP_HEADER || result->type == REGEXP_RAW_HEADER) { + if (result->type == REGEXP_HEADER || result->type == + REGEXP_RAW_HEADER) { if (result->header && check->header) { if (strcmp (result->header, check->header) == 0) { return check; @@ -769,20 +828,31 @@ parse_regexp (rspamd_mempool_t * pool, const gchar *line, gboolean raw_mode) result->raw_regexp = result->regexp; } else { - result->raw_regexp = g_regex_new (dbegin, regexp_flags | G_REGEX_RAW, 0, &err); - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_regex_unref, (void *)result->raw_regexp); - } - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_regex_unref, (void *)result->regexp); + result->raw_regexp = g_regex_new (dbegin, + regexp_flags | G_REGEX_RAW, + 0, + &err); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_regex_unref, + (void *)result->raw_regexp); + } + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_regex_unref, + (void *)result->regexp); *dend = '/'; if (result->regexp == NULL || err != NULL) { - msg_warn ("could not read regexp: %s while reading regexp %s", err->message, src); + msg_warn ("could not read regexp: %s while reading regexp %s", + err->message, + src); return NULL; } if (result->raw_regexp == NULL || err != NULL) { - msg_warn ("could not read raw regexp: %s while reading regexp %s", err->message, src); + msg_warn ("could not read raw regexp: %s while reading regexp %s", + err->message, + src); return NULL; } @@ -792,13 +862,19 @@ parse_regexp (rspamd_mempool_t * pool, const gchar *line, gboolean raw_mode) } gboolean -call_expression_function (struct expression_function * func, struct rspamd_task * task, lua_State *L) +call_expression_function (struct expression_function * func, + struct rspamd_task * task, + lua_State *L) { - struct _fl *selected, key; + struct _fl *selected, key; key.name = func->name; - selected = bsearch (&key, list_ptr, functions_number, sizeof (struct _fl), fl_cmp); + selected = bsearch (&key, + list_ptr, + functions_number, + sizeof (struct _fl), + fl_cmp); if (selected == NULL) { /* Try to check lua function */ return FALSE; @@ -807,21 +883,26 @@ call_expression_function (struct expression_function * func, struct rspamd_task return selected->func (task, func->args, selected->user_data); } -struct expression_argument * -get_function_arg (struct expression *expr, struct rspamd_task *task, gboolean want_string) +struct expression_argument * +get_function_arg (struct expression *expr, + struct rspamd_task *task, + gboolean want_string) { - GQueue *stack; - gsize cur, op1, op2; - struct expression_argument *res; - struct expression *it; + GQueue *stack; + gsize cur, op1, op2; + struct expression_argument *res; + struct expression *it; if (expr == NULL) { msg_warn ("NULL expression passed"); return NULL; } if (expr->next == NULL) { - res = rspamd_mempool_alloc (task->task_pool, sizeof (struct expression_argument)); - if (expr->type == EXPR_REGEXP || expr->type == EXPR_STR || expr->type == EXPR_REGEXP_PARSED) { + res = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct expression_argument)); + if (expr->type == EXPR_REGEXP || expr->type == EXPR_STR || expr->type == + EXPR_REGEXP_PARSED) { res->type = EXPRESSION_ARGUMENT_NORMAL; res->data = expr->content.operand; } @@ -831,27 +912,36 @@ get_function_arg (struct expression *expr, struct rspamd_task *task, gboolean wa res->data = GSIZE_TO_POINTER (cur); } else { - msg_warn ("cannot parse argument: it contains operator or bool expression that is not wanted"); + msg_warn ( + "cannot parse argument: it contains operator or bool expression that is not wanted"); return NULL; } return res; } else if (!want_string) { - res = rspamd_mempool_alloc (task->task_pool, sizeof (struct expression_argument)); + res = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct expression_argument)); res->type = EXPRESSION_ARGUMENT_BOOL; stack = g_queue_new (); it = expr; while (it) { - if (it->type == EXPR_REGEXP || it->type == EXPR_REGEXP_PARSED || it->type == EXPR_STR) { + if (it->type == EXPR_REGEXP || it->type == EXPR_REGEXP_PARSED || + it->type == EXPR_STR) { g_queue_free (stack); res->type = EXPRESSION_ARGUMENT_EXPR; res->data = expr; return res; } else if (it->type == EXPR_FUNCTION) { - cur = (gsize) call_expression_function ((struct expression_function *)it->content.operand, task, NULL); - debug_task ("function %s returned %s", ((struct expression_function *)it->content.operand)->name, cur ? "true" : "false"); + cur = + (gsize) call_expression_function ((struct + expression_function + *)it->content.operand, task, NULL); + debug_task ("function %s returned %s", + ((struct expression_function *)it->content.operand)->name, + cur ? "true" : "false"); } else if (it->type == EXPR_OPERATION) { if (g_queue_is_empty (stack)) { @@ -901,9 +991,11 @@ get_function_arg (struct expression *expr, struct rspamd_task *task, gboolean wa } void -register_expression_function (const gchar *name, rspamd_internal_func_t func, void *user_data) +register_expression_function (const gchar *name, + rspamd_internal_func_t func, + void *user_data) { - static struct _fl *new; + static struct _fl *new; functions_number++; @@ -924,7 +1016,7 @@ register_expression_function (const gchar *name, rspamd_internal_func_t func, vo gboolean rspamd_compare_encoding (struct rspamd_task *task, GList * args, void *unused) { - struct expression_argument *arg; + struct expression_argument *arg; if (args == NULL || task == NULL) { return FALSE; @@ -943,8 +1035,8 @@ rspamd_compare_encoding (struct rspamd_task *task, GList * args, void *unused) gboolean rspamd_header_exists (struct rspamd_task * task, GList * args, void *unused) { - struct expression_argument *arg; - GList *headerlist; + struct expression_argument *arg; + GList *headerlist; if (args == NULL || task == NULL) { return FALSE; @@ -957,7 +1049,10 @@ rspamd_header_exists (struct rspamd_task * task, GList * args, void *unused) } debug_task ("try to get header %s", (gchar *)arg->data); - headerlist = message_get_header (task->task_pool, task->message, (gchar *)arg->data, FALSE); + headerlist = message_get_header (task->task_pool, + task->message, + (gchar *)arg->data, + FALSE); if (headerlist) { g_list_free (headerlist); return TRUE; @@ -967,20 +1062,20 @@ rspamd_header_exists (struct rspamd_task * task, GList * args, void *unused) /* * This function is designed to find difference between text/html and text/plain parts - * It takes one argument: difference threshold, if we have two text parts, compare + * It takes one argument: difference threshold, if we have two text parts, compare * its hashes and check for threshold, if value is greater than threshold, return TRUE * and return FALSE otherwise. */ gboolean rspamd_parts_distance (struct rspamd_task * task, GList * args, void *unused) { - gint threshold, threshold2 = -1, diff; - struct mime_text_part *p1, *p2; - GList *cur; - struct expression_argument *arg; - GMimeObject *parent; - const GMimeContentType *ct; - gint *pdiff; + gint threshold, threshold2 = -1, diff; + struct mime_text_part *p1, *p2; + GList *cur; + struct expression_argument *arg; + GMimeObject *parent; + const GMimeContentType *ct; + gint *pdiff; if (args == NULL) { debug_task ("no threshold is specified, assume it 100"); @@ -991,7 +1086,8 @@ rspamd_parts_distance (struct rspamd_task * task, GList * args, void *unused) arg = get_function_arg (args->data, task, TRUE); threshold = strtoul ((gchar *)arg->data, NULL, 10); if (errno != 0) { - msg_info ("bad numeric value for threshold \"%s\", assume it 100", (gchar *)args->data); + msg_info ("bad numeric value for threshold \"%s\", assume it 100", + (gchar *)args->data); threshold = 100; } if (args->next) { @@ -999,17 +1095,22 @@ rspamd_parts_distance (struct rspamd_task * task, GList * args, void *unused) errno = 0; threshold2 = strtoul ((gchar *)arg->data, NULL, 10); if (errno != 0) { - msg_info ("bad numeric value for threshold \"%s\", ignore it", (gchar *)arg->data); + msg_info ("bad numeric value for threshold \"%s\", ignore it", + (gchar *)arg->data); threshold2 = -1; } } } - if ((pdiff = rspamd_mempool_get_variable (task->task_pool, "parts_distance")) != NULL) { + if ((pdiff = + rspamd_mempool_get_variable (task->task_pool, + "parts_distance")) != NULL) { diff = *pdiff; if (diff != -1) { if (threshold2 > 0) { - if (diff >= MIN (threshold, threshold2) && diff < MAX (threshold, threshold2)) { + if (diff >= + MIN (threshold, + threshold2) && diff < MAX (threshold, threshold2)) { return TRUE; } } @@ -1042,32 +1143,52 @@ rspamd_parts_distance (struct rspamd_task * task, GList * args, void *unused) parent = p1->parent; ct = g_mime_object_get_content_type (parent); #ifndef GMIME24 - if (ct == NULL || ! g_mime_content_type_is_type (ct, "multipart", "alternative")) { + if (ct == NULL || + !g_mime_content_type_is_type (ct, "multipart", "alternative")) { #else - if (ct == NULL || ! g_mime_content_type_is_type ((GMimeContentType *)ct, "multipart", "alternative")) { + if (ct == NULL || + !g_mime_content_type_is_type ((GMimeContentType *)ct, + "multipart", "alternative")) { #endif - debug_task ("two parts are not belong to multipart/alternative container, skip check"); - rspamd_mempool_set_variable (task->task_pool, "parts_distance", pdiff, NULL); + debug_task ( + "two parts are not belong to multipart/alternative container, skip check"); + rspamd_mempool_set_variable (task->task_pool, + "parts_distance", + pdiff, + NULL); return FALSE; } } else { - debug_task ("message contains two parts but they are in different multi-parts"); - rspamd_mempool_set_variable (task->task_pool, "parts_distance", pdiff, NULL); + debug_task ( + "message contains two parts but they are in different multi-parts"); + rspamd_mempool_set_variable (task->task_pool, + "parts_distance", + pdiff, + NULL); return FALSE; } if (!p1->is_empty && !p2->is_empty) { if (p1->diff_str != NULL && p2->diff_str != NULL) { - diff = compare_diff_distance_normalized (p1->diff_str, p2->diff_str); + diff = compare_diff_distance_normalized (p1->diff_str, + p2->diff_str); } else { diff = fuzzy_compare_parts (p1, p2); } - debug_task ("got likeliness between parts of %d%%, threshold is %d%%", diff, threshold); + debug_task ( + "got likeliness between parts of %d%%, threshold is %d%%", + diff, + threshold); *pdiff = diff; - rspamd_mempool_set_variable (task->task_pool, "parts_distance", pdiff, NULL); + rspamd_mempool_set_variable (task->task_pool, + "parts_distance", + pdiff, + NULL); if (threshold2 > 0) { - if (diff >= MIN (threshold, threshold2) && diff < MAX (threshold, threshold2)) { + if (diff >= + MIN (threshold, + threshold2) && diff < MAX (threshold, threshold2)) { return TRUE; } } @@ -1077,41 +1198,51 @@ rspamd_parts_distance (struct rspamd_task * task, GList * args, void *unused) } } } - else if ((p1->is_empty && !p2->is_empty) || (!p1->is_empty && p2->is_empty)) { + else if ((p1->is_empty && + !p2->is_empty) || (!p1->is_empty && p2->is_empty)) { /* Empty and non empty parts are different */ *pdiff = 0; - rspamd_mempool_set_variable (task->task_pool, "parts_distance", pdiff, NULL); + rspamd_mempool_set_variable (task->task_pool, + "parts_distance", + pdiff, + NULL); return TRUE; } } else { - debug_task ("message has too many text parts, so do not try to compare them with each other"); - rspamd_mempool_set_variable (task->task_pool, "parts_distance", pdiff, NULL); + debug_task ( + "message has too many text parts, so do not try to compare them with each other"); + rspamd_mempool_set_variable (task->task_pool, + "parts_distance", + pdiff, + NULL); return FALSE; } - rspamd_mempool_set_variable (task->task_pool, "parts_distance", pdiff, NULL); + rspamd_mempool_set_variable (task->task_pool, "parts_distance", pdiff, + NULL); return FALSE; } struct addr_list { - const gchar *name; - const gchar *addr; + const gchar *name; + const gchar *addr; }; #define COMPARE_RCPT_LEN 3 #define MIN_RCPT_TO_COMPARE 7 gboolean -rspamd_recipients_distance (struct rspamd_task *task, GList * args, void *unused) +rspamd_recipients_distance (struct rspamd_task *task, GList * args, + void *unused) { - struct expression_argument *arg; - InternetAddressList *cur; - InternetAddress *addr; - double threshold; - struct addr_list *ar; - gchar *c; - gint num, i, j, hits = 0, total = 0; + struct expression_argument *arg; + InternetAddressList *cur; + InternetAddress *addr; + double threshold; + struct addr_list *ar; + gchar *c; + gint num, i, j, hits = 0, total = 0; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1122,7 +1253,9 @@ rspamd_recipients_distance (struct rspamd_task *task, GList * args, void *unused errno = 0; threshold = strtod ((gchar *)arg->data, NULL); if (errno != 0) { - msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); + msg_warn ("invalid numeric value '%s': %s", + (gchar *)arg->data, + strerror (errno)); return FALSE; } @@ -1133,14 +1266,17 @@ rspamd_recipients_distance (struct rspamd_task *task, GList * args, void *unused if (num < MIN_RCPT_TO_COMPARE) { return FALSE; } - ar = rspamd_mempool_alloc0 (task->task_pool, num * sizeof (struct addr_list)); + ar = + rspamd_mempool_alloc0 (task->task_pool, num * + sizeof (struct addr_list)); /* Fill array */ cur = task->rcpts; #ifdef GMIME24 - for (i = 0; i < num; i ++) { + for (i = 0; i < num; i++) { addr = internet_address_list_get_address (cur, i); - ar[i].name = rspamd_mempool_strdup (task->task_pool, internet_address_get_name (addr)); + ar[i].name = rspamd_mempool_strdup (task->task_pool, + internet_address_get_name (addr)); if (ar[i].name != NULL && (c = strchr (ar[i].name, '@')) != NULL) { *c = '\0'; ar[i].addr = c + 1; @@ -1151,7 +1287,8 @@ rspamd_recipients_distance (struct rspamd_task *task, GList * args, void *unused while (cur) { addr = internet_address_list_get_address (cur); if (addr && internet_address_get_type (addr) == INTERNET_ADDRESS_NAME) { - ar[i].name = rspamd_mempool_strdup (task->task_pool, internet_address_get_addr (addr)); + ar[i].name = rspamd_mempool_strdup (task->task_pool, + internet_address_get_addr (addr)); if (ar[i].name != NULL && (c = strchr (ar[i].name, '@')) != NULL) { *c = '\0'; ar[i].addr = c + 1; @@ -1168,11 +1305,14 @@ rspamd_recipients_distance (struct rspamd_task *task, GList * args, void *unused /* Cycle all elements in array */ for (i = 0; i < num; i++) { for (j = i + 1; j < num; j++) { - if (ar[i].name && ar[j].name && g_ascii_strncasecmp (ar[i].name, ar[j].name, COMPARE_RCPT_LEN) == 0) { + if (ar[i].name && ar[j].name && + g_ascii_strncasecmp (ar[i].name, ar[j].name, + COMPARE_RCPT_LEN) == 0) { /* Common name part */ hits++; } - else if (ar[i].addr && ar[j].addr && g_ascii_strcasecmp (ar[i].addr, ar[j].addr) == 0) { + else if (ar[i].addr && ar[j].addr && + g_ascii_strcasecmp (ar[i].addr, ar[j].addr) == 0) { /* Common address part, but different name */ hits++; } @@ -1188,11 +1328,12 @@ rspamd_recipients_distance (struct rspamd_task *task, GList * args, void *unused } gboolean -rspamd_has_only_html_part (struct rspamd_task * task, GList * args, void *unused) +rspamd_has_only_html_part (struct rspamd_task * task, GList * args, + void *unused) { - struct mime_text_part *p; - GList *cur; - gboolean res = FALSE; + struct mime_text_part *p; + GList *cur; + gboolean res = FALSE; cur = g_list_first (task->text_parts); while (cur) { @@ -1210,30 +1351,34 @@ rspamd_has_only_html_part (struct rspamd_task * task, GList * args, void *unused return res; } -static gboolean +static gboolean is_recipient_list_sorted (const InternetAddressList * ia) { - const InternetAddressList *cur; - InternetAddress *addr; - gboolean res = TRUE; - struct addr_list current = { NULL, NULL }, previous = { - NULL, NULL}; + const InternetAddressList *cur; + InternetAddress *addr; + gboolean res = TRUE; + struct addr_list current = { NULL, NULL }, previous = { + NULL, NULL + }; #ifdef GMIME24 - gint num, i; + gint num, i; #endif /* Do not check to short address lists */ - if (internet_address_list_length ((InternetAddressList *)ia) < MIN_RCPT_TO_COMPARE) { + if (internet_address_list_length ((InternetAddressList *)ia) < + MIN_RCPT_TO_COMPARE) { return FALSE; } #ifdef GMIME24 num = internet_address_list_length ((InternetAddressList *)ia); cur = ia; - for (i = 0; i < num; i ++) { - addr = internet_address_list_get_address ((InternetAddressList *)cur, i); + for (i = 0; i < num; i++) { + addr = + internet_address_list_get_address ((InternetAddressList *)cur, i); current.addr = (gchar *)internet_address_get_name (addr); if (previous.addr != NULL) { - if (current.addr && g_ascii_strcasecmp (current.addr, previous.addr) < 0) { + if (current.addr && + g_ascii_strcasecmp (current.addr, previous.addr) < 0) { res = FALSE; break; } @@ -1247,7 +1392,8 @@ is_recipient_list_sorted (const InternetAddressList * ia) if (internet_address_get_type (addr) == INTERNET_ADDRESS_NAME) { current.addr = internet_address_get_addr (addr); if (previous.addr != NULL) { - if (current.addr && g_ascii_strcasecmp (current.addr, previous.addr) < 0) { + if (current.addr && + g_ascii_strcasecmp (current.addr, previous.addr) < 0) { res = FALSE; break; } @@ -1262,16 +1408,21 @@ is_recipient_list_sorted (const InternetAddressList * ia) } gboolean -rspamd_is_recipients_sorted (struct rspamd_task * task, GList * args, void *unused) +rspamd_is_recipients_sorted (struct rspamd_task * task, + GList * args, + void *unused) { /* Check all types of addresses */ - if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, GMIME_RECIPIENT_TYPE_TO)) == TRUE) { + if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, + GMIME_RECIPIENT_TYPE_TO)) == TRUE) { return TRUE; } - if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, GMIME_RECIPIENT_TYPE_BCC)) == TRUE) { + if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, + GMIME_RECIPIENT_TYPE_BCC)) == TRUE) { return TRUE; } - if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, GMIME_RECIPIENT_TYPE_CC)) == TRUE) { + if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, + GMIME_RECIPIENT_TYPE_CC)) == TRUE) { return TRUE; } @@ -1279,15 +1430,17 @@ rspamd_is_recipients_sorted (struct rspamd_task * task, GList * args, void *unus } gboolean -rspamd_compare_transfer_encoding (struct rspamd_task * task, GList * args, void *unused) +rspamd_compare_transfer_encoding (struct rspamd_task * task, + GList * args, + void *unused) { - GMimeObject *part; + GMimeObject *part; #ifndef GMIME24 - GMimePartEncodingType enc_req, part_enc; + GMimePartEncodingType enc_req, part_enc; #else - GMimeContentEncoding enc_req, part_enc; + GMimeContentEncoding enc_req, part_enc; #endif - struct expression_argument *arg; + struct expression_argument *arg; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1324,7 +1477,9 @@ rspamd_compare_transfer_encoding (struct rspamd_task * task, GList * args, void #endif - debug_task ("got encoding in part: %d and compare with %d", (gint)part_enc, (gint)enc_req); + debug_task ("got encoding in part: %d and compare with %d", + (gint)part_enc, + (gint)enc_req); #ifndef GMIME24 g_object_unref (part); #endif @@ -1342,9 +1497,9 @@ rspamd_compare_transfer_encoding (struct rspamd_task * task, GList * args, void gboolean rspamd_is_html_balanced (struct rspamd_task * task, GList * args, void *unused) { - struct mime_text_part *p; - GList *cur; - gboolean res = TRUE; + struct mime_text_part *p; + GList *cur; + gboolean res = TRUE; cur = g_list_first (task->text_parts); while (cur) { @@ -1366,15 +1521,15 @@ rspamd_is_html_balanced (struct rspamd_task * task, GList * args, void *unused) } struct html_callback_data { - struct html_tag *tag; - gboolean *res; + struct html_tag *tag; + gboolean *res; }; -static gboolean +static gboolean search_html_node_callback (GNode * node, gpointer data) { - struct html_callback_data *cd = data; - struct html_node *nd; + struct html_callback_data *cd = data; + struct html_node *nd; nd = node->data; if (nd) { @@ -1390,12 +1545,12 @@ search_html_node_callback (GNode * node, gpointer data) gboolean rspamd_has_html_tag (struct rspamd_task * task, GList * args, void *unused) { - struct mime_text_part *p; - GList *cur; - struct expression_argument *arg; - struct html_tag *tag; - gboolean res = FALSE; - struct html_callback_data cd; + struct mime_text_part *p; + GList *cur; + struct expression_argument *arg; + struct html_tag *tag; + gboolean res = FALSE; + struct html_callback_data cd; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1405,7 +1560,8 @@ rspamd_has_html_tag (struct rspamd_task * task, GList * args, void *unused) arg = get_function_arg (args->data, task, TRUE); tag = get_tag_by_name (arg->data); if (tag == NULL) { - msg_warn ("unknown tag type passed as argument: %s", (gchar *)arg->data); + msg_warn ("unknown tag type passed as argument: %s", + (gchar *)arg->data); return FALSE; } @@ -1416,7 +1572,12 @@ rspamd_has_html_tag (struct rspamd_task * task, GList * args, void *unused) while (cur && res == FALSE) { p = cur->data; if (!p->is_empty && p->is_html && p->html_nodes) { - g_node_traverse (p->html_nodes, G_PRE_ORDER, G_TRAVERSE_ALL, -1, search_html_node_callback, &cd); + g_node_traverse (p->html_nodes, + G_PRE_ORDER, + G_TRAVERSE_ALL, + -1, + search_html_node_callback, + &cd); } cur = g_list_next (cur); } @@ -1428,9 +1589,9 @@ rspamd_has_html_tag (struct rspamd_task * task, GList * args, void *unused) gboolean rspamd_has_fake_html (struct rspamd_task * task, GList * args, void *unused) { - struct mime_text_part *p; - GList *cur; - gboolean res = FALSE; + struct mime_text_part *p; + GList *cur; + gboolean res = FALSE; cur = g_list_first (task->text_parts); diff --git a/src/libmime/expressions.h b/src/libmime/expressions.h index 954cc74f7..1ba02d956 100644 --- a/src/libmime/expressions.h +++ b/src/libmime/expressions.h @@ -16,8 +16,8 @@ struct rspamd_regexp; * Rspamd expression function */ struct expression_function { - gchar *name; /**< name of function */ - GList *args; /**< its args */ + gchar *name; /**< name of function */ + GList *args; /**< its args */ }; /** @@ -28,30 +28,31 @@ struct expression_argument { EXPRESSION_ARGUMENT_NORMAL, EXPRESSION_ARGUMENT_BOOL, EXPRESSION_ARGUMENT_EXPR, - } type; /**< type of argument (text or other function) */ - void *data; /**< pointer to its data */ + } type; /**< type of argument (text or other function) */ + void *data; /**< pointer to its data */ }; -/** - * Logic expression +/** + * Logic expression */ struct expression { - enum { + enum { EXPR_REGEXP, - EXPR_OPERATION, - EXPR_FUNCTION, - EXPR_STR, + EXPR_OPERATION, + EXPR_FUNCTION, + EXPR_STR, EXPR_REGEXP_PARSED, - } type; /**< expression type */ + } type; /**< expression type */ union { void *operand; gchar operation; - } content; /**< union for storing operand or operation code */ - const gchar *orig; /**< original line */ - struct expression *next; /**< chain link */ + } content; /**< union for storing operand or operation code */ + const gchar *orig; /**< original line */ + struct expression *next; /**< chain link */ }; -typedef gboolean (*rspamd_internal_func_t)(struct rspamd_task *, GList *args, void *user_data); +typedef gboolean (*rspamd_internal_func_t)(struct rspamd_task *, GList *args, + void *user_data); /** * Parse regexp line to regexp structure @@ -59,7 +60,9 @@ typedef gboolean (*rspamd_internal_func_t)(struct rspamd_task *, GList *args, vo * @param line incoming line * @return regexp structure or NULL in case of error */ -struct rspamd_regexp* parse_regexp (rspamd_mempool_t *pool, const gchar *line, gboolean raw_mode); +struct rspamd_regexp * parse_regexp (rspamd_mempool_t *pool, + const gchar *line, + gboolean raw_mode); /** * Parse composites line to composites structure (eg. "SYMBOL1&SYMBOL2|!SYMBOL3") @@ -67,7 +70,7 @@ struct rspamd_regexp* parse_regexp (rspamd_mempool_t *pool, const gchar *line, g * @param line incoming line * @return expression structure or NULL in case of error */ -struct expression* parse_expression (rspamd_mempool_t *pool, gchar *line); +struct expression * parse_expression (rspamd_mempool_t *pool, gchar *line); /** * Call specified fucntion and return boolean result @@ -76,14 +79,18 @@ struct expression* parse_expression (rspamd_mempool_t *pool, gchar *line); * @param L lua specific state * @return TRUE or FALSE depending on function result */ -gboolean call_expression_function (struct expression_function *func, struct rspamd_task *task, lua_State *L); +gboolean call_expression_function (struct expression_function *func, + struct rspamd_task *task, + lua_State *L); /** * Register specified function to rspamd internal functions list * @param name name of function * @param func pointer to function */ -void register_expression_function (const gchar *name, rspamd_internal_func_t func, void *user_data); +void register_expression_function (const gchar *name, + rspamd_internal_func_t func, + void *user_data); /** * Add regexp to regexp cache @@ -111,7 +118,9 @@ void re_cache_del (const gchar *line, rspamd_mempool_t *pool); * @param pointer regexp data * @param result numeric result of this regexp */ -void task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 result); +void task_cache_add (struct rspamd_task *task, + struct rspamd_regexp *re, + gint32 result); /** * Check regexp in cache @@ -128,6 +137,8 @@ gint32 task_cache_check (struct rspamd_task *task, struct rspamd_regexp *re); * @param want_string return NULL if argument is not a string * @return expression argument structure or NULL if failed */ -struct expression_argument *get_function_arg (struct expression *expr, struct rspamd_task *task, gboolean want_string); +struct expression_argument * get_function_arg (struct expression *expr, + struct rspamd_task *task, + gboolean want_string); #endif diff --git a/src/libmime/filter.c b/src/libmime/filter.c index 2068c79e3..ead59c4bf 100644 --- a/src/libmime/filter.c +++ b/src/libmime/filter.c @@ -44,44 +44,56 @@ #ifndef PARAM_H_HAS_BITSET /* Bit map related macros. */ #define NBBY 8 /* number of bits in a byte */ -#define setbit(a,i) (((unsigned char *)(a))[(i)/NBBY] |= 1<<((i)%NBBY)) -#define clrbit(a,i) (((unsigned char *)(a))[(i)/NBBY] &= ~(1<<((i)%NBBY))) +#define setbit(a, \ + i) (((unsigned char *)(a))[(i) / NBBY] |= 1 << ((i) % NBBY)) +#define clrbit(a, \ + i) (((unsigned char *)(a))[(i) / NBBY] &= ~(1 << ((i) % NBBY))) #define isset(a,i) \ - (((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) + (((const unsigned char *)(a))[(i) / NBBY] & (1 << ((i) % NBBY))) #define isclr(a,i) \ - ((((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) == 0) + ((((const unsigned char *)(a))[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) #endif -#define BITSPERBYTE (8*sizeof (gchar)) -#define NBYTES(nbits) (((nbits) + BITSPERBYTE - 1) / BITSPERBYTE) +#define BITSPERBYTE (8 * sizeof (gchar)) +#define NBYTES(nbits) (((nbits) + BITSPERBYTE - 1) / BITSPERBYTE) -static inline GQuark +static inline GQuark filter_error_quark (void) { return g_quark_from_static_string ("g-filter-error-quark"); } static void -insert_metric_result (struct rspamd_task *task, struct metric *metric, const gchar *symbol, - double flag, GList * opts, gboolean single) +insert_metric_result (struct rspamd_task *task, + struct metric *metric, + const gchar *symbol, + double flag, + GList * opts, + gboolean single) { - struct metric_result *metric_res; - struct symbol *s; - gdouble *weight, w; + struct metric_result *metric_res; + struct symbol *s; + gdouble *weight, w; metric_res = g_hash_table_lookup (task->results, metric->name); if (metric_res == NULL) { /* Create new metric chain */ - metric_res = rspamd_mempool_alloc (task->task_pool, sizeof (struct metric_result)); - metric_res->symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); + metric_res = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct metric_result)); + metric_res->symbols = g_hash_table_new (rspamd_str_hash, + rspamd_str_equal); metric_res->checked = FALSE; - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_hash_table_unref, metric_res->symbols); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_hash_table_unref, + metric_res->symbols); metric_res->metric = metric; metric_res->grow_factor = 0; metric_res->score = 0; - g_hash_table_insert (task->results, (gpointer) metric->name, metric_res); + g_hash_table_insert (task->results, (gpointer) metric->name, + metric_res); } - + weight = g_hash_table_lookup (metric->symbols, symbol); if (weight == NULL) { w = 0.0; @@ -94,7 +106,7 @@ insert_metric_result (struct rspamd_task *task, struct metric *metric, const gch if ((s = g_hash_table_lookup (metric_res->symbols, symbol)) != NULL) { if (s->options && opts && opts != s->options) { /* Append new options */ - s->options = g_list_concat (s->options, g_list_copy(opts)); + s->options = g_list_concat (s->options, g_list_copy (opts)); /* * Note that there is no need to add new destructor of GList as elements of appended * GList are used directly, so just free initial GList @@ -102,7 +114,8 @@ insert_metric_result (struct rspamd_task *task, struct metric *metric, const gch } else if (opts) { s->options = g_list_copy (opts); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_list_free, s->options); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_list_free, s->options); } if (!single) { /* Handle grow factor */ @@ -139,7 +152,8 @@ insert_metric_result (struct rspamd_task *task, struct metric *metric, const gch if (opts) { s->options = g_list_copy (opts); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_list_free, s->options); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_list_free, s->options); } else { s->options = NULL; @@ -147,22 +161,30 @@ insert_metric_result (struct rspamd_task *task, struct metric *metric, const gch g_hash_table_insert (metric_res->symbols, (gpointer) symbol, s); } - debug_task ("symbol %s, score %.2f, metric %s, factor: %f", symbol, s->score, metric->name, w); - + debug_task ("symbol %s, score %.2f, metric %s, factor: %f", + symbol, + s->score, + metric->name, + w); + } #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) -static GStaticMutex result_mtx = G_STATIC_MUTEX_INIT; +static GStaticMutex result_mtx = G_STATIC_MUTEX_INIT; #else G_LOCK_DEFINE (result_mtx); #endif static void -insert_result_common (struct rspamd_task *task, const gchar *symbol, double flag, GList * opts, gboolean single) +insert_result_common (struct rspamd_task *task, + const gchar *symbol, + double flag, + GList * opts, + gboolean single) { - struct metric *metric; - struct cache_item *item; - GList *cur, *metric_list; + struct metric *metric; + struct cache_item *item; + GList *cur, *metric_list; /* Avoid concurrenting inserting of results */ #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) @@ -173,7 +195,7 @@ insert_result_common (struct rspamd_task *task, const gchar *symbol, double flag metric_list = g_hash_table_lookup (task->cfg->metrics_symbols, symbol); if (metric_list) { cur = metric_list; - + while (cur) { metric = cur->data; insert_metric_result (task, metric, symbol, flag, opts, single); @@ -182,7 +204,12 @@ insert_result_common (struct rspamd_task *task, const gchar *symbol, double flag } else { /* Insert symbol to default metric */ - insert_metric_result (task, task->cfg->default_metric, symbol, flag, opts, single); + insert_metric_result (task, + task->cfg->default_metric, + symbol, + flag, + opts, + single); } /* Process cache item */ @@ -206,21 +233,27 @@ insert_result_common (struct rspamd_task *task, const gchar *symbol, double flag /* Insert result that may be increased on next insertions */ void -insert_result (struct rspamd_task *task, const gchar *symbol, double flag, GList * opts) +insert_result (struct rspamd_task *task, + const gchar *symbol, + double flag, + GList * opts) { insert_result_common (task, symbol, flag, opts, task->cfg->one_shot_mode); } /* Insert result as a single option */ void -insert_result_single (struct rspamd_task *task, const gchar *symbol, double flag, GList * opts) +insert_result_single (struct rspamd_task *task, + const gchar *symbol, + double flag, + GList * opts) { insert_result_common (task, symbol, flag, opts, TRUE); } static gboolean check_metric_settings (struct rspamd_task *task, struct metric *metric, - double *score) + double *score) { const ucl_object_t *mobj, *reject; double val; @@ -243,11 +276,11 @@ check_metric_settings (struct rspamd_task *task, struct metric *metric, } /* Return true if metric has score that is more than spam score for it */ -static gboolean +static gboolean check_metric_is_spam (struct rspamd_task *task, struct metric *metric) { - struct metric_result *res; - double ms; + struct metric_result *res; + double ms; /* Avoid concurrency while checking results */ #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) @@ -280,9 +313,9 @@ check_metric_is_spam (struct rspamd_task *task, struct metric *metric) gint process_filters (struct rspamd_task *task) { - GList *cur; - struct metric *metric; - gpointer item = NULL; + GList *cur; + struct metric *metric; + gpointer item = NULL; /* Process metrics symbols */ while (call_symbol_callback (task, task->cfg->cache, &item)) { @@ -291,8 +324,8 @@ process_filters (struct rspamd_task *task) while (cur) { metric = cur->data; if (!task->pass_all_filters && - metric->actions[METRIC_ACTION_REJECT].score > 0 && - check_metric_is_spam (task, metric)) { + metric->actions[METRIC_ACTION_REJECT].score > 0 && + check_metric_is_spam (task, metric)) { task->state = WRITE_REPLY; return 1; } @@ -307,22 +340,22 @@ process_filters (struct rspamd_task *task) struct composites_data { - struct rspamd_task *task; - struct metric_result *metric_res; - GTree *symbols_to_remove; - guint8 *checked; + struct rspamd_task *task; + struct metric_result *metric_res; + GTree *symbols_to_remove; + guint8 *checked; }; struct symbol_remove_data { - struct symbol *ms; - gboolean remove_weight; - gboolean remove_symbol; + struct symbol *ms; + gboolean remove_weight; + gboolean remove_symbol; }; static gint remove_compare_data (gconstpointer a, gconstpointer b) { - const gchar *ca = a, *cb = b; + const gchar *ca = a, *cb = b; return strcmp (ca, cb); } @@ -330,16 +363,16 @@ remove_compare_data (gconstpointer a, gconstpointer b) static void composites_foreach_callback (gpointer key, gpointer value, void *data) { - struct composites_data *cd = (struct composites_data *)data; - struct rspamd_composite *composite = value, *ncomp; - struct expression *expr; - GQueue *stack; - GList *symbols = NULL, *s; - gsize cur, op1, op2; - gchar logbuf[256], *sym, *check_sym; - gint r; - struct symbol *ms; - struct symbol_remove_data *rd; + struct composites_data *cd = (struct composites_data *)data; + struct rspamd_composite *composite = value, *ncomp; + struct expression *expr; + GQueue *stack; + GList *symbols = NULL, *s; + gsize cur, op1, op2; + gchar logbuf[256], *sym, *check_sym; + gint r; + struct symbol *ms; + struct symbol_remove_data *rd; expr = composite->expr; @@ -355,16 +388,19 @@ composites_foreach_callback (gpointer key, gpointer value, void *data) /* Find corresponding symbol */ sym = expr->content.operand; if (*sym == '~' || *sym == '-') { - sym ++; + sym++; } if (g_hash_table_lookup (cd->metric_res->symbols, sym) == NULL) { cur = 0; - if ((ncomp = g_hash_table_lookup (cd->task->cfg->composite_symbols, sym)) != NULL) { + if ((ncomp = + g_hash_table_lookup (cd->task->cfg->composite_symbols, + sym)) != NULL) { /* Set checked for this symbol to avoid cyclic references */ if (isclr (cd->checked, ncomp->id)) { setbit (cd->checked, composite->id); composites_foreach_callback (sym, ncomp, cd); - if (g_hash_table_lookup (cd->metric_res->symbols, sym) != NULL) { + if (g_hash_table_lookup (cd->metric_res->symbols, + sym) != NULL) { cur = 1; } } @@ -412,7 +448,11 @@ composites_foreach_callback (gpointer key, gpointer value, void *data) if (op1) { /* Remove all symbols that are in composite symbol */ s = g_list_first (symbols); - r = rspamd_snprintf (logbuf, sizeof (logbuf), "<%s>, insert symbol %s instead of symbols: ", cd->task->message_id, key); + r = rspamd_snprintf (logbuf, + sizeof (logbuf), + "<%s>, insert symbol %s instead of symbols: ", + cd->task->message_id, + key); while (s) { sym = s->data; if (*sym == '~' || *sym == '-') { @@ -425,18 +465,23 @@ composites_foreach_callback (gpointer key, gpointer value, void *data) if (ms == NULL) { /* Try to process other composites */ - if ((ncomp = g_hash_table_lookup (cd->task->cfg->composite_symbols, check_sym)) != NULL) { + if ((ncomp = + g_hash_table_lookup (cd->task->cfg->composite_symbols, + check_sym)) != NULL) { /* Set checked for this symbol to avoid cyclic references */ if (isclr (cd->checked, ncomp->id)) { setbit (cd->checked, composite->id); composites_foreach_callback (check_sym, ncomp, cd); - ms = g_hash_table_lookup (cd->metric_res->symbols, check_sym); + ms = g_hash_table_lookup (cd->metric_res->symbols, + check_sym); } } } if (ms != NULL) { - rd = rspamd_mempool_alloc (cd->task->task_pool, sizeof (struct symbol_remove_data)); + rd = + rspamd_mempool_alloc (cd->task->task_pool, + sizeof (struct symbol_remove_data)); rd->ms = ms; if (G_UNLIKELY (*sym == '~')) { rd->remove_weight = FALSE; @@ -451,7 +496,9 @@ composites_foreach_callback (gpointer key, gpointer value, void *data) rd->remove_weight = TRUE; } if (!g_tree_lookup (cd->symbols_to_remove, rd)) { - g_tree_insert (cd->symbols_to_remove, (gpointer)ms->name, rd); + g_tree_insert (cd->symbols_to_remove, + (gpointer)ms->name, + rd); } } else { @@ -459,10 +506,16 @@ composites_foreach_callback (gpointer key, gpointer value, void *data) } if (s->next) { - r += rspamd_snprintf (logbuf + r, sizeof (logbuf) -r, "%s, ", s->data); + r += rspamd_snprintf (logbuf + r, + sizeof (logbuf) - r, + "%s, ", + s->data); } else { - r += rspamd_snprintf (logbuf + r, sizeof (logbuf) -r, "%s", s->data); + r += rspamd_snprintf (logbuf + r, + sizeof (logbuf) - r, + "%s", + s->data); } s = g_list_next (s); } @@ -479,12 +532,13 @@ composites_foreach_callback (gpointer key, gpointer value, void *data) return; } -static gboolean -check_autolearn (struct statfile_autolearn_params *params, struct rspamd_task *task) +static gboolean +check_autolearn (struct statfile_autolearn_params *params, + struct rspamd_task *task) { - gchar *metric_name = DEFAULT_METRIC; - struct metric_result *metric_res; - GList *cur; + gchar *metric_name = DEFAULT_METRIC; + struct metric_result *metric_res; + GList *cur; if (params->metric != NULL) { metric_name = (gchar *)params->metric; @@ -502,12 +556,16 @@ check_autolearn (struct statfile_autolearn_params *params, struct rspamd_task *t } else { /* Process score of metric */ - if ((params->threshold_min != 0 && metric_res->score > params->threshold_min) || (params->threshold_max != 0 && metric_res->score < params->threshold_max)) { + if ((params->threshold_min != 0 && metric_res->score > + params->threshold_min) || + (params->threshold_max != 0 && metric_res->score < + params->threshold_max)) { /* Now check for specific symbols */ if (params->symbols) { cur = params->symbols; while (cur) { - if (g_hash_table_lookup (metric_res->symbols, cur->data) == NULL) { + if (g_hash_table_lookup (metric_res->symbols, + cur->data) == NULL) { return FALSE; } cur = g_list_next (cur); @@ -522,28 +580,47 @@ check_autolearn (struct statfile_autolearn_params *params, struct rspamd_task *t } void -process_autolearn (struct rspamd_statfile_config *st, struct rspamd_task *task, GTree * tokens, struct classifier *classifier, gchar *filename, struct classifier_ctx *ctx) +process_autolearn (struct rspamd_statfile_config *st, + struct rspamd_task *task, + GTree * tokens, + struct classifier *classifier, + gchar *filename, + struct classifier_ctx *ctx) { - stat_file_t *statfile; - struct rspamd_statfile_config *unused; + stat_file_t *statfile; + struct rspamd_statfile_config *unused; if (check_autolearn (st->autolearn, task)) { if (tokens) { /* Take care of subject */ tokenize_subject (task, &tokens); - msg_info ("message with id <%s> autolearned statfile '%s'", task->message_id, filename); - + msg_info ("message with id <%s> autolearned statfile '%s'", + task->message_id, + filename); + /* Get or create statfile */ - statfile = get_statfile_by_symbol (task->worker->srv->statfile_pool, ctx->cfg, - st->symbol, &unused, TRUE); - + statfile = get_statfile_by_symbol (task->worker->srv->statfile_pool, + ctx->cfg, + st->symbol, + &unused, + TRUE); + if (statfile == NULL) { return; } - classifier->learn_func (ctx, task->worker->srv->statfile_pool, st->symbol, tokens, TRUE, NULL, 1., NULL); + classifier->learn_func (ctx, + task->worker->srv->statfile_pool, + st->symbol, + tokens, + TRUE, + NULL, + 1., + NULL); maybe_write_binlog (ctx->cfg, st, statfile, tokens); - statfile_pool_plan_invalidate (task->worker->srv->statfile_pool, DEFAULT_STATFILE_INVALIDATE_TIME, DEFAULT_STATFILE_INVALIDATE_JITTER); + statfile_pool_plan_invalidate (task->worker->srv->statfile_pool, + DEFAULT_STATFILE_INVALIDATE_TIME, + DEFAULT_STATFILE_INVALIDATE_JITTER); } } } @@ -551,8 +628,8 @@ process_autolearn (struct rspamd_statfile_config *st, struct rspamd_task *task, static gboolean composites_remove_symbols (gpointer key, gpointer value, gpointer data) { - struct composites_data *cd = data; - struct symbol_remove_data *rd = value; + struct composites_data *cd = data; + struct symbol_remove_data *rd = value; if (rd->remove_symbol) { g_hash_table_remove (cd->metric_res->symbols, key); @@ -567,17 +644,22 @@ composites_remove_symbols (gpointer key, gpointer value, gpointer data) static void composites_metric_callback (gpointer key, gpointer value, gpointer data) { - struct rspamd_task *task = (struct rspamd_task *)data; - struct composites_data *cd = rspamd_mempool_alloc (task->task_pool, sizeof (struct composites_data)); - struct metric_result *metric_res = (struct metric_result *)value; + struct rspamd_task *task = (struct rspamd_task *)data; + struct composites_data *cd = + rspamd_mempool_alloc (task->task_pool, sizeof (struct composites_data)); + struct metric_result *metric_res = (struct metric_result *)value; cd->task = task; cd->metric_res = (struct metric_result *)metric_res; cd->symbols_to_remove = g_tree_new (remove_compare_data); - cd->checked = rspamd_mempool_alloc0 (task->task_pool, NBYTES (g_hash_table_size (task->cfg->composite_symbols))); + cd->checked = + rspamd_mempool_alloc0 (task->task_pool, + NBYTES (g_hash_table_size (task->cfg->composite_symbols))); /* Process hash table */ - g_hash_table_foreach (task->cfg->composite_symbols, composites_foreach_callback, cd); + g_hash_table_foreach (task->cfg->composite_symbols, + composites_foreach_callback, + cd); /* Remove symbols that are in composites */ g_tree_foreach (cd->symbols_to_remove, composites_remove_symbols, cd); @@ -599,30 +681,32 @@ struct classifiers_cbdata { static void classifiers_callback (gpointer value, void *arg) { - struct classifiers_cbdata *cbdata = arg; - struct rspamd_task *task; - struct rspamd_classifier_config *cl = value; - struct classifier_ctx *ctx; - struct mime_text_part *text_part, *p1, *p2; - struct rspamd_statfile_config *st; - GTree *tokens = NULL; - GList *cur; - f_str_t c; - gchar *header = NULL; - gint *dist = NULL, diff; - gboolean is_twopart = FALSE; - + struct classifiers_cbdata *cbdata = arg; + struct rspamd_task *task; + struct rspamd_classifier_config *cl = value; + struct classifier_ctx *ctx; + struct mime_text_part *text_part, *p1, *p2; + struct rspamd_statfile_config *st; + GTree *tokens = NULL; + GList *cur; + f_str_t c; + gchar *header = NULL; + gint *dist = NULL, diff; + gboolean is_twopart = FALSE; + task = cbdata->task; if ((header = g_hash_table_lookup (cl->opts, "header")) != NULL) { - cur = message_get_header (task->task_pool, task->message, header, FALSE); + cur = + message_get_header (task->task_pool, task->message, header, FALSE); if (cur) { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, cur); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, cur); } } else { cur = g_list_first (task->text_parts); - dist = rspamd_mempool_get_variable (task->task_pool, "parts_distance"); + dist = rspamd_mempool_get_variable (task->task_pool, "parts_distance"); if (cur != NULL && cur->next != NULL && cur->next->next == NULL) { is_twopart = TRUE; } @@ -635,7 +719,8 @@ classifiers_callback (gpointer value, void *arg) c.len = strlen (cur->data); if (c.len > 0) { c.begin = cur->data; - if (!cl->tokenizer->tokenize_func (cl->tokenizer, task->task_pool, &c, &tokens, FALSE, FALSE, NULL)) { + if (!cl->tokenizer->tokenize_func (cl->tokenizer, + task->task_pool, &c, &tokens, FALSE, FALSE, NULL)) { msg_info ("cannot tokenize input"); return; } @@ -651,7 +736,9 @@ classifiers_callback (gpointer value, void *arg) /* Compare part's content */ if (*dist >= COMMON_PART_FACTOR) { - msg_info ("message <%s> has two common text parts, ignore the last one", task->message_id); + msg_info ( + "message <%s> has two common text parts, ignore the last one", + task->message_id); break; } } @@ -659,21 +746,25 @@ classifiers_callback (gpointer value, void *arg) p1 = cur->prev->data; p2 = text_part; if (p1->diff_str != NULL && p2->diff_str != NULL) { - diff = compare_diff_distance (p1->diff_str, p2->diff_str); + diff = + compare_diff_distance (p1->diff_str, p2->diff_str); } else { diff = fuzzy_compare_parts (p1, p2); } if (diff >= COMMON_PART_FACTOR) { - msg_info ("message <%s> has two common text parts, ignore the last one", task->message_id); + msg_info ( + "message <%s> has two common text parts, ignore the last one", + task->message_id); break; } } c.begin = (gchar *)text_part->content->data; c.len = text_part->content->len; /* Tree would be freed at task pool freeing */ - if (!cl->tokenizer->tokenize_func (cl->tokenizer, task->task_pool, &c, &tokens, - FALSE, text_part->is_utf, text_part->urls_offset)) { + if (!cl->tokenizer->tokenize_func (cl->tokenizer, + task->task_pool, &c, &tokens, + FALSE, text_part->is_utf, text_part->urls_offset)) { msg_info ("cannot tokenize input"); return; } @@ -692,12 +783,20 @@ classifiers_callback (gpointer value, void *arg) if (cbdata->nL != NULL) { rspamd_mutex_lock (cbdata->nL->m); - cl->classifier->classify_func (ctx, task->worker->srv->statfile_pool, tokens, task, cbdata->nL->L); + cl->classifier->classify_func (ctx, + task->worker->srv->statfile_pool, + tokens, + task, + cbdata->nL->L); rspamd_mutex_unlock (cbdata->nL->m); } else { /* Non-threaded case */ - cl->classifier->classify_func (ctx, task->worker->srv->statfile_pool, tokens, task, task->cfg->lua_state); + cl->classifier->classify_func (ctx, + task->worker->srv->statfile_pool, + tokens, + task, + task->cfg->lua_state); } /* Autolearning */ @@ -707,7 +806,12 @@ classifiers_callback (gpointer value, void *arg) if (st->autolearn) { if (check_autolearn (st->autolearn, task)) { /* Process autolearn */ - process_autolearn (st, task, tokens, cl->classifier, st->path, ctx); + process_autolearn (st, + task, + tokens, + cl->classifier, + st->path, + ctx); } } cur = g_list_next (cur); @@ -718,7 +822,7 @@ classifiers_callback (gpointer value, void *arg) void process_statfiles (struct rspamd_task *task) { - struct classifiers_cbdata cbdata; + struct classifiers_cbdata cbdata; if (task->is_skipped) { return; @@ -726,7 +830,8 @@ process_statfiles (struct rspamd_task *task) if (task->tokens == NULL) { task->tokens = g_hash_table_new (g_direct_hash, g_direct_equal); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_hash_table_unref, task->tokens); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_hash_table_unref, task->tokens); } cbdata.task = task; cbdata.nL = NULL; @@ -739,9 +844,9 @@ process_statfiles (struct rspamd_task *task) void process_statfiles_threaded (gpointer data, gpointer user_data) { - struct rspamd_task *task = (struct rspamd_task *)data; - struct lua_locked_state *nL = user_data; - struct classifiers_cbdata cbdata; + struct rspamd_task *task = (struct rspamd_task *)data; + struct lua_locked_state *nL = user_data; + struct classifiers_cbdata cbdata; if (task->is_skipped) { remove_async_thread (task->s); @@ -750,7 +855,8 @@ process_statfiles_threaded (gpointer data, gpointer user_data) if (task->tokens == NULL) { task->tokens = g_hash_table_new (g_direct_hash, g_direct_equal); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_hash_table_unref, task->tokens); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_hash_table_unref, task->tokens); } cbdata.task = task; @@ -760,18 +866,22 @@ process_statfiles_threaded (gpointer data, gpointer user_data) } static void -insert_metric_header (gpointer metric_name, gpointer metric_value, gpointer data) +insert_metric_header (gpointer metric_name, gpointer metric_value, + gpointer data) { #ifndef GLIB_HASH_COMPAT - struct rspamd_task *task = (struct rspamd_task *)data; - gint r = 0; + struct rspamd_task *task = (struct rspamd_task *)data; + gint r = 0; /* Try to be rfc2822 compatible and avoid long headers with folding */ - gchar header_name[128], outbuf[1000]; - GList *symbols = NULL, *cur; - struct metric_result *metric_res = (struct metric_result *)metric_value; - double ms; + gchar header_name[128], outbuf[1000]; + GList *symbols = NULL, *cur; + struct metric_result *metric_res = (struct metric_result *)metric_value; + double ms; - rspamd_snprintf (header_name, sizeof (header_name), "X-Spam-%s", metric_res->metric->name); + rspamd_snprintf (header_name, + sizeof (header_name), + "X-Spam-%s", + metric_res->metric->name); if (!check_metric_settings (task, metric_res->metric, &ms)) { ms = metric_res->metric->actions[METRIC_ACTION_REJECT].score; @@ -800,7 +910,8 @@ insert_metric_header (gpointer metric_name, gpointer metric_value, gpointer data } g_list_free (symbols); #ifdef GMIME24 - g_mime_object_append_header (GMIME_OBJECT (task->message), header_name, outbuf); + g_mime_object_append_header (GMIME_OBJECT ( + task->message), header_name, outbuf); #else g_mime_message_add_header (task->message, header_name, outbuf); #endif @@ -820,13 +931,16 @@ check_action_str (const gchar *data, gint *result) if (g_ascii_strncasecmp (data, "reject", sizeof ("reject") - 1) == 0) { *result = METRIC_ACTION_REJECT; } - else if (g_ascii_strncasecmp (data, "greylist", sizeof ("greylist") - 1) == 0) { + else if (g_ascii_strncasecmp (data, "greylist", + sizeof ("greylist") - 1) == 0) { *result = METRIC_ACTION_GREYLIST; } - else if (g_ascii_strncasecmp (data, "add_header", sizeof ("add_header") - 1) == 0) { + else if (g_ascii_strncasecmp (data, "add_header", sizeof ("add_header") - + 1) == 0) { *result = METRIC_ACTION_ADD_HEADER; } - else if (g_ascii_strncasecmp (data, "rewrite_subject", sizeof ("rewrite_subject") - 1) == 0) { + else if (g_ascii_strncasecmp (data, "rewrite_subject", + sizeof ("rewrite_subject") - 1) == 0) { *result = METRIC_ACTION_REWRITE_SUBJECT; } else { @@ -861,9 +975,9 @@ str_action_metric (enum rspamd_metric_action action) gint check_metric_action (double score, double required_score, struct metric *metric) { - struct metric_action *action, *selected_action = NULL; - double max_score = 0; - int i; + struct metric_action *action, *selected_action = NULL; + double max_score = 0; + int i; if (score >= required_score) { return METRIC_ACTION_REJECT; @@ -872,7 +986,7 @@ check_metric_action (double score, double required_score, struct metric *metric) return METRIC_ACTION_NOACTION; } else { - for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { + for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) { action = &metric->actions[i]; if (action->score < 0) { continue; @@ -894,24 +1008,26 @@ check_metric_action (double score, double required_score, struct metric *metric) gboolean learn_task (const gchar *statfile, struct rspamd_task *task, GError **err) { - GList *cur, *ex; - struct rspamd_classifier_config *cl; - struct classifier_ctx *cls_ctx; - gchar *s; - f_str_t c; - GTree *tokens = NULL; - struct rspamd_statfile_config *st; - stat_file_t *stf; - gdouble sum; - struct mime_text_part *part, *p1, *p2; - gboolean is_utf = FALSE, is_twopart = FALSE; - gint diff; + GList *cur, *ex; + struct rspamd_classifier_config *cl; + struct classifier_ctx *cls_ctx; + gchar *s; + f_str_t c; + GTree *tokens = NULL; + struct rspamd_statfile_config *st; + stat_file_t *stf; + gdouble sum; + struct mime_text_part *part, *p1, *p2; + gboolean is_utf = FALSE, is_twopart = FALSE; + gint diff; /* Load classifier by symbol */ cl = g_hash_table_lookup (task->cfg->classifiers_symbols, statfile); if (cl == NULL) { - g_set_error (err, filter_error_quark(), 1, "Statfile %s is not configured in any classifier", statfile); + g_set_error (err, + filter_error_quark (), 1, "Statfile %s is not configured in any classifier", + statfile); return FALSE; } @@ -919,7 +1035,8 @@ learn_task (const gchar *statfile, struct rspamd_task *task, GError **err) if ((s = g_hash_table_lookup (cl->opts, "header")) != NULL) { cur = message_get_header (task->task_pool, task->message, s, FALSE); if (cur) { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, cur); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, cur); } } else { @@ -959,7 +1076,9 @@ learn_task (const gchar *statfile, struct rspamd_task *task, GError **err) diff = fuzzy_compare_parts (p1, p2); } if (diff >= COMMON_PART_FACTOR) { - msg_info ("message <%s> has two common text parts, ignore the last one", task->message_id); + msg_info ( + "message <%s> has two common text parts, ignore the last one", + task->message_id); break; } } @@ -968,7 +1087,8 @@ learn_task (const gchar *statfile, struct rspamd_task *task, GError **err) if (!cl->tokenizer->tokenize_func ( cl->tokenizer, task->task_pool, &c, &tokens, FALSE, is_utf, ex)) { - g_set_error (err, filter_error_quark(), 2, "Cannot tokenize message"); + g_set_error (err, + filter_error_quark (), 2, "Cannot tokenize message"); return FALSE; } cur = g_list_next (cur); @@ -976,8 +1096,10 @@ learn_task (const gchar *statfile, struct rspamd_task *task, GError **err) /* Handle messages without text */ if (tokens == NULL) { - g_set_error (err, filter_error_quark(), 3, "Cannot tokenize message, no text data"); - msg_info ("learn failed for message <%s>, no tokens to extract", task->message_id); + g_set_error (err, + filter_error_quark (), 3, "Cannot tokenize message, no text data"); + msg_info ("learn failed for message <%s>, no tokens to extract", + task->message_id); return FALSE; } @@ -986,7 +1108,7 @@ learn_task (const gchar *statfile, struct rspamd_task *task, GError **err) /* Init classifier */ cls_ctx = cl->classifier->init_func ( - task->task_pool, cl); + task->task_pool, cl); /* Get or create statfile */ stf = get_statfile_by_symbol (task->worker->srv->statfile_pool, cl, statfile, &st, TRUE); @@ -997,12 +1119,17 @@ learn_task (const gchar *statfile, struct rspamd_task *task, GError **err) statfile, tokens, TRUE, &sum, 1.0, err)) { if (*err) { - msg_info ("learn failed for message <%s>, learn error: %s", task->message_id, (*err)->message); + msg_info ("learn failed for message <%s>, learn error: %s", + task->message_id, + (*err)->message); return FALSE; } else { - g_set_error (err, filter_error_quark(), 4, "Learn failed, unknown learn classifier error"); - msg_info ("learn failed for message <%s>, unknown learn error", task->message_id); + g_set_error (err, + filter_error_quark (), 4, + "Learn failed, unknown learn classifier error"); + msg_info ("learn failed for message <%s>, unknown learn error", + task->message_id); return FALSE; } } @@ -1010,25 +1137,31 @@ learn_task (const gchar *statfile, struct rspamd_task *task, GError **err) task->worker->srv->stat->messages_learned++; maybe_write_binlog (cl, st, stf, tokens); - msg_info ("learn success for message <%s>, for statfile: %s, sum weight: %.2f", - task->message_id, statfile, sum); + msg_info ( + "learn success for message <%s>, for statfile: %s, sum weight: %.2f", + task->message_id, + statfile, + sum); statfile_pool_plan_invalidate (task->worker->srv->statfile_pool, - DEFAULT_STATFILE_INVALIDATE_TIME, - DEFAULT_STATFILE_INVALIDATE_JITTER); + DEFAULT_STATFILE_INVALIDATE_TIME, + DEFAULT_STATFILE_INVALIDATE_JITTER); return TRUE; } gboolean -learn_task_spam (struct rspamd_classifier_config *cl, struct rspamd_task *task, gboolean is_spam, GError **err) +learn_task_spam (struct rspamd_classifier_config *cl, + struct rspamd_task *task, + gboolean is_spam, + GError **err) { - GList *cur, *ex; - struct classifier_ctx *cls_ctx; - f_str_t c; - GTree *tokens = NULL; - struct mime_text_part *part, *p1, *p2; - gboolean is_utf = FALSE, is_twopart = FALSE; - gint diff; + GList *cur, *ex; + struct classifier_ctx *cls_ctx; + f_str_t c; + GTree *tokens = NULL; + struct mime_text_part *part, *p1, *p2; + gboolean is_utf = FALSE, is_twopart = FALSE; + gint diff; cur = g_list_first (task->text_parts); if (cur != NULL && cur->next != NULL && cur->next->next == NULL) { @@ -1061,7 +1194,9 @@ learn_task_spam (struct rspamd_classifier_config *cl, struct rspamd_task *task, diff = fuzzy_compare_parts (p1, p2); } if (diff >= COMMON_PART_FACTOR) { - msg_info ("message <%s> has two common text parts, ignore the last one", task->message_id); + msg_info ( + "message <%s> has two common text parts, ignore the last one", + task->message_id); break; } } @@ -1069,7 +1204,8 @@ learn_task_spam (struct rspamd_classifier_config *cl, struct rspamd_task *task, if (!cl->tokenizer->tokenize_func ( cl->tokenizer, task->task_pool, &c, &tokens, FALSE, is_utf, ex)) { - g_set_error (err, filter_error_quark(), 2, "Cannot tokenize message"); + g_set_error (err, + filter_error_quark (), 2, "Cannot tokenize message"); return FALSE; } cur = g_list_next (cur); @@ -1077,8 +1213,10 @@ learn_task_spam (struct rspamd_classifier_config *cl, struct rspamd_task *task, /* Handle messages without text */ if (tokens == NULL) { - g_set_error (err, filter_error_quark(), 3, "Cannot tokenize message, no text data"); - msg_info ("learn failed for message <%s>, no tokens to extract", task->message_id); + g_set_error (err, + filter_error_quark (), 3, "Cannot tokenize message, no text data"); + msg_info ("learn failed for message <%s>, no tokens to extract", + task->message_id); return FALSE; } @@ -1087,18 +1225,23 @@ learn_task_spam (struct rspamd_classifier_config *cl, struct rspamd_task *task, /* Init classifier */ cls_ctx = cl->classifier->init_func ( - task->task_pool, cl); + task->task_pool, cl); /* Learn */ if (!cl->classifier->learn_spam_func ( cls_ctx, task->worker->srv->statfile_pool, tokens, task, is_spam, task->cfg->lua_state, err)) { if (*err) { - msg_info ("learn failed for message <%s>, learn error: %s", task->message_id, (*err)->message); + msg_info ("learn failed for message <%s>, learn error: %s", + task->message_id, + (*err)->message); return FALSE; } else { - g_set_error (err, filter_error_quark(), 4, "Learn failed, unknown learn classifier error"); - msg_info ("learn failed for message <%s>, unknown learn error", task->message_id); + g_set_error (err, + filter_error_quark (), 4, + "Learn failed, unknown learn classifier error"); + msg_info ("learn failed for message <%s>, unknown learn error", + task->message_id); return FALSE; } } @@ -1106,14 +1249,14 @@ learn_task_spam (struct rspamd_classifier_config *cl, struct rspamd_task *task, task->worker->srv->stat->messages_learned++; msg_info ("learn success for message <%s>", - task->message_id); + task->message_id); statfile_pool_plan_invalidate (task->worker->srv->statfile_pool, - DEFAULT_STATFILE_INVALIDATE_TIME, - DEFAULT_STATFILE_INVALIDATE_JITTER); + DEFAULT_STATFILE_INVALIDATE_TIME, + DEFAULT_STATFILE_INVALIDATE_JITTER); return TRUE; } -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/libmime/filter.h b/src/libmime/filter.h index 2891ebd00..f0a343483 100644 --- a/src/libmime/filter.h +++ b/src/libmime/filter.h @@ -14,7 +14,8 @@ struct rspamd_task; struct rspamd_settings; struct rspamd_classifier_config; -typedef double (*metric_cons_func)(struct rspamd_task *task, const gchar *metric_name, const gchar *func_name); +typedef double (*metric_cons_func)(struct rspamd_task *task, + const gchar *metric_name, const gchar *func_name); typedef void (*filter_func)(struct rspamd_task *task); enum filter_type { C_FILTER, PERL_FILTER }; @@ -23,17 +24,17 @@ enum filter_type { C_FILTER, PERL_FILTER }; * Filter structure */ struct filter { - gchar *func_name; /**< function name */ - enum filter_type type; /**< filter type (c or perl) */ - module_t *module; + gchar *func_name; /**< function name */ + enum filter_type type; /**< filter type (c or perl) */ + module_t *module; }; /** * Rspamd symbol */ struct symbol { - double score; /**< symbol's score */ - GList *options; /**< list of symbol's options */ + double score; /**< symbol's score */ + GList *options; /**< list of symbol's options */ const gchar *name; }; @@ -46,25 +47,25 @@ struct metric_action { * Common definition of metric */ struct metric { - const gchar *name; /**< name of metric */ - gchar *func_name; /**< name of consolidation function */ - metric_cons_func func; /**< c consolidation function */ - double grow_factor; /**< grow factor for metric */ - GHashTable *symbols; /**< weights of symbols in metric */ - GHashTable *descriptions; /**< descriptions of symbols in metric */ + const gchar *name; /**< name of metric */ + gchar *func_name; /**< name of consolidation function */ + metric_cons_func func; /**< c consolidation function */ + double grow_factor; /**< grow factor for metric */ + GHashTable *symbols; /**< weights of symbols in metric */ + GHashTable *descriptions; /**< descriptions of symbols in metric */ struct metric_action actions[METRIC_ACTION_MAX]; /**< all actions of the metric */ - gchar *subject; /**< subject rewrite string */ + gchar *subject; /**< subject rewrite string */ }; /** * Result of metric processing */ struct metric_result { - struct metric *metric; /**< pointer to metric structure */ - double score; /**< total score */ - GHashTable *symbols; /**< symbols of metric */ - gboolean checked; /**< whether metric result is consolidated */ - double grow_factor; /**< current grow factor */ + struct metric *metric; /**< pointer to metric structure */ + double score; /**< total score */ + GHashTable *symbols; /**< symbols of metric */ + gboolean checked; /**< whether metric result is consolidated */ + double grow_factor; /**< current grow factor */ }; /** @@ -102,7 +103,10 @@ void process_statfiles_threaded (gpointer data, gpointer user_data); * @param flag numeric weight for symbol * @param opts list of symbol's options */ -void insert_result (struct rspamd_task *task, const gchar *symbol, double flag, GList *opts); +void insert_result (struct rspamd_task *task, + const gchar *symbol, + double flag, + GList *opts); /** * Insert a single result to task @@ -112,7 +116,10 @@ void insert_result (struct rspamd_task *task, const gchar *symbol, double flag, * @param flag numeric weight for symbol * @param opts list of symbol's options */ -void insert_result_single (struct rspamd_task *task, const gchar *symbol, double flag, GList *opts); +void insert_result_single (struct rspamd_task *task, + const gchar *symbol, + double flag, + GList *opts); /** * Process all results and form composite metrics from existent metrics as it is defined in config @@ -121,13 +128,15 @@ void insert_result_single (struct rspamd_task *task, const gchar *symbol, double void make_composites (struct rspamd_task *task); /** - * Default consolidation function for metric, it get all symbols and multiply symbol + * Default consolidation function for metric, it get all symbols and multiply symbol * weight by some factor that is specified in config. Default factor is 1. * @param task worker's task that present message from user * @param metric_name name of metric * @return result metric weight */ -double factor_consolidation_func (struct rspamd_task *task, const gchar *metric_name, const gchar *unused); +double factor_consolidation_func (struct rspamd_task *task, + const gchar *metric_name, + const gchar *unused); /* * Learn specified statfile with message in a task @@ -136,7 +145,9 @@ double factor_consolidation_func (struct rspamd_task *task, const gchar *metric_ * @param err pointer to GError * @return true if learn succeed */ -gboolean learn_task (const gchar *statfile, struct rspamd_task *task, GError **err); +gboolean learn_task (const gchar *statfile, + struct rspamd_task *task, + GError **err); /* * Learn specified statfile with message in a task @@ -145,7 +156,10 @@ gboolean learn_task (const gchar *statfile, struct rspamd_task *task, GError **e * @param err pointer to GError * @return true if learn succeed */ -gboolean learn_task_spam (struct rspamd_classifier_config *cl, struct rspamd_task *task, gboolean is_spam, GError **err); +gboolean learn_task_spam (struct rspamd_classifier_config *cl, + struct rspamd_task *task, + gboolean is_spam, + GError **err); /* * Get action from a string @@ -155,11 +169,13 @@ gboolean check_action_str (const gchar *data, gint *result); /* * Return textual representation of action enumeration */ -const gchar *str_action_metric (enum rspamd_metric_action action); +const gchar * str_action_metric (enum rspamd_metric_action action); /* * Get action for specific metric */ -gint check_metric_action (double score, double required_score, struct metric *metric); +gint check_metric_action (double score, + double required_score, + struct metric *metric); #endif diff --git a/src/libmime/images.c b/src/libmime/images.c index ff07bbd72..3b2ceecd1 100644 --- a/src/libmime/images.c +++ b/src/libmime/images.c @@ -32,19 +32,20 @@ static const guint8 jpg_sig2[] = {'J', 'F', 'I', 'F'}; static const guint8 gif_signature[] = {'G', 'I', 'F', '8'}; static const guint8 bmp_signature[] = {'B', 'M'}; -static void process_image (struct rspamd_task *task, struct mime_part *part); +static void process_image (struct rspamd_task *task, struct mime_part *part); void process_images (struct rspamd_task *task) { - GList *cur; - struct mime_part *part; + GList *cur; + struct mime_part *part; cur = task->parts; while (cur) { part = cur->data; - if (g_mime_content_type_is_type (part->type, "image", "*") && part->content->len > 0) { + if (g_mime_content_type_is_type (part->type, "image", + "*") && part->content->len > 0) { process_image (task, part); } cur = g_list_next (cur); @@ -85,9 +86,9 @@ detect_image_type (GByteArray *data) static struct rspamd_image * process_png_image (struct rspamd_task *task, GByteArray *data) { - struct rspamd_image *img; - guint32 t; - guint8 *p; + struct rspamd_image *img; + guint32 t; + guint8 *p; if (data->len < 24) { msg_info ("bad png detected (maybe striped): <%s>", task->message_id); @@ -119,10 +120,10 @@ process_png_image (struct rspamd_task *task, GByteArray *data) static struct rspamd_image * process_jpg_image (struct rspamd_task *task, GByteArray *data) { - guint8 *p; - guint16 t; - gsize remain; - struct rspamd_image *img; + guint8 *p; + guint16 t; + gsize remain; + struct rspamd_image *img; img = rspamd_mempool_alloc (task->task_pool, sizeof (struct rspamd_image)); img->type = IMAGE_TYPE_JPG; @@ -131,15 +132,16 @@ process_jpg_image (struct rspamd_task *task, GByteArray *data) p = data->data; remain = data->len; /* In jpeg we should find any data stream (ff c0 .. ff c3) and extract its height and width */ - while (remain --) { - if (*p == 0xFF && remain > 8 && (*(p + 1) >= 0xC0 && *(p + 1) <= 0xC3)) { + while (remain--) { + if (*p == 0xFF && remain > 8 && + (*(p + 1) >= 0xC0 && *(p + 1) <= 0xC3)) { memcpy (&t, p + 5, sizeof (guint16)); img->height = ntohs (t); memcpy (&t, p + 7, sizeof (guint16)); img->width = ntohs (t); return img; } - p ++; + p++; } return NULL; @@ -148,9 +150,9 @@ process_jpg_image (struct rspamd_task *task, GByteArray *data) static struct rspamd_image * process_gif_image (struct rspamd_task *task, GByteArray *data) { - struct rspamd_image *img; - guint8 *p; - guint16 t; + struct rspamd_image *img; + guint8 *p; + guint16 t; if (data->len < 10) { msg_info ("bad gif detected (maybe striped): <%s>", task->message_id); @@ -162,7 +164,7 @@ process_gif_image (struct rspamd_task *task, GByteArray *data) img->data = data; p = data->data + 6; - memcpy (&t, p, sizeof (guint16)); + memcpy (&t, p, sizeof (guint16)); img->width = GUINT16_FROM_LE (t); memcpy (&t, p + 2, sizeof (guint16)); img->height = GUINT16_FROM_LE (t); @@ -173,9 +175,9 @@ process_gif_image (struct rspamd_task *task, GByteArray *data) static struct rspamd_image * process_bmp_image (struct rspamd_task *task, GByteArray *data) { - struct rspamd_image *img; - gint32 t; - guint8 *p; + struct rspamd_image *img; + gint32 t; + guint8 *p; @@ -188,7 +190,7 @@ process_bmp_image (struct rspamd_task *task, GByteArray *data) img->type = IMAGE_TYPE_BMP; img->data = data; p = data->data + 18; - memcpy (&t, p, sizeof (gint32)); + memcpy (&t, p, sizeof (gint32)); img->width = abs (GINT32_FROM_LE (t)); memcpy (&t, p + 4, sizeof (gint32)); img->height = abs (GINT32_FROM_LE (t)); @@ -199,8 +201,8 @@ process_bmp_image (struct rspamd_task *task, GByteArray *data) static void process_image (struct rspamd_task *task, struct mime_part *part) { - enum known_image_types type; - struct rspamd_image *img = NULL; + enum known_image_types type; + struct rspamd_image *img = NULL; if ((type = detect_image_type (part->content)) != IMAGE_TYPE_UNKNOWN) { switch (type) { case IMAGE_TYPE_PNG: @@ -223,9 +225,9 @@ process_image (struct rspamd_task *task, struct mime_part *part) if (img != NULL) { debug_task ("detected %s image of size %ud x %ud in message <%s>", - image_type_str (img->type), - img->width, img->height, - task->message_id); + image_type_str (img->type), + img->width, img->height, + task->message_id); img->filename = part->filename; task->images = g_list_prepend (task->images, img); } diff --git a/src/libmime/images.h b/src/libmime/images.h index c43941ebc..5648f030f 100644 --- a/src/libmime/images.h +++ b/src/libmime/images.h @@ -28,6 +28,6 @@ void process_images (struct rspamd_task *task); /* * Get textual representation of an image's type */ -const gchar *image_type_str (enum known_image_types type); +const gchar * image_type_str (enum known_image_types type); #endif /* IMAGES_H_ */ diff --git a/src/libmime/message.c b/src/libmime/message.c index 4567869e9..e045e9650 100644 --- a/src/libmime/message.c +++ b/src/libmime/message.c @@ -33,15 +33,19 @@ #define RECURSION_LIMIT 30 #define UTF8_CHARSET "UTF-8" -GByteArray * -strip_html_tags (struct rspamd_task *task, rspamd_mempool_t * pool, struct mime_text_part *part, GByteArray * src, gint *stateptr) +GByteArray * +strip_html_tags (struct rspamd_task *task, + rspamd_mempool_t * pool, + struct mime_text_part *part, + GByteArray * src, + gint *stateptr) { - uint8_t *p, *rp, *tbegin = NULL, *end, c, lc; - gint br, i = 0, depth = 0, in_q = 0; - gint state = 0; - GByteArray *buf; - GNode *level_ptr = NULL; - gboolean erase = FALSE; + uint8_t *p, *rp, *tbegin = NULL, *end, c, lc; + gint br, i = 0, depth = 0, in_q = 0; + gint state = 0; + GByteArray *buf; + GNode *level_ptr = NULL; + gboolean erase = FALSE; if (stateptr) state = *stateptr; @@ -71,11 +75,11 @@ strip_html_tags (struct rspamd_task *task, rspamd_mempool_t * pool, struct mime_ } else if (state == 1) { /* Opening bracket without closing one */ - p --; + p--; while (g_ascii_isspace (*p) && p > src->data) { - p --; + p--; } - p ++; + p++; goto unbreak_tag; } break; @@ -115,13 +119,19 @@ strip_html_tags (struct rspamd_task *task, rspamd_mempool_t * pool, struct mime_ } unbreak_tag: switch (state) { - case 1: /* HTML/XML */ + case 1: /* HTML/XML */ lc = '>'; in_q = state = 0; - erase = !add_html_node (task, pool, part, tbegin, p - tbegin, end - tbegin, &level_ptr); + erase = !add_html_node (task, + pool, + part, + tbegin, + p - tbegin, + end - tbegin, + &level_ptr); break; - case 2: /* PHP */ + case 2: /* PHP */ if (!br && lc != '\"' && *(p - 1) == '?') { in_q = state = 0; } @@ -131,7 +141,7 @@ unbreak_tag: in_q = state = 0; break; - case 4: /* JavaScript/CSS/etc... */ + case 4: /* JavaScript/CSS/etc... */ if (p >= src->data + 2 && *(p - 1) == '-' && *(p - 2) == '-') { in_q = state = 0; } @@ -158,7 +168,8 @@ unbreak_tag: else if (state == 0 && !erase) { *(rp++) = c; } - if (state && p != src->data && *(p - 1) != '\\' && (!in_q || *p == in_q)) { + if (state && p != src->data && *(p - 1) != '\\' && + (!in_q || *p == in_q)) { if (in_q) { in_q = 0; } @@ -182,7 +193,8 @@ unbreak_tag: break; case '-': - if (state == 3 && p >= src->data + 2 && *(p - 1) == '-' && *(p - 2) == '!') { + if (state == 3 && p >= src->data + 2 && *(p - 1) == '-' && + *(p - 2) == '!') { state = 4; } else { @@ -204,11 +216,14 @@ unbreak_tag: if (state == 3 && p > src->data + 6 && g_ascii_tolower (*(p - 1)) == 'p' && g_ascii_tolower (*(p - 2)) == 'y' - && g_ascii_tolower (*(p - 3)) == 't' && g_ascii_tolower (*(p - 4)) == 'c' && g_ascii_tolower (*(p - 5)) == 'o' && g_ascii_tolower (*(p - 6)) == 'd') { + && g_ascii_tolower (*(p - 3)) == 't' && + g_ascii_tolower (*(p - 4)) == 'c' && + g_ascii_tolower (*(p - 5)) == 'o' && + g_ascii_tolower (*(p - 6)) == 'd') { state = 1; break; } - /* fall-through */ + /* fall-through */ case 'l': @@ -216,14 +231,15 @@ unbreak_tag: * state == 2 (PHP). Switch back to HTML. */ - if (state == 2 && p > src->data + 2 && *(p - 1) == 'm' && *(p - 2) == 'x') { + if (state == 2 && p > src->data + 2 && *(p - 1) == 'm' && + *(p - 2) == 'x') { state = 1; break; } - /* fall-through */ + /* fall-through */ default: - reg_char: +reg_char: if (state == 0 && !erase) { *(rp++) = c; } @@ -252,9 +268,11 @@ unbreak_tag: } static void -parse_qmail_recv (rspamd_mempool_t * pool, gchar *line, struct received_header *r) +parse_qmail_recv (rspamd_mempool_t * pool, + gchar *line, + struct received_header *r) { - gchar *s, *p, t; + gchar *s, *p, t; /* We are interested only with received from network headers */ if ((p = strstr (line, "from network")) == NULL) { @@ -269,7 +287,7 @@ parse_qmail_recv (rspamd_mempool_t * pool, gchar *line, struct received_header * /* format is ip/host */ s = p; if (*p) { - while (g_ascii_isdigit (*++p) || *p == '.'); + while (g_ascii_isdigit (*++p) || *p == '.') ; if (*p != '/') { r->is_error = 1; return; @@ -280,7 +298,8 @@ parse_qmail_recv (rspamd_mempool_t * pool, gchar *line, struct received_header * *p = '/'; /* Now try to parse hostname */ s = ++p; - while (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == '_') { + while (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == + '_') { p++; } t = *p; @@ -292,9 +311,11 @@ parse_qmail_recv (rspamd_mempool_t * pool, gchar *line, struct received_header * } static void -parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header *r) +parse_recv_header (rspamd_mempool_t * pool, + gchar *line, + struct received_header *r) { - gchar *p, *s, t, **res = NULL; + gchar *p, *s, t, **res = NULL; enum { RSPAMD_RECV_STATE_INIT = 0, RSPAMD_RECV_STATE_FROM, @@ -305,8 +326,8 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header RSPAMD_RECV_STATE_SKIP_SPACES, RSPAMD_RECV_STATE_ERROR } state = RSPAMD_RECV_STATE_INIT, - next_state = RSPAMD_RECV_STATE_INIT; - gboolean is_exim = FALSE; + next_state = RSPAMD_RECV_STATE_INIT; + gboolean is_exim = FALSE; g_strstrip (line); p = line; @@ -314,16 +335,18 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header while (*p) { switch (state) { - /* Initial state, search for from */ + /* Initial state, search for from */ case RSPAMD_RECV_STATE_INIT: if (*p == 'f' || *p == 'F') { - if (g_ascii_tolower (*++p) == 'r' && g_ascii_tolower (*++p) == 'o' && g_ascii_tolower (*++p) == 'm') { + if (g_ascii_tolower (*++p) == 'r' && g_ascii_tolower (*++p) == + 'o' && g_ascii_tolower (*++p) == 'm') { p++; state = RSPAMD_RECV_STATE_SKIP_SPACES; next_state = RSPAMD_RECV_STATE_FROM; } } - else if (g_ascii_tolower (*p) == 'b' && g_ascii_tolower (*(p + 1)) == 'y') { + else if (g_ascii_tolower (*p) == 'b' && + g_ascii_tolower (*(p + 1)) == 'y') { state = RSPAMD_RECV_STATE_IP_BLOCK; } else { @@ -332,7 +355,7 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header return; } break; - /* Read hostname */ + /* Read hostname */ case RSPAMD_RECV_STATE_FROM: if (*p == '[') { /* This should be IP address */ @@ -341,7 +364,8 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header next_state = RSPAMD_RECV_STATE_IP_BLOCK; s = ++p; } - else if (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == '_') { + else if (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == + '_') { p++; } else { @@ -353,10 +377,11 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header next_state = RSPAMD_RECV_STATE_IP_BLOCK; } break; - /* Try to extract additional info */ + /* Try to extract additional info */ case RSPAMD_RECV_STATE_IP_BLOCK: /* Try to extract ip or () info or by */ - if (g_ascii_tolower (*p) == 'b' && g_ascii_tolower (*(p + 1)) == 'y') { + if (g_ascii_tolower (*p) == 'b' && g_ascii_tolower (*(p + 1)) == + 'y') { p += 2; /* Skip spaces after by */ state = RSPAMD_RECV_STATE_SKIP_SPACES; @@ -378,11 +403,11 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header p++; } break; - /* We are in () block. Here can be found real hostname and real ip, this is written by some MTA */ + /* We are in () block. Here can be found real hostname and real ip, this is written by some MTA */ case RSPAMD_RECV_STATE_BRACES_BLOCK: /* End of block */ if (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || - *p == '_' || *p == ':') { + *p == '_' || *p == ':') { p++; } else if (*p == '[') { @@ -404,41 +429,45 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header next_state = RSPAMD_RECV_STATE_BRACES_BLOCK; } else if (p - s == 4 && memcmp (s, "helo=", 5) == 0) { - p ++; + p++; is_exim = TRUE; - if (r->real_hostname == NULL && r->from_hostname != NULL) { + if (r->real_hostname == NULL && r->from_hostname != + NULL) { r->real_hostname = r->from_hostname; } s = p; - while (*p != ')' && !g_ascii_isspace (*p) && *p != '\0') { - p ++; + while (*p != ')' && !g_ascii_isspace (*p) && *p != + '\0') { + p++; } if (p > s) { - r->from_hostname = rspamd_mempool_alloc (pool, p - s + 1); + r->from_hostname = rspamd_mempool_alloc (pool, + p - s + 1); rspamd_strlcpy (r->from_hostname, s, p - s + 1); } } else if (p - s == 4 && memcmp (s, "port=", 5) == 0) { - p ++; + p++; is_exim = TRUE; while (g_ascii_isdigit (*p)) { - p ++; + p++; } state = RSPAMD_RECV_STATE_SKIP_SPACES; next_state = RSPAMD_RECV_STATE_BRACES_BLOCK; } else if (*p == '=' && is_exim) { /* Just skip unknown pairs */ - p ++; - while (!g_ascii_isspace (*p) && *p != ')' && *p != '\0') { - p ++; + p++; + while (!g_ascii_isspace (*p) && *p != ')' && *p != + '\0') { + p++; } state = RSPAMD_RECV_STATE_SKIP_SPACES; next_state = RSPAMD_RECV_STATE_BRACES_BLOCK; } else { /* skip all */ - while (*p++ != ')' && *p != '\0'); + while (*p++ != ')' && *p != '\0') ; state = RSPAMD_RECV_STATE_IP_BLOCK; } } @@ -457,13 +486,13 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header continue; } if (*p == ')') { - p ++; + p++; state = RSPAMD_RECV_STATE_SKIP_SPACES; next_state = RSPAMD_RECV_STATE_IP_BLOCK; } } else if (*p == ')') { - p ++; + p++; state = RSPAMD_RECV_STATE_SKIP_SPACES; next_state = RSPAMD_RECV_STATE_IP_BLOCK; } @@ -473,11 +502,11 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header } } break; - /* Got by word */ + /* Got by word */ case RSPAMD_RECV_STATE_BY_BLOCK: /* Here can be only hostname */ if ((g_ascii_isalnum (*p) || *p == '.' || *p == '-' - || *p == '_') && p[1] != '\0') { + || *p == '_') && p[1] != '\0') { p++; } else { @@ -499,7 +528,8 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header } else if (r->from_ip == NULL && r->real_ip != NULL) { r->from_ip = r->real_ip; - if (r->real_hostname == NULL && r->from_hostname != NULL) { + if (r->real_hostname == NULL && r->from_hostname != + NULL) { r->real_hostname = r->from_hostname; } } @@ -508,10 +538,10 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header } break; - /* Extract ip */ + /* Extract ip */ case RSPAMD_RECV_STATE_PARSE_IP: while (g_ascii_isxdigit (*p) || *p == '.' || *p == ':') { - p ++; + p++; } if (*p != ']') { /* Not an ip in fact */ @@ -527,7 +557,7 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header } break; - /* Skip spaces */ + /* Skip spaces */ case RSPAMD_RECV_STATE_SKIP_SPACES: if (!g_ascii_isspace (*p)) { state = next_state; @@ -552,10 +582,10 @@ parse_recv_header (rspamd_mempool_t * pool, gchar *line, struct received_header static void process_raw_headers (struct rspamd_task *task) { - struct raw_header *new = NULL, *lp; - gchar *p, *c, *tmp, *tp; - gint state = 0, l, next_state = 100, err_state = 100, t_state; - gboolean valid_folding = FALSE; + struct raw_header *new = NULL, *lp; + gchar *p, *c, *tmp, *tp; + gint state = 0, l, next_state = 100, err_state = 100, t_state; + gboolean valid_folding = FALSE; p = task->raw_headers_str; c = p; @@ -577,13 +607,15 @@ process_raw_headers (struct rspamd_task *task) case 1: /* We got something like header's name */ if (*p == ':') { - new = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct raw_header)); + new = + rspamd_mempool_alloc0 (task->task_pool, + sizeof (struct raw_header)); l = p - c; tmp = rspamd_mempool_alloc (task->task_pool, l + 1); rspamd_strlcpy (tmp, c, l + 1); new->name = tmp; new->empty_separator = TRUE; - p ++; + p++; state = 2; c = p; } @@ -593,7 +625,7 @@ process_raw_headers (struct rspamd_task *task) next_state = 0; } else { - p ++; + p++; } break; case 2: @@ -601,11 +633,11 @@ process_raw_headers (struct rspamd_task *task) if (*p == '\t') { new->tab_separated = TRUE; new->empty_separator = FALSE; - p ++; + p++; } else if (*p == ' ') { new->empty_separator = FALSE; - p ++; + p++; } else if (*p == '\n' || *p == '\r') { /* Process folding */ @@ -643,7 +675,7 @@ process_raw_headers (struct rspamd_task *task) state = 4; } else { - p ++; + p++; } break; case 4: @@ -652,16 +684,16 @@ process_raw_headers (struct rspamd_task *task) tmp = rspamd_mempool_alloc (task->task_pool, l + 1); tp = tmp; t_state = 0; - while (l --) { + while (l--) { if (t_state == 0) { /* Before folding */ if (*c == '\n' || *c == '\r') { t_state = 1; - c ++; - *tp ++ = ' '; + c++; + *tp++ = ' '; } else { - *tp ++ = *c ++; + *tp++ = *c++; } } else if (t_state == 1) { @@ -671,18 +703,19 @@ process_raw_headers (struct rspamd_task *task) } else { t_state = 0; - *tp ++ = *c ++; + *tp++ = *c++; } } } /* Strip last space that can be added by \r\n parsing */ if (*(tp - 1) == ' ') { - tp --; + tp--; } *tp = '\0'; new->value = tmp; new->next = NULL; - if ((lp = g_hash_table_lookup (task->raw_headers, new->name)) != NULL) { + if ((lp = + g_hash_table_lookup (task->raw_headers, new->name)) != NULL) { while (lp->next != NULL) { lp = lp->next; } @@ -698,7 +731,8 @@ process_raw_headers (struct rspamd_task *task) /* Header has only name, no value */ new->next = NULL; new->value = ""; - if ((lp = g_hash_table_lookup (task->raw_headers, new->name)) != NULL) { + if ((lp = + g_hash_table_lookup (task->raw_headers, new->name)) != NULL) { while (lp->next != NULL) { lp = lp->next; } @@ -717,12 +751,12 @@ process_raw_headers (struct rspamd_task *task) } else { if (*p == '\r' || *p == '\n') { - p ++; + p++; valid_folding = FALSE; } else if (*p == '\t' || *p == ' ') { /* Valid folding */ - p ++; + p++; valid_folding = TRUE; } else { @@ -742,24 +776,24 @@ process_raw_headers (struct rspamd_task *task) /* Fail state, skip line */ if (*p == '\r') { if (*(p + 1) == '\n') { - p ++; + p++; } - p ++; + p++; state = next_state; } else if (*p == '\n') { if (*(p + 1) == '\r') { - p ++; + p++; } - p ++; + p++; state = next_state; } else if (*(p + 1) == '\0') { state = next_state; - p ++; + p++; } else { - p ++; + p++; } break; } @@ -769,45 +803,62 @@ process_raw_headers (struct rspamd_task *task) static void free_byte_array_callback (void *pointer) { - GByteArray *arr = (GByteArray *) pointer; + GByteArray *arr = (GByteArray *) pointer; g_byte_array_free (arr, TRUE); } -static GByteArray * -convert_text_to_utf (struct rspamd_task *task, GByteArray * part_content, GMimeContentType * type, struct mime_text_part *text_part) +static GByteArray * +convert_text_to_utf (struct rspamd_task *task, + GByteArray * part_content, + GMimeContentType * type, + struct mime_text_part *text_part) { - GError *err = NULL; - gsize read_bytes, write_bytes; - const gchar *charset; - gchar *res_str; - GByteArray *result_array; + GError *err = NULL; + gsize read_bytes, write_bytes; + const gchar *charset; + gchar *res_str; + GByteArray *result_array; if (task->cfg->raw_mode) { text_part->is_raw = TRUE; return part_content; } - if ((charset = g_mime_content_type_get_parameter (type, "charset")) == NULL) { + if ((charset = + g_mime_content_type_get_parameter (type, "charset")) == NULL) { text_part->is_raw = TRUE; return part_content; } - if (g_ascii_strcasecmp (charset, "utf-8") == 0 || g_ascii_strcasecmp (charset, "utf8") == 0) { + if (g_ascii_strcasecmp (charset, + "utf-8") == 0 || g_ascii_strcasecmp (charset, "utf8") == 0) { if (g_utf8_validate (part_content->data, part_content->len, NULL)) { text_part->is_raw = FALSE; text_part->is_utf = TRUE; return part_content; } else { - msg_info ("<%s>: contains invalid utf8 characters, assume it as raw", task->message_id); + msg_info ( + "<%s>: contains invalid utf8 characters, assume it as raw", + task->message_id); text_part->is_raw = TRUE; return part_content; } } - res_str = g_convert_with_fallback (part_content->data, part_content->len, UTF8_CHARSET, charset, NULL, &read_bytes, &write_bytes, &err); + res_str = g_convert_with_fallback (part_content->data, + part_content->len, + UTF8_CHARSET, + charset, + NULL, + &read_bytes, + &write_bytes, + &err); if (res_str == NULL) { - msg_warn ("<%s>: cannot convert from %s to utf8: %s", task->message_id, charset, err ? err->message : "unknown problem"); + msg_warn ("<%s>: cannot convert from %s to utf8: %s", + task->message_id, + charset, + err ? err->message : "unknown problem"); text_part->is_raw = TRUE; return part_content; } @@ -815,7 +866,9 @@ convert_text_to_utf (struct rspamd_task *task, GByteArray * part_content, GMimeC result_array = rspamd_mempool_alloc (task->task_pool, sizeof (GByteArray)); result_array->data = res_str; result_array->len = write_bytes; - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_free, res_str); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_free, + res_str); text_part->is_raw = FALSE; text_part->is_utf = TRUE; @@ -823,31 +876,43 @@ convert_text_to_utf (struct rspamd_task *task, GByteArray * part_content, GMimeC } static void -process_text_part (struct rspamd_task *task, GByteArray *part_content, GMimeContentType *type, - GMimeObject *part, GMimeObject *parent, gboolean is_empty) +process_text_part (struct rspamd_task *task, + GByteArray *part_content, + GMimeContentType *type, + GMimeObject *part, + GMimeObject *parent, + gboolean is_empty) { - struct mime_text_part *text_part; - const gchar *cd; + struct mime_text_part *text_part; + const gchar *cd; /* Skip attachements */ #ifndef GMIME24 cd = g_mime_part_get_content_disposition (GMIME_PART (part)); - if (cd && g_ascii_strcasecmp (cd, "attachment") == 0 && !task->cfg->check_text_attachements) { + if (cd && + g_ascii_strcasecmp (cd, + "attachment") == 0 && !task->cfg->check_text_attachements) { debug_task ("skip attachments for checking as text parts"); return; } #else cd = g_mime_object_get_disposition (GMIME_OBJECT (part)); - if (cd && g_ascii_strcasecmp (cd, GMIME_DISPOSITION_ATTACHMENT) == 0 && !task->cfg->check_text_attachements) { + if (cd && + g_ascii_strcasecmp (cd, + GMIME_DISPOSITION_ATTACHMENT) == 0 && + !task->cfg->check_text_attachements) { debug_task ("skip attachments for checking as text parts"); return; } #endif - if (g_mime_content_type_is_type (type, "text", "html") || g_mime_content_type_is_type (type, "text", "xhtml")) { + if (g_mime_content_type_is_type (type, "text", + "html") || g_mime_content_type_is_type (type, "text", "xhtml")) { debug_task ("got urls from text/html part"); - text_part = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct mime_text_part)); + text_part = + rspamd_mempool_alloc0 (task->task_pool, + sizeof (struct mime_text_part)); text_part->is_html = TRUE; if (is_empty) { text_part->is_empty = TRUE; @@ -856,18 +921,26 @@ process_text_part (struct rspamd_task *task, GByteArray *part_content, GMimeCont task->text_parts = g_list_prepend (task->text_parts, text_part); return; } - text_part->orig = convert_text_to_utf (task, part_content, type, text_part); + text_part->orig = convert_text_to_utf (task, + part_content, + type, + text_part); text_part->is_balanced = TRUE; text_part->html_nodes = NULL; text_part->parent = parent; - text_part->content = strip_html_tags (task, task->task_pool, text_part, text_part->orig, NULL); + text_part->content = strip_html_tags (task, + task->task_pool, + text_part, + text_part->orig, + NULL); if (text_part->html_nodes == NULL) { url_parse_text (task->task_pool, task, text_part, FALSE); } else { - decode_entitles (text_part->content->data, &text_part->content->len); + decode_entitles (text_part->content->data, + &text_part->content->len); url_parse_text (task->task_pool, task, text_part, FALSE); #if 0 url_parse_text (task->task_pool, task, text_part, TRUE); @@ -875,13 +948,17 @@ process_text_part (struct rspamd_task *task, GByteArray *part_content, GMimeCont } fuzzy_init_part (text_part, task->task_pool, task->cfg->max_diff); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) free_byte_array_callback, text_part->content); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) free_byte_array_callback, + text_part->content); task->text_parts = g_list_prepend (task->text_parts, text_part); } else if (g_mime_content_type_is_type (type, "text", "*")) { debug_task ("got urls from text/plain part"); - text_part = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct mime_text_part)); + text_part = + rspamd_mempool_alloc0 (task->task_pool, + sizeof (struct mime_text_part)); text_part->is_html = FALSE; text_part->parent = parent; if (is_empty) { @@ -891,7 +968,10 @@ process_text_part (struct rspamd_task *task, GByteArray *part_content, GMimeCont task->text_parts = g_list_prepend (task->text_parts, text_part); return; } - text_part->orig = convert_text_to_utf (task, part_content, type, text_part); + text_part->orig = convert_text_to_utf (task, + part_content, + type, + text_part); text_part->content = text_part->orig; url_parse_text (task->task_pool, task, text_part, FALSE); fuzzy_init_part (text_part, task->task_pool, task->cfg->max_diff); @@ -901,18 +981,20 @@ process_text_part (struct rspamd_task *task, GByteArray *part_content, GMimeCont #ifdef GMIME24 static void -mime_foreach_callback (GMimeObject * parent, GMimeObject * part, gpointer user_data) +mime_foreach_callback (GMimeObject * parent, + GMimeObject * part, + gpointer user_data) #else static void mime_foreach_callback (GMimeObject * part, gpointer user_data) #endif { - struct rspamd_task *task = (struct rspamd_task *)user_data; - struct mime_part *mime_part; - GMimeContentType *type; - GMimeDataWrapper *wrapper; - GMimeStream *part_stream; - GByteArray *part_content; + struct rspamd_task *task = (struct rspamd_task *)user_data; + struct mime_part *mime_part; + GMimeContentType *type; + GMimeDataWrapper *wrapper; + GMimeStream *part_stream; + GByteArray *part_content; task->parts_count++; @@ -921,7 +1003,7 @@ mime_foreach_callback (GMimeObject * part, gpointer user_data) /* find out what class 'part' is... */ if (GMIME_IS_MESSAGE_PART (part)) { /* message/rfc822 or message/news */ - GMimeMessage *message; + GMimeMessage *message; /* g_mime_message_foreach_part() won't descend into child message parts, so if we want to count any @@ -957,11 +1039,13 @@ mime_foreach_callback (GMimeObject * part, gpointer user_data) else if (GMIME_IS_MULTIPART (part)) { /* multipart/mixed, multipart/alternative, multipart/related, multipart/signed, multipart/encrypted, etc... */ task->parser_parent_part = part; -#ifndef GMIME24 +#ifndef GMIME24 debug_task ("detected multipart part"); /* we'll get to finding out if this is a signed/encrypted multipart later... */ if (task->parser_recursion++ < RECURSION_LIMIT) { - g_mime_multipart_foreach ((GMimeMultipart *) part, mime_foreach_callback, task); + g_mime_multipart_foreach ((GMimeMultipart *) part, + mime_foreach_callback, + task); } else { msg_err ("endless recursion detected: %d", task->parser_recursion); @@ -972,17 +1056,21 @@ mime_foreach_callback (GMimeObject * part, gpointer user_data) else if (GMIME_IS_PART (part)) { /* a normal leaf part, could be text/plain or image/jpeg etc */ #ifdef GMIME24 - type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT (part)); + type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT ( + part)); #else - type = (GMimeContentType *) g_mime_part_get_content_type (GMIME_PART (part)); + type = + (GMimeContentType *) g_mime_part_get_content_type (GMIME_PART (part)); #endif if (type == NULL) { msg_warn ("type of part is unknown, assume text/plain"); type = g_mime_content_type_new ("text", "plain"); #ifdef GMIME24 - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_object_unref, type); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_object_unref, type); #else - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_mime_content_type_destroy, type); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_mime_content_type_destroy, type); #endif } wrapper = g_mime_part_get_content_object (GMIME_PART (part)); @@ -992,29 +1080,45 @@ mime_foreach_callback (GMimeObject * part, gpointer user_data) if (wrapper != NULL) { #endif part_stream = g_mime_stream_mem_new (); - if (g_mime_data_wrapper_write_to_stream (wrapper, part_stream) != -1) { - g_mime_stream_mem_set_owner (GMIME_STREAM_MEM (part_stream), FALSE); - part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (part_stream)); + if (g_mime_data_wrapper_write_to_stream (wrapper, + part_stream) != -1) { + g_mime_stream_mem_set_owner (GMIME_STREAM_MEM ( + part_stream), FALSE); + part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM ( + part_stream)); g_object_unref (part_stream); - mime_part = rspamd_mempool_alloc (task->task_pool, sizeof (struct mime_part)); + mime_part = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct mime_part)); mime_part->type = type; mime_part->content = part_content; mime_part->parent = task->parser_parent_part; - mime_part->filename = g_mime_part_get_filename (GMIME_PART (part)); - debug_task ("found part with content-type: %s/%s", type->type, type->subtype); + mime_part->filename = g_mime_part_get_filename (GMIME_PART ( + part)); + debug_task ("found part with content-type: %s/%s", + type->type, + type->subtype); task->parts = g_list_prepend (task->parts, mime_part); /* Skip empty parts */ - process_text_part (task, part_content, type, part, task->parser_parent_part, (part_content->len <= 0)); + process_text_part (task, + part_content, + type, + part, + task->parser_parent_part, + (part_content->len <= 0)); } else { - msg_warn ("write to stream failed: %d, %s", errno, strerror (errno)); + msg_warn ("write to stream failed: %d, %s", errno, + strerror (errno)); } #ifndef GMIME24 g_object_unref (wrapper); #endif } else { - msg_warn ("cannot get wrapper for mime part, type of part: %s/%s", type->type, type->subtype); + msg_warn ("cannot get wrapper for mime part, type of part: %s/%s", + type->type, + type->subtype); } } else { @@ -1025,7 +1129,7 @@ mime_foreach_callback (GMimeObject * part, gpointer user_data) static void destroy_message (void *pointer) { - GMimeMessage *msg = pointer; + GMimeMessage *msg = pointer; msg_debug ("freeing pointer %p", msg); g_object_unref (msg); @@ -1034,33 +1138,34 @@ destroy_message (void *pointer) gint process_message (struct rspamd_task *task) { - GMimeMessage *message; - GMimeParser *parser; - GMimeStream *stream; - GByteArray *tmp; - GList *first, *cur; - GMimePart *part; - GMimeDataWrapper *wrapper; - struct received_header *recv; - gchar *mid, *url_str, *p, *end, *url_end; - struct uri *subject_url; - gsize len; - gint rc; + GMimeMessage *message; + GMimeParser *parser; + GMimeStream *stream; + GByteArray *tmp; + GList *first, *cur; + GMimePart *part; + GMimeDataWrapper *wrapper; + struct received_header *recv; + gchar *mid, *url_str, *p, *end, *url_end; + struct uri *subject_url; + gsize len; + gint rc; tmp = rspamd_mempool_alloc (task->task_pool, sizeof (GByteArray)); tmp->data = task->msg->str; tmp->len = task->msg->len; stream = g_mime_stream_mem_new_with_byte_array (tmp); - /* - * This causes g_mime_stream not to free memory by itself as it is memory allocated by - * pool allocator - */ + /* + * This causes g_mime_stream not to free memory by itself as it is memory allocated by + * pool allocator + */ g_mime_stream_mem_set_owner (GMIME_STREAM_MEM (stream), FALSE); if (task->is_mime) { - debug_task ("construct mime parser from string length %d", (gint)task->msg->len); + debug_task ("construct mime parser from string length %d", + (gint)task->msg->len); /* create a new parser object to parse the stream */ parser = g_mime_parser_new_with_stream (stream); g_object_unref (stream); @@ -1074,7 +1179,8 @@ process_message (struct rspamd_task *task) } task->message = message; - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) destroy_message, task->message); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) destroy_message, task->message); /* Save message id for future use */ task->message_id = g_mime_message_get_message_id (task->message); @@ -1101,7 +1207,8 @@ process_message (struct rspamd_task *task) } #ifdef GMIME24 - task->raw_headers_str = g_mime_object_get_headers (GMIME_OBJECT (task->message)); + task->raw_headers_str = + g_mime_object_get_headers (GMIME_OBJECT (task->message)); #else task->raw_headers_str = g_mime_message_get_headers (task->message); #endif @@ -1109,10 +1216,13 @@ process_message (struct rspamd_task *task) process_images (task); /* Parse received headers */ - first = message_get_header (task->task_pool, message, "Received", FALSE); + first = + message_get_header (task->task_pool, message, "Received", FALSE); cur = first; while (cur) { - recv = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct received_header)); + recv = + rspamd_mempool_alloc0 (task->task_pool, + sizeof (struct received_header)); parse_recv_header (task->task_pool, cur->data, recv); task->received = g_list_prepend (task->received, recv); cur = g_list_next (cur); @@ -1122,16 +1232,21 @@ process_message (struct rspamd_task *task) } if (task->raw_headers_str) { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_free, task->raw_headers_str); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_free, task->raw_headers_str); process_raw_headers (task); } task->rcpts = g_mime_message_get_all_recipients (message); if (task->rcpts) { #ifdef GMIME24 - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_object_unref, task->rcpts); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_object_unref, + task->rcpts); #else - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) internet_address_list_destroy, task->rcpts); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) internet_address_list_destroy, + task->rcpts); #endif } @@ -1149,26 +1264,33 @@ process_message (struct rspamd_task *task) /* Construct part for it */ part = g_mime_part_new_with_type ("text", "html"); #ifdef GMIME24 - wrapper = g_mime_data_wrapper_new_with_stream (stream, GMIME_CONTENT_ENCODING_8BIT); + wrapper = g_mime_data_wrapper_new_with_stream (stream, + GMIME_CONTENT_ENCODING_8BIT); #else - wrapper = g_mime_data_wrapper_new_with_stream (stream, GMIME_PART_ENCODING_8BIT); + wrapper = g_mime_data_wrapper_new_with_stream (stream, + GMIME_PART_ENCODING_8BIT); #endif g_mime_part_set_content_object (part, wrapper); g_mime_message_set_mime_part (task->message, GMIME_OBJECT (part)); /* Register destructors */ - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_object_unref, wrapper); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_object_unref, part); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) destroy_message, task->message); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_object_unref, wrapper); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_object_unref, part); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) destroy_message, task->message); /* Now parse in a normal way */ task->parser_recursion = 0; #ifdef GMIME24 g_mime_message_foreach (task->message, mime_foreach_callback, task); #else - g_mime_message_foreach_part (task->message, mime_foreach_callback, task); + g_mime_message_foreach_part (task->message, mime_foreach_callback, + task); #endif /* Generate message ID */ mid = g_mime_utils_generate_message_id ("localhost.localdomain"); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_free, mid); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_free, mid); g_mime_message_set_message_id (task->message, mid); task->message_id = mid; task->queue_id = mid; @@ -1182,7 +1304,10 @@ process_message (struct rspamd_task *task) if (task->rcpt) { cur = task->rcpt; while (cur) { - g_mime_message_add_recipient (task->message, GMIME_RECIPIENT_TYPE_TO, NULL, (gchar *)cur->data); + g_mime_message_add_recipient (task->message, + GMIME_RECIPIENT_TYPE_TO, + NULL, + (gchar *)cur->data); cur = g_list_next (cur); } } @@ -1198,22 +1323,29 @@ process_message (struct rspamd_task *task) while (p < end) { /* Search to the end of url */ - if (url_try_text (task->task_pool, p, end - p, NULL, &url_end, &url_str, FALSE)) { + if (url_try_text (task->task_pool, p, end - p, NULL, &url_end, + &url_str, FALSE)) { if (url_str != NULL) { - subject_url = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct uri)); + subject_url = rspamd_mempool_alloc0 (task->task_pool, + sizeof (struct uri)); if (subject_url != NULL) { /* Try to parse url */ rc = parse_uri (subject_url, url_str, task->task_pool); - if ((rc == URI_ERRNO_OK || rc == URI_ERRNO_NO_SLASHES || rc == URI_ERRNO_NO_HOST_SLASH) && - subject_url->hostlen > 0) { + if ((rc == URI_ERRNO_OK || rc == URI_ERRNO_NO_SLASHES || + rc == URI_ERRNO_NO_HOST_SLASH) && + subject_url->hostlen > 0) { if (subject_url->protocol != PROTOCOL_MAILTO) { if (!g_tree_lookup (task->urls, subject_url)) { - g_tree_insert (task->urls, subject_url, subject_url); + g_tree_insert (task->urls, + subject_url, + subject_url); } } } else if (rc != URI_ERRNO_OK) { - msg_info ("extract of url '%s' failed: %s", url_str, url_strerror (rc)); + msg_info ("extract of url '%s' failed: %s", + url_str, + url_strerror (rc)); } } } @@ -1231,15 +1363,15 @@ process_message (struct rspamd_task *task) } struct gmime_raw_header { - struct raw_header *next; - gchar *name; - gchar *value; + struct raw_header *next; + gchar *name; + gchar *value; }; typedef struct _GMimeHeader { - GHashTable *hash; - GHashTable *writers; - struct raw_header *headers; + GHashTable *hash; + GHashTable *writers; + struct raw_header *headers; } local_GMimeHeader; @@ -1261,13 +1393,20 @@ enum { */ #ifndef GMIME24 static void -header_iterate (rspamd_mempool_t * pool, struct gmime_raw_header *h, GList ** ret, const gchar *field, gboolean strong) +header_iterate (rspamd_mempool_t * pool, + struct gmime_raw_header *h, + GList ** ret, + const gchar *field, + gboolean strong) { while (h) { if (G_LIKELY (!strong)) { - if (h->value && !g_ascii_strncasecmp (field, h->name, strlen (field))) { + if (h->value && + !g_ascii_strncasecmp (field, h->name, strlen (field))) { if (pool != NULL) { - *ret = g_list_prepend (*ret, rspamd_mempool_strdup (pool, h->value)); + *ret = + g_list_prepend (*ret, + rspamd_mempool_strdup (pool, h->value)); } else { *ret = g_list_prepend (*ret, g_strdup (h->value)); @@ -1277,7 +1416,9 @@ header_iterate (rspamd_mempool_t * pool, struct gmime_raw_header *h, GList ** re else { if (h->value && !strncmp (field, h->name, strlen (field))) { if (pool != NULL) { - *ret = g_list_prepend (*ret, rspamd_mempool_strdup (pool, h->value)); + *ret = + g_list_prepend (*ret, + rspamd_mempool_strdup (pool, h->value)); } else { *ret = g_list_prepend (*ret, g_strdup (h->value)); @@ -1289,11 +1430,15 @@ header_iterate (rspamd_mempool_t * pool, struct gmime_raw_header *h, GList ** re } #else static void -header_iterate (rspamd_mempool_t * pool, GMimeHeaderList * ls, GList ** ret, const gchar *field, gboolean strong) +header_iterate (rspamd_mempool_t * pool, + GMimeHeaderList * ls, + GList ** ret, + const gchar *field, + gboolean strong) { /* Use iterator in case of gmime 2.4 */ - GMimeHeaderIter *iter; - const gchar *name; + GMimeHeaderIter *iter; + const gchar *name; if (ls == NULL) { *ret = NULL; @@ -1301,27 +1446,38 @@ header_iterate (rspamd_mempool_t * pool, GMimeHeaderList * ls, GList ** ret, con } iter = g_mime_header_iter_new (); - if (g_mime_header_list_get_iter (ls, iter) && g_mime_header_iter_first (iter)) { + if (g_mime_header_list_get_iter (ls, + iter) && g_mime_header_iter_first (iter)) { /* Iterate throught headers */ while (g_mime_header_iter_is_valid (iter)) { name = g_mime_header_iter_get_name (iter); if (G_LIKELY (!strong)) { if (!g_ascii_strncasecmp (field, name, strlen (name))) { if (pool != NULL) { - *ret = g_list_prepend (*ret, rspamd_mempool_strdup (pool, g_mime_header_iter_get_value (iter))); + *ret = + g_list_prepend (*ret, + rspamd_mempool_strdup (pool, + g_mime_header_iter_get_value (iter))); } else { - *ret = g_list_prepend (*ret, g_strdup (g_mime_header_iter_get_value (iter))); + *ret = + g_list_prepend (*ret, + g_strdup (g_mime_header_iter_get_value (iter))); } } } else { if (!strncmp (field, name, strlen (name))) { if (pool != NULL) { - *ret = g_list_prepend (*ret, rspamd_mempool_strdup (pool, g_mime_header_iter_get_value (iter))); + *ret = + g_list_prepend (*ret, + rspamd_mempool_strdup (pool, + g_mime_header_iter_get_value (iter))); } else { - *ret = g_list_prepend (*ret, g_strdup (g_mime_header_iter_get_value (iter))); + *ret = + g_list_prepend (*ret, + g_strdup (g_mime_header_iter_get_value (iter))); } } } @@ -1336,12 +1492,12 @@ header_iterate (rspamd_mempool_t * pool, GMimeHeaderList * ls, GList ** ret, con struct multipart_cb_data { - GList *ret; - rspamd_mempool_t *pool; - const gchar *field; - gboolean try_search; - gboolean strong; - gint rec; + GList *ret; + rspamd_mempool_t *pool; + const gchar *field; + gboolean try_search; + gboolean strong; + gint rec; }; #define MAX_REC 10 @@ -1353,21 +1509,21 @@ multipart_iterate (GMimeObject * parent, GMimeObject * part, gpointer user_data) multipart_iterate (GMimeObject * part, gpointer user_data) #endif { - struct multipart_cb_data *data = user_data; + struct multipart_cb_data *data = user_data; #ifndef GMIME24 - struct gmime_raw_header *h; + struct gmime_raw_header *h; #endif - GList *l = NULL; + GList *l = NULL; if (data->try_search && part != NULL && GMIME_IS_PART (part)) { #ifdef GMIME24 - GMimeHeaderList *ls; + GMimeHeaderList *ls; ls = g_mime_object_get_header_list (GMIME_OBJECT (part)); header_iterate (data->pool, ls, &l, data->field, data->strong); #else h = (struct gmime_raw_header *)part->headers->headers; - header_iterate (data->pool, h, &l, data->field, data->strong); + header_iterate (data->pool, h, &l, data->field, data->strong); #endif if (l == NULL) { /* Header not found, abandon search results */ @@ -1382,21 +1538,26 @@ multipart_iterate (GMimeObject * part, gpointer user_data) else if (data->try_search && GMIME_IS_MULTIPART (part)) { /* Maybe endless recursion here ? */ if (data->rec++ < MAX_REC) { - g_mime_multipart_foreach (GMIME_MULTIPART (part), multipart_iterate, data); + g_mime_multipart_foreach (GMIME_MULTIPART ( + part), multipart_iterate, data); } else { - msg_info ("maximum recurse limit is over, stop recursing, %d", data->rec); + msg_info ("maximum recurse limit is over, stop recursing, %d", + data->rec); data->try_search = FALSE; } } } -static GList * -local_message_get_header (rspamd_mempool_t * pool, GMimeMessage * message, const gchar *field, gboolean strong) +static GList * +local_message_get_header (rspamd_mempool_t * pool, + GMimeMessage * message, + const gchar *field, + gboolean strong) { - GList *gret = NULL; - GMimeObject *part; - struct multipart_cb_data cb = { + GList *gret = NULL; + GMimeObject *part; + struct multipart_cb_data cb = { .try_search = TRUE, .rec = 0, .ret = NULL, @@ -1406,7 +1567,7 @@ local_message_get_header (rspamd_mempool_t * pool, GMimeMessage * message, const cb.strong = strong; #ifndef GMIME24 - struct gmime_raw_header *h; + struct gmime_raw_header *h; if (field == NULL) { return NULL; @@ -1418,14 +1579,18 @@ local_message_get_header (rspamd_mempool_t * pool, GMimeMessage * message, const if (gret == NULL) { /* Try to iterate with mime part headers */ - msg_debug ("iterate over headers of mime part to find header %s", field); + msg_debug ("iterate over headers of mime part to find header %s", + field); part = g_mime_message_get_mime_part (message); if (part) { h = (struct gmime_raw_header *)part->headers->headers; header_iterate (pool, h, &gret, field, strong); if (gret == NULL && GMIME_IS_MULTIPART (part)) { - msg_debug ("iterate over headers of each multipart's subparts %s", field); - g_mime_multipart_foreach (GMIME_MULTIPART (part), multipart_iterate, &cb); + msg_debug ( + "iterate over headers of each multipart's subparts %s", + field); + g_mime_multipart_foreach (GMIME_MULTIPART ( + part), multipart_iterate, &cb); if (cb.ret != NULL) { gret = cb.ret; } @@ -1438,7 +1603,7 @@ local_message_get_header (rspamd_mempool_t * pool, GMimeMessage * message, const return gret; #else - GMimeHeaderList *ls; + GMimeHeaderList *ls; ls = g_mime_object_get_header_list (GMIME_OBJECT (message)); header_iterate (pool, ls, &gret, field, strong); @@ -1449,7 +1614,8 @@ local_message_get_header (rspamd_mempool_t * pool, GMimeMessage * message, const ls = g_mime_object_get_header_list (GMIME_OBJECT (part)); header_iterate (pool, ls, &gret, field, strong); if (gret == NULL && GMIME_IS_MULTIPART (part)) { - g_mime_multipart_foreach (GMIME_MULTIPART (part), multipart_iterate, &cb); + g_mime_multipart_foreach (GMIME_MULTIPART ( + part), multipart_iterate, &cb); if (cb.ret != NULL) { gret = cb.ret; } @@ -1466,17 +1632,18 @@ local_message_get_header (rspamd_mempool_t * pool, GMimeMessage * message, const } /** -* g_mime_message_set_date_from_string: Set the message sent-date -* @message: MIME Message -* @string: A string of date -* -* Set the sent-date on a MIME Message. -**/ + * g_mime_message_set_date_from_string: Set the message sent-date + * @message: MIME Message + * @string: A string of date + * + * Set the sent-date on a MIME Message. + **/ void -local_mime_message_set_date_from_string (GMimeMessage * message, const gchar * string) +local_mime_message_set_date_from_string (GMimeMessage * message, + const gchar * string) { - time_t date; - gint offset = 0; + time_t date; + gint offset = 0; date = g_mime_utils_header_decode_date (string, &offset); g_mime_message_set_date (message, date, offset); @@ -1485,14 +1652,14 @@ local_mime_message_set_date_from_string (GMimeMessage * message, const gchar * s /* * Replacements for standart gmime functions but converting adresses to IA */ -static const gchar * +static const gchar * local_message_get_sender (GMimeMessage * message) { - gchar *res; - const gchar *from = g_mime_message_get_sender (message); - InternetAddressList *ia; + gchar *res; + const gchar *from = g_mime_message_get_sender (message); + InternetAddressList *ia; -#ifndef GMIME24 +#ifndef GMIME24 ia = internet_address_parse_string (from); #else ia = internet_address_list_parse_string (from); @@ -1501,7 +1668,7 @@ local_message_get_sender (GMimeMessage * message) return NULL; } res = internet_address_list_to_string (ia, FALSE); -#ifndef GMIME24 +#ifndef GMIME24 internet_address_list_destroy (ia); #else g_object_unref (ia); @@ -1510,14 +1677,14 @@ local_message_get_sender (GMimeMessage * message) return res; } -static const gchar * +static const gchar * local_message_get_reply_to (GMimeMessage * message) { - gchar *res; - const gchar *from = g_mime_message_get_reply_to (message); - InternetAddressList *ia; + gchar *res; + const gchar *from = g_mime_message_get_reply_to (message); + InternetAddressList *ia; -#ifndef GMIME24 +#ifndef GMIME24 ia = internet_address_parse_string (from); #else ia = internet_address_list_parse_string (from); @@ -1526,7 +1693,7 @@ local_message_get_reply_to (GMimeMessage * message) return NULL; } res = internet_address_list_to_string (ia, FALSE); -#ifndef GMIME24 +#ifndef GMIME24 internet_address_list_destroy (ia); #else g_object_unref (ia); @@ -1537,122 +1704,161 @@ local_message_get_reply_to (GMimeMessage * message) #ifdef GMIME24 -# define ADD_RECIPIENT_TEMPLATE(type,def) \ -static void \ -local_message_add_recipients_from_string_##type (GMimeMessage *message, const gchar *string, const gchar *value) \ -{ \ - InternetAddressList *il, *new; \ - \ - il = g_mime_message_get_recipients (message, (def)); \ - new = internet_address_list_parse_string (string); \ - internet_address_list_append (il, new); \ -} \ - -ADD_RECIPIENT_TEMPLATE (to, GMIME_RECIPIENT_TYPE_TO) - ADD_RECIPIENT_TEMPLATE (cc, GMIME_RECIPIENT_TYPE_CC) - ADD_RECIPIENT_TEMPLATE (bcc, GMIME_RECIPIENT_TYPE_BCC) -# define GET_RECIPIENT_TEMPLATE(type,def) \ -static InternetAddressList* \ -local_message_get_recipients_##type (GMimeMessage *message, const gchar *unused) \ -{ \ - return g_mime_message_get_recipients (message, (def)); \ -} - GET_RECIPIENT_TEMPLATE (to, GMIME_RECIPIENT_TYPE_TO) - GET_RECIPIENT_TEMPLATE (cc, GMIME_RECIPIENT_TYPE_CC) - GET_RECIPIENT_TEMPLATE (bcc, GMIME_RECIPIENT_TYPE_BCC) +# define ADD_RECIPIENT_TEMPLATE(type,def) \ + static void \ + local_message_add_recipients_from_string_ ## type (GMimeMessage * message, \ + const gchar * string, \ + const gchar * value) \ + { \ + InternetAddressList *il, *new; \ + \ + il = g_mime_message_get_recipients (message, (def)); \ + new = internet_address_list_parse_string (string); \ + internet_address_list_append (il, new); \ + } \ + +ADD_RECIPIENT_TEMPLATE (to, GMIME_RECIPIENT_TYPE_TO) +ADD_RECIPIENT_TEMPLATE (cc, GMIME_RECIPIENT_TYPE_CC) +ADD_RECIPIENT_TEMPLATE (bcc, GMIME_RECIPIENT_TYPE_BCC) +# define GET_RECIPIENT_TEMPLATE(type,def) \ + static InternetAddressList * \ + local_message_get_recipients_ ## type (GMimeMessage * message, \ + const gchar * unused) \ + { \ + return g_mime_message_get_recipients (message, (def)); \ + } +GET_RECIPIENT_TEMPLATE (to, GMIME_RECIPIENT_TYPE_TO) +GET_RECIPIENT_TEMPLATE (cc, GMIME_RECIPIENT_TYPE_CC) +GET_RECIPIENT_TEMPLATE (bcc, GMIME_RECIPIENT_TYPE_BCC) #endif /* different declarations for different types of set and get functions */ - typedef const gchar *(*GetFunc) (GMimeMessage * message); - typedef InternetAddressList *(*GetRcptFunc) (GMimeMessage * message, const gchar *type); - typedef GList *(*GetListFunc) (rspamd_mempool_t * pool, GMimeMessage * message, const gchar *type, gboolean strong); - typedef void (*SetFunc) (GMimeMessage * message, const gchar *value); - typedef void (*SetListFunc) (GMimeMessage * message, const gchar *field, const gchar *value); +typedef const gchar *(*GetFunc) (GMimeMessage * message); +typedef InternetAddressList *(*GetRcptFunc) (GMimeMessage * message, + const gchar *type); +typedef GList *(*GetListFunc) (rspamd_mempool_t * pool, GMimeMessage * message, + const gchar *type, gboolean strong); +typedef void (*SetFunc) (GMimeMessage * message, const gchar *value); +typedef void (*SetListFunc) (GMimeMessage * message, const gchar *field, + const gchar *value); /** different types of functions -* -* FUNC_CHARPTR -* - function with no arguments -* - get returns gchar* -* -* FUNC_IA (from Internet Address) -* - function with additional "field" argument from the fieldfunc table, -* - get returns Glist* -* -* FUNC_LIST -* - function with additional "field" argument (given arbitrary header field name) -* - get returns Glist* -**/ - enum { - FUNC_CHARPTR = 0, - FUNC_CHARFREEPTR, - FUNC_IA, - FUNC_LIST - }; + * + * FUNC_CHARPTR + * - function with no arguments + * - get returns gchar* + * + * FUNC_IA (from Internet Address) + * - function with additional "field" argument from the fieldfunc table, + * - get returns Glist* + * + * FUNC_LIST + * - function with additional "field" argument (given arbitrary header field name) + * - get returns Glist* + **/ +enum { + FUNC_CHARPTR = 0, + FUNC_CHARFREEPTR, + FUNC_IA, + FUNC_LIST +}; /** -* fieldfunc struct: structure of MIME fields and corresponding get and set -* functions. -**/ - static struct { - gchar *name; - GetFunc func; - GetRcptFunc rcptfunc; - GetListFunc getlistfunc; - SetFunc setfunc; - SetListFunc setlfunc; - gint functype; - } fieldfunc[] = + * fieldfunc struct: structure of MIME fields and corresponding get and set + * functions. + **/ +static struct { + gchar *name; + GetFunc func; + GetRcptFunc rcptfunc; + GetListFunc getlistfunc; + SetFunc setfunc; + SetListFunc setlfunc; + gint functype; +} fieldfunc[] = { { - "From", local_message_get_sender, NULL, NULL, g_mime_message_set_sender, NULL, FUNC_CHARFREEPTR}, { - "Reply-To", local_message_get_reply_to, NULL, NULL, g_mime_message_set_reply_to, NULL, FUNC_CHARFREEPTR}, + "From", local_message_get_sender, NULL, NULL, g_mime_message_set_sender, + NULL, FUNC_CHARFREEPTR + }, { + "Reply-To", local_message_get_reply_to, NULL, NULL, + g_mime_message_set_reply_to, NULL, FUNC_CHARFREEPTR + }, #ifndef GMIME24 { - "To", NULL, (GetRcptFunc) g_mime_message_get_recipients, NULL, NULL, (SetListFunc) g_mime_message_add_recipients_from_string, FUNC_IA}, { - "Cc", NULL, (GetRcptFunc) g_mime_message_get_recipients, NULL, NULL, (SetListFunc) g_mime_message_add_recipients_from_string, FUNC_IA}, { - "Bcc", NULL, (GetRcptFunc) g_mime_message_get_recipients, NULL, NULL, (SetListFunc) g_mime_message_add_recipients_from_string, FUNC_IA}, { - "Date", (GetFunc) g_mime_message_get_date_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR}, + "To", NULL, (GetRcptFunc) g_mime_message_get_recipients, NULL, NULL, + (SetListFunc) g_mime_message_add_recipients_from_string, FUNC_IA + }, { + "Cc", NULL, (GetRcptFunc) g_mime_message_get_recipients, NULL, NULL, + (SetListFunc) g_mime_message_add_recipients_from_string, FUNC_IA + }, { + "Bcc", NULL, (GetRcptFunc) g_mime_message_get_recipients, NULL, NULL, + (SetListFunc) g_mime_message_add_recipients_from_string, FUNC_IA + }, { + "Date", (GetFunc) g_mime_message_get_date_string, NULL, NULL, + local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR + }, #else { - "To", NULL, local_message_get_recipients_to, NULL, NULL, local_message_add_recipients_from_string_to, FUNC_IA}, { - "Cc", NULL, local_message_get_recipients_cc, NULL, NULL, local_message_add_recipients_from_string_cc, FUNC_IA}, { - "Bcc", NULL, local_message_get_recipients_bcc, NULL, NULL, local_message_add_recipients_from_string_bcc, FUNC_IA}, { - "Date", (GetFunc)g_mime_message_get_date_as_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR}, + "To", NULL, local_message_get_recipients_to, NULL, NULL, + local_message_add_recipients_from_string_to, FUNC_IA + }, { + "Cc", NULL, local_message_get_recipients_cc, NULL, NULL, + local_message_add_recipients_from_string_cc, FUNC_IA + }, { + "Bcc", NULL, local_message_get_recipients_bcc, NULL, NULL, + local_message_add_recipients_from_string_bcc, FUNC_IA + }, { + "Date", (GetFunc)g_mime_message_get_date_as_string, NULL, NULL, + local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR + }, #endif { - "Subject", g_mime_message_get_subject, NULL, NULL, g_mime_message_set_subject, NULL, FUNC_CHARPTR}, { - "Message-Id", g_mime_message_get_message_id, NULL, NULL, g_mime_message_set_message_id, NULL, FUNC_CHARPTR}, + "Subject", g_mime_message_get_subject, NULL, NULL, + g_mime_message_set_subject, NULL, FUNC_CHARPTR + }, { + "Message-Id", g_mime_message_get_message_id, NULL, NULL, + g_mime_message_set_message_id, NULL, FUNC_CHARPTR + }, #ifndef GMIME24 { - NULL, NULL, NULL, local_message_get_header, NULL, g_mime_message_add_header, FUNC_LIST} + NULL, NULL, NULL, local_message_get_header, NULL, + g_mime_message_add_header, FUNC_LIST + } #else { - NULL, NULL, NULL, local_message_get_header, NULL, (SetListFunc)g_mime_object_append_header, FUNC_LIST} + NULL, NULL, NULL, local_message_get_header, NULL, + (SetListFunc)g_mime_object_append_header, FUNC_LIST + } #endif }; /** -* message_set_header: set header of any type excluding special (Content- and MIME-Version:) -**/ + * message_set_header: set header of any type excluding special (Content- and MIME-Version:) + **/ void -message_set_header (GMimeMessage * message, const gchar *field, const gchar *value) +message_set_header (GMimeMessage * message, + const gchar *field, + const gchar *value) { - gint i; + gint i; - if (!g_ascii_strcasecmp (field, "MIME-Version:") || !g_ascii_strncasecmp (field, "Content-", 8)) { + if (!g_ascii_strcasecmp (field, + "MIME-Version:") || !g_ascii_strncasecmp (field, "Content-", 8)) { return; } for (i = 0; i <= HEADER_UNKNOWN; ++i) { - if (!fieldfunc[i].name || !g_ascii_strncasecmp (field, fieldfunc[i].name, strlen (fieldfunc[i].name))) { + if (!fieldfunc[i].name || + !g_ascii_strncasecmp (field, fieldfunc[i].name, + strlen (fieldfunc[i].name))) { switch (fieldfunc[i].functype) { case FUNC_CHARPTR: - (*(fieldfunc[i].setfunc)) (message, value); + (*(fieldfunc[i].setfunc))(message, value); break; case FUNC_IA: - (*(fieldfunc[i].setlfunc)) (message, fieldfunc[i].name, value); + (*(fieldfunc[i].setlfunc))(message, fieldfunc[i].name, value); break; case FUNC_LIST: - (*(fieldfunc[i].setlfunc)) (message, field, value); + (*(fieldfunc[i].setlfunc))(message, field, value); break; } break; @@ -1662,37 +1868,45 @@ message_set_header (GMimeMessage * message, const gchar *field, const gchar *val /** -* message_get_header: returns the list of 'any header' values -* (except of unsupported yet Content- and MIME-Version special headers) -* -* You should free the GList list by yourself. -**/ -GList * -message_get_header (rspamd_mempool_t * pool, GMimeMessage * message, const gchar *field, gboolean strong) + * message_get_header: returns the list of 'any header' values + * (except of unsupported yet Content- and MIME-Version special headers) + * + * You should free the GList list by yourself. + **/ +GList * +message_get_header (rspamd_mempool_t * pool, + GMimeMessage * message, + const gchar *field, + gboolean strong) { - gint i; - gchar *ret = NULL, *ia_string; - GList *gret = NULL; - InternetAddressList *ia_list = NULL, *ia; + gint i; + gchar *ret = NULL, *ia_string; + GList *gret = NULL; + InternetAddressList *ia_list = NULL, *ia; for (i = 0; i <= HEADER_UNKNOWN; ++i) { - if (!fieldfunc[i].name || !g_ascii_strncasecmp (field, fieldfunc[i].name, strlen (fieldfunc[i].name))) { + if (!fieldfunc[i].name || + !g_ascii_strncasecmp (field, fieldfunc[i].name, + strlen (fieldfunc[i].name))) { switch (fieldfunc[i].functype) { case FUNC_CHARFREEPTR: - ret = (gchar *)(*(fieldfunc[i].func)) (message); + ret = (gchar *)(*(fieldfunc[i].func))(message); break; case FUNC_CHARPTR: - ret = (gchar *)(*(fieldfunc[i].func)) (message); + ret = (gchar *)(*(fieldfunc[i].func))(message); break; case FUNC_IA: - ia_list = (*(fieldfunc[i].rcptfunc)) (message, field); + ia_list = (*(fieldfunc[i].rcptfunc))(message, field); ia = ia_list; #ifndef GMIME24 while (ia && ia->address) { - ia_string = internet_address_to_string ((InternetAddress *) ia->address, FALSE); + ia_string = internet_address_to_string ( + (InternetAddress *) ia->address, + FALSE); if (pool != NULL) { - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_free, ia_string); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_free, ia_string); } gret = g_list_prepend (gret, ia_string); ia = ia->next; @@ -1700,16 +1914,21 @@ message_get_header (rspamd_mempool_t * pool, GMimeMessage * message, const gchar #else i = internet_address_list_length (ia); while (--i >= 0) { - ia_string = internet_address_to_string (internet_address_list_get_address (ia, i), FALSE); + ia_string = internet_address_to_string (internet_address_list_get_address ( + ia, + i), + FALSE); if (pool != NULL) { - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_free, ia_string); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_free, ia_string); } gret = g_list_prepend (gret, ia_string); } #endif break; case FUNC_LIST: - gret = (*(fieldfunc[i].getlistfunc)) (pool, message, field, strong); + gret = + (*(fieldfunc[i].getlistfunc))(pool, message, field, strong); break; } break; @@ -1730,11 +1949,13 @@ message_get_header (rspamd_mempool_t * pool, GMimeMessage * message, const gchar return gret; } -GList* -message_get_raw_header (struct rspamd_task *task, const gchar *field, gboolean strong) +GList * +message_get_raw_header (struct rspamd_task *task, + const gchar *field, + gboolean strong) { - GList *gret = NULL; - struct raw_header *rh; + GList *gret = NULL; + struct raw_header *rh; rh = g_hash_table_lookup (task->raw_headers, field); @@ -1757,7 +1978,8 @@ message_get_raw_header (struct rspamd_task *task, const gchar *field, gboolean s } if (gret != NULL) { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, gret); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, gret); } return gret; diff --git a/src/libmime/message.h b/src/libmime/message.h index 5e27579d1..fdb987c8c 100644 --- a/src/libmime/message.h +++ b/src/libmime/message.h @@ -30,7 +30,7 @@ struct mime_text_part { GByteArray *orig; GByteArray *content; GNode *html_nodes; - GList *urls_offset; /**< list of offsets of urls */ + GList *urls_offset; /**< list of offsets of urls */ fuzzy_hash_t *fuzzy; fuzzy_hash_t *double_fuzzy; GMimeObject *parent; @@ -57,7 +57,7 @@ struct raw_header { }; /** - * Process message with all filters/statfiles, extract mime parts, urls and + * Process message with all filters/statfiles, extract mime parts, urls and * call metrics consolidation functions * @param task worker_task object * @return 0 if we have delayed filters to process and 1 if we have finished with processing @@ -67,7 +67,9 @@ gint process_message (struct rspamd_task *task); /* * Set header with specified name and value */ -void message_set_header (GMimeMessage *message, const gchar *field, const gchar *value); +void message_set_header (GMimeMessage *message, + const gchar *field, + const gchar *value); /* * Get a list of header's values with specified header's name @@ -77,7 +79,10 @@ void message_set_header (GMimeMessage *message, const gchar *field, const gchar * @param strong if this flag is TRUE header's name is case sensitive, otherwise it is not * @return A list of header's values or NULL. If list is not NULL it MUST be freed. If pool is NULL elements must be freed as well. */ -GList* message_get_header (rspamd_mempool_t *pool, GMimeMessage *message, const gchar *field, gboolean strong); +GList * message_get_header (rspamd_mempool_t *pool, + GMimeMessage *message, + const gchar *field, + gboolean strong); /* * Get a list of header's values with specified header's name using raw headers @@ -86,6 +91,8 @@ GList* message_get_header (rspamd_mempool_t *pool, GMimeMessage *message, const * @param strong if this flag is TRUE header's name is case sensitive, otherwise it is not * @return A list of header's values or NULL. Unlike previous function it is NOT required to free list or values. I should rework one of these functions some time. */ -GList* message_get_raw_header (struct rspamd_task *task, const gchar *field, gboolean strong); +GList * message_get_raw_header (struct rspamd_task *task, + const gchar *field, + gboolean strong); #endif diff --git a/src/libmime/smtp_proto.c b/src/libmime/smtp_proto.c index 3af1c3910..c9220f84a 100644 --- a/src/libmime/smtp_proto.c +++ b/src/libmime/smtp_proto.c @@ -30,13 +30,16 @@ #include "smtp_proto.h" #include "smtp_utils.h" -gchar * -make_smtp_error (rspamd_mempool_t *pool, gint error_code, const gchar *format, ...) +gchar * +make_smtp_error (rspamd_mempool_t *pool, + gint error_code, + const gchar *format, + ...) { - va_list vp; - gchar *result = NULL, *p; - size_t len; - + va_list vp; + gchar *result = NULL, *p; + size_t len; + va_start (vp, format); len = g_printf_string_upper_bound (format, vp); va_end (vp); @@ -53,7 +56,9 @@ make_smtp_error (rspamd_mempool_t *pool, gint error_code, const gchar *format, . gboolean -parse_smtp_command (struct smtp_session *session, f_str_t *line, struct smtp_command **cmd) +parse_smtp_command (struct smtp_session *session, + f_str_t *line, + struct smtp_command **cmd) { enum { SMTP_PARSE_START = 0, @@ -61,11 +66,11 @@ parse_smtp_command (struct smtp_session *session, f_str_t *line, struct smtp_com SMTP_PARSE_ARGUMENT, SMTP_PARSE_DONE } state; - gchar *p, *c, ch, cmd_buf[4]; - guint i; - f_str_t *arg = NULL; - struct smtp_command *pcmd; - + gchar *p, *c, ch, cmd_buf[4]; + guint i; + f_str_t *arg = NULL; + struct smtp_command *pcmd; + if (line->len == 0) { return FALSE; } @@ -76,125 +81,129 @@ parse_smtp_command (struct smtp_session *session, f_str_t *line, struct smtp_com *cmd = rspamd_mempool_alloc0 (session->pool, sizeof (struct smtp_command)); pcmd = *cmd; - for (i = 0; i < line->len; i ++, p ++) { + for (i = 0; i < line->len; i++, p++) { ch = *p; switch (state) { - case SMTP_PARSE_START: - if (ch == ' ' || ch == ':' || ch == CR || ch == LF || i == line->len - 1) { - if (i == line->len - 1) { - p ++; + case SMTP_PARSE_START: + if (ch == ' ' || ch == ':' || ch == CR || ch == LF || i == + line->len - 1) { + if (i == line->len - 1) { + p++; + } + if (p - c == 4) { + cmd_buf[0] = g_ascii_toupper (c[0]); + cmd_buf[1] = g_ascii_toupper (c[1]); + cmd_buf[2] = g_ascii_toupper (c[2]); + cmd_buf[3] = g_ascii_toupper (c[3]); + + if (memcmp (cmd_buf, "HELO", 4) == 0) { + pcmd->command = SMTP_COMMAND_HELO; } - if (p - c == 4) { - cmd_buf[0] = g_ascii_toupper (c[0]); - cmd_buf[1] = g_ascii_toupper (c[1]); - cmd_buf[2] = g_ascii_toupper (c[2]); - cmd_buf[3] = g_ascii_toupper (c[3]); - - if (memcmp (cmd_buf, "HELO", 4) == 0) { - pcmd->command = SMTP_COMMAND_HELO; - } - else if (memcmp (cmd_buf, "EHLO", 4) == 0) { - pcmd->command = SMTP_COMMAND_EHLO; - } - else if (memcmp (cmd_buf, "MAIL", 4) == 0) { - pcmd->command = SMTP_COMMAND_MAIL; - } - else if (memcmp (cmd_buf, "RCPT", 4) == 0) { - pcmd->command = SMTP_COMMAND_RCPT; - } - else if (memcmp (cmd_buf, "DATA", 4) == 0) { - pcmd->command = SMTP_COMMAND_DATA; - } - else if (memcmp (cmd_buf, "QUIT", 4) == 0) { - pcmd->command = SMTP_COMMAND_QUIT; - } - else if (memcmp (cmd_buf, "NOOP", 4) == 0) { - pcmd->command = SMTP_COMMAND_NOOP; - } - else if (memcmp (cmd_buf, "EXPN", 4) == 0) { - pcmd->command = SMTP_COMMAND_EXPN; - } - else if (memcmp (cmd_buf, "RSET", 4) == 0) { - pcmd->command = SMTP_COMMAND_RSET; - } - else if (memcmp (cmd_buf, "HELP", 4) == 0) { - pcmd->command = SMTP_COMMAND_HELP; - } - else if (memcmp (cmd_buf, "VRFY", 4) == 0) { - pcmd->command = SMTP_COMMAND_VRFY; - } - else { - msg_info ("invalid command: %*s", 4, cmd_buf); - return FALSE; - } + else if (memcmp (cmd_buf, "EHLO", 4) == 0) { + pcmd->command = SMTP_COMMAND_EHLO; } - else { - /* Invalid command */ - msg_info ("invalid command: %*s", 4, c); - return FALSE; + else if (memcmp (cmd_buf, "MAIL", 4) == 0) { + pcmd->command = SMTP_COMMAND_MAIL; + } + else if (memcmp (cmd_buf, "RCPT", 4) == 0) { + pcmd->command = SMTP_COMMAND_RCPT; + } + else if (memcmp (cmd_buf, "DATA", 4) == 0) { + pcmd->command = SMTP_COMMAND_DATA; + } + else if (memcmp (cmd_buf, "QUIT", 4) == 0) { + pcmd->command = SMTP_COMMAND_QUIT; } - /* Now check what we have */ - if (ch == ' ' || ch == ':') { - state = SMTP_PARSE_SPACES; + else if (memcmp (cmd_buf, "NOOP", 4) == 0) { + pcmd->command = SMTP_COMMAND_NOOP; } - else if (ch == CR) { - state = SMTP_PARSE_DONE; + else if (memcmp (cmd_buf, "EXPN", 4) == 0) { + pcmd->command = SMTP_COMMAND_EXPN; } - else if (ch == LF) { - return TRUE; + else if (memcmp (cmd_buf, "RSET", 4) == 0) { + pcmd->command = SMTP_COMMAND_RSET; + } + else if (memcmp (cmd_buf, "HELP", 4) == 0) { + pcmd->command = SMTP_COMMAND_HELP; + } + else if (memcmp (cmd_buf, "VRFY", 4) == 0) { + pcmd->command = SMTP_COMMAND_VRFY; + } + else { + msg_info ("invalid command: %*s", 4, cmd_buf); + return FALSE; } } - else if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { - msg_info ("invalid letter code in SMTP command: %d", (gint)ch); + else { + /* Invalid command */ + msg_info ("invalid command: %*s", 4, c); return FALSE; } - break; - case SMTP_PARSE_SPACES: - if (ch == CR) { + /* Now check what we have */ + if (ch == ' ' || ch == ':') { + state = SMTP_PARSE_SPACES; + } + else if (ch == CR) { state = SMTP_PARSE_DONE; } else if (ch == LF) { - goto end; - } - else if (ch != ' ' && ch != ':') { - state = SMTP_PARSE_ARGUMENT; - arg = rspamd_mempool_alloc (session->pool, sizeof (f_str_t)); - c = p; + return TRUE; } - break; - case SMTP_PARSE_ARGUMENT: - if (ch == ' ' || ch == ':' || ch == CR || ch == LF || i == line->len - 1) { - if (i == line->len - 1 && (ch != ' ' && ch != CR && ch != LF)) { - p ++; - } - arg->len = p - c; - arg->begin = rspamd_mempool_alloc (session->pool, arg->len); - memcpy (arg->begin, c, arg->len); - pcmd->args = g_list_prepend (pcmd->args, arg); - if (ch == ' ' || ch == ':') { - state = SMTP_PARSE_SPACES; - } - else if (ch == CR) { - state = SMTP_PARSE_DONE; - } - else { - goto end; - } + } + else if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { + msg_info ("invalid letter code in SMTP command: %d", (gint)ch); + return FALSE; + } + break; + case SMTP_PARSE_SPACES: + if (ch == CR) { + state = SMTP_PARSE_DONE; + } + else if (ch == LF) { + goto end; + } + else if (ch != ' ' && ch != ':') { + state = SMTP_PARSE_ARGUMENT; + arg = rspamd_mempool_alloc (session->pool, sizeof (f_str_t)); + c = p; + } + break; + case SMTP_PARSE_ARGUMENT: + if (ch == ' ' || ch == ':' || ch == CR || ch == LF || i == + line->len - 1) { + if (i == line->len - 1 && (ch != ' ' && ch != CR && ch != LF)) { + p++; + } + arg->len = p - c; + arg->begin = rspamd_mempool_alloc (session->pool, arg->len); + memcpy (arg->begin, c, arg->len); + pcmd->args = g_list_prepend (pcmd->args, arg); + if (ch == ' ' || ch == ':') { + state = SMTP_PARSE_SPACES; + } + else if (ch == CR) { + state = SMTP_PARSE_DONE; } - break; - case SMTP_PARSE_DONE: - if (ch == LF) { + else { goto end; } - msg_info ("CR without LF in SMTP command"); - return FALSE; + } + break; + case SMTP_PARSE_DONE: + if (ch == LF) { + goto end; + } + msg_info ("CR without LF in SMTP command"); + return FALSE; } } end: if (pcmd->args) { pcmd->args = g_list_reverse (pcmd->args); - rspamd_mempool_add_destructor (session->pool, (rspamd_mempool_destruct_t)g_list_free, pcmd->args); + rspamd_mempool_add_destructor (session->pool, + (rspamd_mempool_destruct_t)g_list_free, + pcmd->args); } return TRUE; } @@ -202,14 +211,14 @@ end: static gboolean check_smtp_path (f_str_t *path) { - guint i; - gchar *p; + guint i; + gchar *p; p = path->begin; if (*p != '<' || path->len < 2) { return FALSE; } - for (i = 0; i < path->len; i++, p ++) { + for (i = 0; i < path->len; i++, p++) { if (*p == '>' && i != path->len - 1) { return FALSE; } @@ -221,7 +230,7 @@ check_smtp_path (f_str_t *path) gboolean parse_smtp_helo (struct smtp_session *session, struct smtp_command *cmd) { - f_str_t *arg; + f_str_t *arg; if (cmd->args == NULL) { session->error = SMTP_ERROR_BAD_ARGUMENTS; @@ -256,8 +265,8 @@ parse_smtp_helo (struct smtp_session *session, struct smtp_command *cmd) gboolean parse_smtp_from (struct smtp_session *session, struct smtp_command *cmd) { - f_str_t *arg; - GList *cur = cmd->args; + f_str_t *arg; + GList *cur = cmd->args; if (cmd->args == NULL) { session->error = SMTP_ERROR_BAD_ARGUMENTS; @@ -266,10 +275,10 @@ parse_smtp_from (struct smtp_session *session, struct smtp_command *cmd) arg = cur->data; /* First argument MUST be FROM */ if (arg->len != 4 || ( - g_ascii_toupper (arg->begin[0]) != 'F' || - g_ascii_toupper (arg->begin[1]) != 'R' || - g_ascii_toupper (arg->begin[2]) != 'O' || - g_ascii_toupper (arg->begin[3]) != 'M')) { + g_ascii_toupper (arg->begin[0]) != 'F' || + g_ascii_toupper (arg->begin[1]) != 'R' || + g_ascii_toupper (arg->begin[2]) != 'O' || + g_ascii_toupper (arg->begin[3]) != 'M')) { session->error = SMTP_ERROR_BAD_ARGUMENTS; return FALSE; } @@ -294,8 +303,8 @@ parse_smtp_from (struct smtp_session *session, struct smtp_command *cmd) gboolean parse_smtp_rcpt (struct smtp_session *session, struct smtp_command *cmd) { - f_str_t *arg; - GList *cur = cmd->args; + f_str_t *arg; + GList *cur = cmd->args; if (cmd->args == NULL) { session->error = SMTP_ERROR_BAD_ARGUMENTS; @@ -304,8 +313,8 @@ parse_smtp_rcpt (struct smtp_session *session, struct smtp_command *cmd) arg = cur->data; /* First argument MUST be FROM */ if (arg->len != 2 || ( - g_ascii_toupper (arg->begin[0]) != 'T' || - g_ascii_toupper (arg->begin[1]) != 'O')) { + g_ascii_toupper (arg->begin[0]) != 'T' || + g_ascii_toupper (arg->begin[1]) != 'O')) { session->error = SMTP_ERROR_BAD_ARGUMENTS; return FALSE; } @@ -332,7 +341,7 @@ parse_smtp_rcpt (struct smtp_session *session, struct smtp_command *cmd) static gint check_smtp_ustream_reply (f_str_t *in, gchar success_code) { - gchar *p; + gchar *p; /* Check for 250 at the begin of line */ if (in->len >= sizeof ("220 ") - 1) { @@ -357,13 +366,13 @@ check_smtp_ustream_reply (f_str_t *in, gchar success_code) size_t smtp_upstream_write_list (GList *args, gchar *buf, size_t buflen) { - GList *cur = args; - size_t r = 0; - f_str_t *arg; + GList *cur = args; + size_t r = 0; + f_str_t *arg; while (cur && r < buflen - 3) { arg = cur->data; - r += rspamd_snprintf (buf + r, buflen - r, " %V", arg); + r += rspamd_snprintf (buf + r, buflen - r, " %V", arg); cur = g_list_next (cur); } @@ -374,288 +383,351 @@ smtp_upstream_write_list (GList *args, gchar *buf, size_t buflen) return r; } -gboolean +gboolean smtp_upstream_write_socket (void *arg) { - struct smtp_session *session = arg; - + struct smtp_session *session = arg; + if (session->upstream_state == SMTP_STATE_IN_SENDFILE) { session->upstream_state = SMTP_STATE_AFTER_DATA; - return rspamd_dispatcher_write (session->upstream_dispatcher, CRLF DATA_END_TRAILER, sizeof (CRLF DATA_END_TRAILER) - 1, FALSE, TRUE); + return rspamd_dispatcher_write (session->upstream_dispatcher, + CRLF DATA_END_TRAILER, + sizeof (CRLF DATA_END_TRAILER) - 1, + FALSE, + TRUE); } return TRUE; } -gboolean +gboolean smtp_upstream_read_socket (f_str_t * in, void *arg) { - struct smtp_session *session = arg; - gchar outbuf[BUFSIZ]; - gint r; - + struct smtp_session *session = arg; + gchar outbuf[BUFSIZ]; + gint r; + msg_debug ("in: %V, state: %d", in, session->upstream_state); switch (session->upstream_state) { - case SMTP_STATE_GREETING: - r = check_smtp_ustream_reply (in, '2'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { - goto err; - } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; + case SMTP_STATE_GREETING: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + in->len, FALSE, TRUE)) { + goto err; } - else if (r == 1) { - if (session->ctx->use_xclient) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "XCLIENT NAME=%s ADDR=%s" CRLF, - session->resolved ? session->hostname : "[UNDEFINED]", - inet_ntoa (session->client_addr)); - session->upstream_state = SMTP_STATE_HELO; - return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); - } - else { - session->upstream_state = SMTP_STATE_FROM; - if (session->helo) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s %s" CRLF, - session->esmtp ? "EHLO" : "HELO", - session->helo); - } - else { - return smtp_upstream_read_socket (in, arg); - } - return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); - } + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, + sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; } - break; - case SMTP_STATE_HELO: - r = check_smtp_ustream_reply (in, '2'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { - goto err; - } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; + destroy_session (session->s); + return FALSE; + } + else if (r == 1) { + if (session->ctx->use_xclient) { + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "XCLIENT NAME=%s ADDR=%s" CRLF, + session->resolved ? session->hostname : "[UNDEFINED]", + inet_ntoa (session->client_addr)); + session->upstream_state = SMTP_STATE_HELO; + return rspamd_dispatcher_write (session->upstream_dispatcher, + outbuf, + r, + FALSE, + FALSE); } - else if (r == 1) { + else { session->upstream_state = SMTP_STATE_FROM; if (session->helo) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s %s" CRLF, - session->esmtp ? "EHLO" : "HELO", - session->helo); + r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s %s" CRLF, + session->esmtp ? "EHLO" : "HELO", + session->helo); } else { return smtp_upstream_read_socket (in, arg); } - return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); + return rspamd_dispatcher_write (session->upstream_dispatcher, + outbuf, + r, + FALSE, + FALSE); } - break; - case SMTP_STATE_FROM: - r = check_smtp_ustream_reply (in, '2'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { - goto err; - } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; + } + break; + case SMTP_STATE_HELO: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + in->len, FALSE, TRUE)) { + goto err; } - else if (r == 1) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "MAIL FROM: "); - r += smtp_upstream_write_list (session->from, outbuf + r, sizeof (outbuf) - r); - session->upstream_state = SMTP_STATE_RCPT; - return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, + sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; } - break; - case SMTP_STATE_RCPT: - r = check_smtp_ustream_reply (in, '2'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { - goto err; - } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; + destroy_session (session->s); + return FALSE; + } + else if (r == 1) { + session->upstream_state = SMTP_STATE_FROM; + if (session->helo) { + r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s %s" CRLF, + session->esmtp ? "EHLO" : "HELO", + session->helo); } - else if (r == 1) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: "); - session->cur_rcpt = g_list_first (session->rcpt); - r += smtp_upstream_write_list (session->cur_rcpt->data, outbuf + r, sizeof (outbuf) - r); - session->cur_rcpt = g_list_next (session->cur_rcpt); - session->upstream_state = SMTP_STATE_BEFORE_DATA; - return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); + else { + return smtp_upstream_read_socket (in, arg); } - break; - case SMTP_STATE_BEFORE_DATA: - r = check_smtp_ustream_reply (in, '2'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { - goto err; - } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - if (session->cur_rcpt) { - session->rcpt = g_list_delete_link (session->rcpt, session->cur_rcpt); - } - else { - session->rcpt = g_list_delete_link (session->rcpt, session->rcpt); - } - session->errors ++; - session->state = SMTP_STATE_RCPT; - return TRUE; - } - else if (r == 1) { - if (session->cur_rcpt != NULL) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: "); - r += smtp_upstream_write_list (session->cur_rcpt, outbuf + r, sizeof (outbuf) - r); - session->cur_rcpt = g_list_next (session->cur_rcpt); - if (! rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE)) { - goto err; - } - } - else { - session->upstream_state = SMTP_STATE_DATA; - rspamd_dispatcher_pause (session->upstream_dispatcher); - } - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* Write to client */ - if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { - goto err; - } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - if (session->state == SMTP_STATE_WAIT_UPSTREAM) { - rspamd_dispatcher_restore (session->dispatcher); - session->state = SMTP_STATE_RCPT; - } + return rspamd_dispatcher_write (session->upstream_dispatcher, + outbuf, + r, + FALSE, + FALSE); + } + break; + case SMTP_STATE_FROM: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + in->len, FALSE, TRUE)) { + goto err; } - break; - case SMTP_STATE_DATA: - r = check_smtp_ustream_reply (in, '3'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { - goto err; - } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, + sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; } - else if (r == 1) { - if (! make_smtp_tempfile (session)) { - session->error = SMTP_ERROR_FILE; - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; - } - session->state = SMTP_STATE_AFTER_DATA; - session->error = SMTP_ERROR_DATA_OK; - rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + destroy_session (session->s); + return FALSE; + } + else if (r == 1) { + r = rspamd_snprintf (outbuf, sizeof (outbuf), "MAIL FROM: "); + r += + smtp_upstream_write_list (session->from, + outbuf + r, + sizeof (outbuf) - r); + session->upstream_state = SMTP_STATE_RCPT; + return rspamd_dispatcher_write (session->upstream_dispatcher, + outbuf, + r, + FALSE, + FALSE); + } + break; + case SMTP_STATE_RCPT: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + in->len, FALSE, TRUE)) { + goto err; + } + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, + sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; + } + destroy_session (session->s); + return FALSE; + } + else if (r == 1) { + r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: "); + session->cur_rcpt = g_list_first (session->rcpt); + r += smtp_upstream_write_list (session->cur_rcpt->data, + outbuf + r, + sizeof (outbuf) - r); + session->cur_rcpt = g_list_next (session->cur_rcpt); + session->upstream_state = SMTP_STATE_BEFORE_DATA; + return rspamd_dispatcher_write (session->upstream_dispatcher, + outbuf, + r, + FALSE, + FALSE); + } + break; + case SMTP_STATE_BEFORE_DATA: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + rspamd_dispatcher_restore (session->dispatcher); + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + in->len, FALSE, TRUE)) { + goto err; + } + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, + sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; + } + if (session->cur_rcpt) { + session->rcpt = g_list_delete_link (session->rcpt, + session->cur_rcpt); + } + else { + session->rcpt = + g_list_delete_link (session->rcpt, session->rcpt); + } + session->errors++; + session->state = SMTP_STATE_RCPT; + return TRUE; + } + else if (r == 1) { + if (session->cur_rcpt != NULL) { + r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: "); + r += smtp_upstream_write_list (session->cur_rcpt, + outbuf + r, + sizeof (outbuf) - r); + session->cur_rcpt = g_list_next (session->cur_rcpt); + if (!rspamd_dispatcher_write (session->upstream_dispatcher, + outbuf, r, FALSE, FALSE)) { goto err; } + } + else { + session->upstream_state = SMTP_STATE_DATA; rspamd_dispatcher_pause (session->upstream_dispatcher); - rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_LINE, 0); - session->dispatcher->strip_eol = FALSE; - return TRUE; } - break; - case SMTP_STATE_AFTER_DATA: session->error = rspamd_mempool_alloc (session->pool, in->len + 1); rspamd_strlcpy (session->error, in->begin, in->len + 1); - session->state = SMTP_STATE_DATA; - rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + /* Write to client */ + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + in->len, FALSE, TRUE)) { + goto err; + } + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, + sizeof (CRLF) - 1, FALSE, TRUE)) { goto err; } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + if (session->state == SMTP_STATE_WAIT_UPSTREAM) { + rspamd_dispatcher_restore (session->dispatcher); + session->state = SMTP_STATE_RCPT; + } + } + break; + case SMTP_STATE_DATA: + r = check_smtp_ustream_reply (in, '3'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { goto err; } - if (! rspamd_dispatcher_write (session->upstream_dispatcher, "QUIT" CRLF, sizeof ("QUIT" CRLF) - 1, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, + sizeof (CRLF) - 1, FALSE, TRUE)) { goto err; } - session->upstream_state = SMTP_STATE_END; - return TRUE; - break; - case SMTP_STATE_END: - r = check_smtp_ustream_reply (in, '5'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ + destroy_session (session->s); + return FALSE; + } + else if (r == 1) { + if (!make_smtp_tempfile (session)) { + session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { - goto err; - } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, + session->error, 0, FALSE, TRUE)) { goto err; } destroy_session (session->s); return FALSE; } - else { - remove_normal_event (session->s, (event_finalizer_t)smtp_upstream_finalize_connection, session); + session->state = SMTP_STATE_AFTER_DATA; + session->error = SMTP_ERROR_DATA_OK; + rspamd_dispatcher_restore (session->dispatcher); + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { + goto err; } - return FALSE; - break; - default: - msg_err ("got upstream reply at unexpected state: %d, reply: %V", session->upstream_state, in); + rspamd_dispatcher_pause (session->upstream_dispatcher); + rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_LINE, 0); + session->dispatcher->strip_eol = FALSE; + return TRUE; + } + break; + case SMTP_STATE_AFTER_DATA: + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + session->state = SMTP_STATE_DATA; + rspamd_dispatcher_restore (session->dispatcher); + if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, + FALSE, TRUE)) { + goto err; + } + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - + 1, FALSE, TRUE)) { + goto err; + } + if (!rspamd_dispatcher_write (session->upstream_dispatcher, "QUIT" CRLF, + sizeof ("QUIT" CRLF) - 1, FALSE, TRUE)) { + goto err; + } + session->upstream_state = SMTP_STATE_END; + return TRUE; + break; + case SMTP_STATE_END: + r = check_smtp_ustream_reply (in, '5'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { goto err; } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, + sizeof (CRLF) - 1, FALSE, TRUE)) { goto err; } destroy_session (session->s); return FALSE; + } + else { + remove_normal_event (session->s, + (event_finalizer_t)smtp_upstream_finalize_connection, + session); + } + return FALSE; + break; + default: + msg_err ("got upstream reply at unexpected state: %d, reply: %V", + session->upstream_state, + in); + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, + FALSE, TRUE)) { + goto err; + } + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - + 1, FALSE, TRUE)) { + goto err; + } + destroy_session (session->s); + return FALSE; } return TRUE; @@ -664,20 +736,24 @@ err: return FALSE; } -void +void smtp_upstream_err_socket (GError *err, void *arg) { - struct smtp_session *session = arg; + struct smtp_session *session = arg; - msg_info ("abnormally closing connection with upstream %s, error: %s", session->upstream->name, err->message); + msg_info ("abnormally closing connection with upstream %s, error: %s", + session->upstream->name, + err->message); session->error = SMTP_ERROR_UPSTREAM; session->state = SMTP_STATE_CRITICAL_ERROR; /* XXX: assume upstream errors as critical errors */ rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, + TRUE)) { return; } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, + FALSE, TRUE)) { return; } upstream_fail (&session->upstream->up, session->session_time); @@ -687,10 +763,11 @@ smtp_upstream_err_socket (GError *err, void *arg) void smtp_upstream_finalize_connection (gpointer data) { - struct smtp_session *session = data; - + struct smtp_session *session = data; + if (session->state != SMTP_STATE_CRITICAL_ERROR) { - if (! rspamd_dispatcher_write (session->upstream_dispatcher, "QUIT" CRLF, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->upstream_dispatcher, "QUIT" CRLF, + 0, FALSE, TRUE)) { msg_warn ("cannot send correctly closing message to upstream"); } } diff --git a/src/libmime/smtp_proto.h b/src/libmime/smtp_proto.h index 42fecd255..7c5787926 100644 --- a/src/libmime/smtp_proto.h +++ b/src/libmime/smtp_proto.h @@ -6,12 +6,14 @@ /* SMTP errors */ #define SMTP_ERROR_BAD_COMMAND "500 Syntax error, command unrecognized" CRLF -#define SMTP_ERROR_BAD_ARGUMENTS "501 Syntax error in parameters or arguments" CRLF +#define SMTP_ERROR_BAD_ARGUMENTS "501 Syntax error in parameters or arguments" \ + CRLF #define SMTP_ERROR_SEQUENCE "503 Bad sequence of commands" CRLF #define SMTP_ERROR_RECIPIENTS "554 No valid recipients" CRLF #define SMTP_ERROR_UNIMPLIMENTED "502 Command not implemented" CRLF #define SMTP_ERROR_LIMIT "505 Too many errors. Aborting." CRLF -#define SMTP_ERROR_UPSTREAM "421 Service not available, closing transmission channel" CRLF +#define SMTP_ERROR_UPSTREAM \ + "421 Service not available, closing transmission channel" CRLF #define SMTP_ERROR_FILE "420 Service not available, filesystem error" CRLF #define SMTP_ERROR_OK "250 Requested mail action okay, completed" CRLF #define SMTP_ERROR_DATA_OK "354 Start mail input; end with <CRLF>.<CRLF>" CRLF @@ -43,27 +45,35 @@ struct smtp_command { /* * Generate SMTP error message */ -gchar * make_smtp_error (rspamd_mempool_t *pool, gint error_code, const gchar *format, ...); +gchar * make_smtp_error (rspamd_mempool_t *pool, + gint error_code, + const gchar *format, + ...); /* * Parse a single SMTP command */ -gboolean parse_smtp_command (struct smtp_session *session, f_str_t *line, struct smtp_command **cmd); +gboolean parse_smtp_command (struct smtp_session *session, + f_str_t *line, + struct smtp_command **cmd); /* * Parse HELO command */ -gboolean parse_smtp_helo (struct smtp_session *session, struct smtp_command *cmd); +gboolean parse_smtp_helo (struct smtp_session *session, + struct smtp_command *cmd); /* * Parse MAIL command */ -gboolean parse_smtp_from (struct smtp_session *session, struct smtp_command *cmd); +gboolean parse_smtp_from (struct smtp_session *session, + struct smtp_command *cmd); /* * Parse RCPT command */ -gboolean parse_smtp_rcpt (struct smtp_session *session, struct smtp_command *cmd); +gboolean parse_smtp_rcpt (struct smtp_session *session, + struct smtp_command *cmd); /* Upstream SMTP */ diff --git a/src/libmime/smtp_utils.c b/src/libmime/smtp_utils.c index 8ed169fa7..606d7de51 100644 --- a/src/libmime/smtp_utils.c +++ b/src/libmime/smtp_utils.c @@ -30,7 +30,7 @@ void free_smtp_session (gpointer arg) { - struct smtp_session *session = arg; + struct smtp_session *session = arg; if (session) { if (session->task) { @@ -60,12 +60,17 @@ free_smtp_session (gpointer arg) gboolean create_smtp_upstream_connection (struct smtp_session *session) { - struct smtp_upstream *selected; + struct smtp_upstream *selected; /* Try to select upstream */ - selected = (struct smtp_upstream *)get_upstream_round_robin (session->ctx->upstreams, - session->ctx->upstream_num, sizeof (struct smtp_upstream), - session->session_time, DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS); + selected = (struct smtp_upstream *)get_upstream_round_robin ( + session->ctx->upstreams, + session->ctx->upstream_num, + sizeof (struct smtp_upstream), + session->session_time, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS); if (selected == NULL) { msg_err ("no upstreams suitable found"); return FALSE; @@ -74,19 +79,32 @@ create_smtp_upstream_connection (struct smtp_session *session) session->upstream = selected; /* Now try to create socket */ - session->upstream_sock = make_universal_socket (selected->addr, selected->port, SOCK_STREAM, TRUE, FALSE, FALSE); + session->upstream_sock = make_universal_socket (selected->addr, + selected->port, + SOCK_STREAM, + TRUE, + FALSE, + FALSE); if (session->upstream_sock == -1) { msg_err ("cannot make a connection to %s", selected->name); upstream_fail (&selected->up, session->session_time); return FALSE; } /* Create a dispatcher for upstream connection */ - session->upstream_dispatcher = rspamd_create_dispatcher (session->ev_base, session->upstream_sock, BUFFER_LINE, - smtp_upstream_read_socket, smtp_upstream_write_socket, smtp_upstream_err_socket, - &session->ctx->smtp_timeout, session); + session->upstream_dispatcher = rspamd_create_dispatcher (session->ev_base, + session->upstream_sock, + BUFFER_LINE, + smtp_upstream_read_socket, + smtp_upstream_write_socket, + smtp_upstream_err_socket, + &session->ctx->smtp_timeout, + session); session->state = SMTP_STATE_WAIT_UPSTREAM; session->upstream_state = SMTP_STATE_GREETING; - register_async_event (session->s, (event_finalizer_t)smtp_upstream_finalize_connection, session, g_quark_from_static_string ("smtp proxy")); + register_async_event (session->s, + (event_finalizer_t)smtp_upstream_finalize_connection, + session, + g_quark_from_static_string ("smtp proxy")); return TRUE; } @@ -98,7 +116,8 @@ smtp_send_upstream_message (struct smtp_session *session) session->upstream_state = SMTP_STATE_IN_SENDFILE; session->state = SMTP_STATE_WAIT_UPSTREAM; - if (! rspamd_dispatcher_sendfile (session->upstream_dispatcher, session->temp_fd, session->temp_size)) { + if (!rspamd_dispatcher_sendfile (session->upstream_dispatcher, + session->temp_fd, session->temp_size)) { msg_err ("sendfile failed: %s", strerror (errno)); goto err; } @@ -107,7 +126,8 @@ smtp_send_upstream_message (struct smtp_session *session) err: session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, + TRUE)) { return FALSE; } destroy_session (session->s); @@ -115,32 +135,35 @@ err: } struct smtp_metric_callback_data { - struct smtp_session *session; - enum rspamd_metric_action action; - struct metric_result *res; - gchar *log_buf; - gint log_offset; - gint log_size; - gboolean alive; + struct smtp_session *session; + enum rspamd_metric_action action; + struct metric_result *res; + gchar *log_buf; + gint log_offset; + gint log_size; + gboolean alive; }; static void smtp_metric_symbols_callback (gpointer key, gpointer value, void *user_data) { - struct smtp_metric_callback_data *cd = user_data; + struct smtp_metric_callback_data *cd = user_data; - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "%s,", (gchar *)key); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "%s,", + (gchar *)key); } static void smtp_metric_callback (gpointer key, gpointer value, gpointer ud) { struct smtp_metric_callback_data *cd = ud; - struct metric_result *metric_res = value; - enum rspamd_metric_action action = METRIC_ACTION_NOACTION; - double ms = 0, rs = 0; - gboolean is_spam = FALSE; - struct rspamd_task *task; + struct metric_result *metric_res = value; + enum rspamd_metric_action action = METRIC_ACTION_NOACTION; + double ms = 0, rs = 0; + gboolean is_spam = FALSE; + struct rspamd_task *task; task = cd->session->task; @@ -152,8 +175,10 @@ smtp_metric_callback (gpointer key, gpointer value, gpointer ud) ms = metric_res->metric->actions[METRIC_ACTION_REJECT].score; rs = metric_res->metric->actions[METRIC_ACTION_REJECT].score; } - if (! check_metric_action_settings (task, metric_res, metric_res->score, &action)) { - action = check_metric_action (metric_res->score, ms, metric_res->metric); + if (!check_metric_action_settings (task, metric_res, metric_res->score, + &action)) { + action = + check_metric_action (metric_res->score, ms, metric_res->metric); } #endif if (metric_res->score >= ms) { @@ -165,42 +190,70 @@ smtp_metric_callback (gpointer key, gpointer value, gpointer ud) } if (!task->is_skipped) { - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: %c (%s): [%.2f/%.2f/%.2f] [", - (gchar *)key, is_spam ? 'T' : 'F', str_action_metric (action), metric_res->score, ms, rs); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "(%s: %c (%s): [%.2f/%.2f/%.2f] [", + (gchar *)key, + is_spam ? 'T' : 'F', + str_action_metric (action), + metric_res->score, + ms, + rs); } else { - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: %c (default): [%.2f/%.2f/%.2f] [", - (gchar *)key, 'S', metric_res->score, ms, rs); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "(%s: %c (default): [%.2f/%.2f/%.2f] [", + (gchar *)key, + 'S', + metric_res->score, + ms, + rs); } - g_hash_table_foreach (metric_res->symbols, smtp_metric_symbols_callback, cd); + g_hash_table_foreach (metric_res->symbols, smtp_metric_symbols_callback, + cd); /* Remove last , from log buf */ if (cd->log_buf[cd->log_offset - 1] == ',') { cd->log_buf[--cd->log_offset] = '\0'; } #ifdef HAVE_CLOCK_GETTIME - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "]), len: %z, time: %s,", - task->msg->len, calculate_check_time (&task->tv, &task->ts, task->cfg->clock_res, &task->scan_milliseconds)); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "]), len: %z, time: %s,", + task->msg->len, + calculate_check_time (&task->tv, &task->ts, task->cfg->clock_res, + &task->scan_milliseconds)); #else - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "]), len: %z, time: %s,", - task->msg->len, calculate_check_time (&task->tv, task->cfg->clock_res, &task->scan_milliseconds)); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "]), len: %z, time: %s,", + task->msg->len, + calculate_check_time (&task->tv, task->cfg->clock_res, + &task->scan_milliseconds)); #endif } gboolean make_smtp_tempfile (struct smtp_session *session) { - gsize r; + gsize r; r = strlen (session->cfg->temp_dir) + sizeof ("/rspamd-XXXXXX"); session->temp_name = rspamd_mempool_alloc (session->pool, r); - rspamd_snprintf (session->temp_name, r, "%s%crspamd-XXXXXX", session->cfg->temp_dir, G_DIR_SEPARATOR); + rspamd_snprintf (session->temp_name, + r, + "%s%crspamd-XXXXXX", + session->cfg->temp_dir, + G_DIR_SEPARATOR); #ifdef HAVE_MKSTEMP /* Umask is set before */ session->temp_fd = mkstemp (session->temp_name); #else - session->temp_fd = g_mkstemp_full (session->temp_name, O_RDWR, S_IWUSR | S_IRUSR); + session->temp_fd = g_mkstemp_full (session->temp_name, + O_RDWR, + S_IWUSR | S_IRUSR); #endif if (session->temp_fd == -1) { msg_err ("mkstemp error: %s", strerror (errno)); @@ -214,23 +267,28 @@ make_smtp_tempfile (struct smtp_session *session) gboolean write_smtp_reply (struct smtp_session *session) { - gchar logbuf[1024], *new_subject; - const gchar *old_subject; + gchar logbuf[1024], *new_subject; + const gchar *old_subject; struct smtp_metric_callback_data cd; - GMimeStream *stream; - gint old_fd, sublen; + GMimeStream *stream; + gint old_fd, sublen; /* Check metrics */ cd.session = session; cd.action = METRIC_ACTION_NOACTION; cd.res = NULL; cd.log_buf = logbuf; - cd.log_offset = rspamd_snprintf (logbuf, sizeof (logbuf), "id: <%s>, qid: <%s>, ", - session->task->message_id, session->task->queue_id); + cd.log_offset = rspamd_snprintf (logbuf, + sizeof (logbuf), + "id: <%s>, qid: <%s>, ", + session->task->message_id, + session->task->queue_id); cd.log_size = sizeof (logbuf); if (session->task->user) { - cd.log_offset += rspamd_snprintf (logbuf + cd.log_offset, sizeof (logbuf) - cd.log_offset, - "user: %s, ", session->task->user); + cd.log_offset += rspamd_snprintf (logbuf + cd.log_offset, + sizeof (logbuf) - cd.log_offset, + "user: %s, ", + session->task->user); } g_hash_table_foreach (session->task->results, smtp_metric_callback, &cd); @@ -238,22 +296,26 @@ write_smtp_reply (struct smtp_session *session) msg_info ("%s", logbuf); if (cd.action <= METRIC_ACTION_REJECT) { - if (! rspamd_dispatcher_write (session->dispatcher, session->ctx->reject_message, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, + session->ctx->reject_message, 0, FALSE, TRUE)) { return FALSE; } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - + 1, FALSE, TRUE)) { return FALSE; } destroy_session (session->s); return FALSE; } - else if (cd.action <= METRIC_ACTION_ADD_HEADER || cd.action <= METRIC_ACTION_REWRITE_SUBJECT) { + else if (cd.action <= METRIC_ACTION_ADD_HEADER || cd.action <= + METRIC_ACTION_REWRITE_SUBJECT) { old_fd = session->temp_fd; - if (! make_smtp_tempfile (session)) { + if (!make_smtp_tempfile (session)) { session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { goto err; } destroy_session (session->s); @@ -266,7 +328,11 @@ write_smtp_reply (struct smtp_session *session) if (old_subject != NULL) { sublen = strlen (old_subject) + sizeof (SPAM_SUBJECT); new_subject = rspamd_mempool_alloc (session->pool, sublen); - rspamd_snprintf (new_subject, sublen, "%s%s", SPAM_SUBJECT, old_subject); + rspamd_snprintf (new_subject, + sublen, + "%s%s", + SPAM_SUBJECT, + old_subject); } else { new_subject = SPAM_SUBJECT; @@ -275,21 +341,26 @@ write_smtp_reply (struct smtp_session *session) } else if (cd.action <= METRIC_ACTION_ADD_HEADER) { #ifndef GMIME24 - g_mime_message_add_header (session->task->message, "X-Spam", "true"); + g_mime_message_add_header (session->task->message, "X-Spam", + "true"); #else - g_mime_object_append_header (GMIME_OBJECT (session->task->message), "X-Spam", "true"); + g_mime_object_append_header (GMIME_OBJECT ( + session->task->message), "X-Spam", "true"); #endif } stream = g_mime_stream_fs_new (session->temp_fd); g_mime_stream_fs_set_owner (GMIME_STREAM_FS (stream), FALSE); close (old_fd); - if (g_mime_object_write_to_stream (GMIME_OBJECT (session->task->message), stream) == -1) { - msg_err ("cannot write MIME object to stream: %s", strerror (errno)); + if (g_mime_object_write_to_stream (GMIME_OBJECT (session->task->message), + stream) == -1) { + msg_err ("cannot write MIME object to stream: %s", + strerror (errno)); session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { goto err; } destroy_session (session->s); @@ -302,7 +373,8 @@ write_smtp_reply (struct smtp_session *session) err: session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, + TRUE)) { return FALSE; } destroy_session (session->s); @@ -310,29 +382,33 @@ err: } gboolean -parse_upstreams_line (rspamd_mempool_t *pool, struct smtp_upstream *upstreams, const gchar *line, gsize *count) +parse_upstreams_line (rspamd_mempool_t *pool, + struct smtp_upstream *upstreams, + const gchar *line, + gsize *count) { - gchar **strv, *p, *t, *tt, *err_str; - guint32 num, i; - struct smtp_upstream *cur; - gchar resolved_path[PATH_MAX]; + gchar **strv, *p, *t, *tt, *err_str; + guint32 num, i; + struct smtp_upstream *cur; + gchar resolved_path[PATH_MAX]; strv = g_strsplit_set (line, ",; ", -1); num = g_strv_length (strv); if (num >= MAX_SMTP_UPSTREAMS) { - msg_err ("cannot define %d upstreams %d is max", num, MAX_SMTP_UPSTREAMS); + msg_err ("cannot define %d upstreams %d is max", num, + MAX_SMTP_UPSTREAMS); return FALSE; } *count = 0; - for (i = 0; i < num; i ++) { + for (i = 0; i < num; i++) { p = strv[i]; cur = &upstreams[*count]; if ((t = strrchr (p, ':')) != NULL && (tt = strchr (p, ':')) != t) { /* Assume that after last `:' we have weigth */ *t = '\0'; - t ++; + t++; errno = 0; cur->up.priority = strtoul (t, &err_str, 10); if (errno != 0 || (err_str && *err_str != '\0')) { @@ -349,15 +425,15 @@ parse_upstreams_line (rspamd_mempool_t *pool, struct smtp_upstream *upstreams, c return FALSE; } cur->name = rspamd_mempool_strdup (pool, resolved_path); - (*count) ++; + (*count)++; } else { - if (! rspamd_parse_host_port (pool, p, &cur->addr, &cur->port)) { + if (!rspamd_parse_host_port (pool, p, &cur->addr, &cur->port)) { g_strfreev (strv); return FALSE; } cur->name = rspamd_mempool_strdup (pool, p); - (*count) ++; + (*count)++; } } diff --git a/src/libmime/smtp_utils.h b/src/libmime/smtp_utils.h index 652b6759f..c09729180 100644 --- a/src/libmime/smtp_utils.h +++ b/src/libmime/smtp_utils.h @@ -58,6 +58,9 @@ void free_smtp_session (gpointer arg); * @param count targeted count * @return */ -gboolean parse_upstreams_line (rspamd_mempool_t *pool, struct smtp_upstream *upstreams, const gchar *line, gsize *count); +gboolean parse_upstreams_line (rspamd_mempool_t *pool, + struct smtp_upstream *upstreams, + const gchar *line, + gsize *count); #endif /* SMTP_UTILS_H_ */ diff --git a/src/libserver/binlog.c b/src/libserver/binlog.c index ec191eac7..6565d41e1 100644 --- a/src/libserver/binlog.c +++ b/src/libserver/binlog.c @@ -35,7 +35,7 @@ static GHashTable *binlog_opened = NULL; static rspamd_mempool_t *binlog_pool = NULL; -static gboolean +static gboolean binlog_write_header (struct rspamd_binlog *log) { struct rspamd_binlog_header header = { @@ -43,27 +43,35 @@ binlog_write_header (struct rspamd_binlog *log) .version = VALID_VERSION, .padding = { '\0', '\0' }, }; - + header.create_time = time (NULL); lock_file (log->fd, FALSE); - + if (write (log->fd, &header, sizeof (struct rspamd_binlog_header)) == -1) { - msg_warn ("cannot write file %s, error %d, %s", log->filename, errno, strerror (errno)); + msg_warn ("cannot write file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); return FALSE; } memcpy (&log->header, &header, sizeof (struct rspamd_binlog_header)); - + /* Metaindex */ log->metaindex = g_malloc (sizeof (struct rspamd_binlog_metaindex)); bzero (log->metaindex, sizeof (struct rspamd_binlog_metaindex)); /* Offset to metaindex */ - log->metaindex->indexes[0] = sizeof (struct rspamd_binlog_metaindex) + sizeof (struct rspamd_binlog_header); + log->metaindex->indexes[0] = sizeof (struct rspamd_binlog_metaindex) + + sizeof (struct rspamd_binlog_header); - if (write (log->fd, log->metaindex, sizeof (struct rspamd_binlog_metaindex)) == -1) { + if (write (log->fd, log->metaindex, + sizeof (struct rspamd_binlog_metaindex)) == -1) { g_free (log->metaindex); - msg_warn ("cannot write file %s, error %d, %s", log->filename, errno, strerror (errno)); + msg_warn ("cannot write file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); unlock_file (log->fd, FALSE); return FALSE; } @@ -71,9 +79,13 @@ binlog_write_header (struct rspamd_binlog *log) /* Alloc, write, mmap */ log->cur_idx = g_malloc (sizeof (struct rspamd_index_block)); bzero (log->cur_idx, sizeof (struct rspamd_index_block)); - if (write (log->fd, log->cur_idx, sizeof (struct rspamd_index_block)) == -1) { + if (write (log->fd, log->cur_idx, + sizeof (struct rspamd_index_block)) == -1) { g_free (log->cur_idx); - msg_warn ("cannot write file %s, error %d, %s", log->filename, errno, strerror (errno)); + msg_warn ("cannot write file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); unlock_file (log->fd, FALSE); return FALSE; } @@ -88,14 +100,20 @@ binlog_check_file (struct rspamd_binlog *log) { static gchar valid_magic[] = VALID_MAGIC, valid_version[] = VALID_VERSION; - if (read (log->fd, &log->header, sizeof (struct rspamd_binlog_header)) != sizeof (struct rspamd_binlog_header)) { - msg_warn ("cannot read file %s, error %d, %s", log->filename, errno, strerror (errno)); + if (read (log->fd, &log->header, + sizeof (struct rspamd_binlog_header)) != + sizeof (struct rspamd_binlog_header)) { + msg_warn ("cannot read file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); return FALSE; } /* Now check all fields */ - if (memcmp (&log->header.magic, valid_magic, sizeof (valid_magic)) != 0 || - memcmp (&log->header.version, valid_version, sizeof (valid_version)) != 0) { + if (memcmp (&log->header.magic, valid_magic, sizeof (valid_magic)) != 0 || + memcmp (&log->header.version, valid_version, + sizeof (valid_version)) != 0) { msg_warn ("cannot validate file %s"); return FALSE; } @@ -103,24 +121,38 @@ binlog_check_file (struct rspamd_binlog *log) if (log->metaindex == NULL) { log->metaindex = g_malloc (sizeof (struct rspamd_binlog_metaindex)); } - if ((read (log->fd, log->metaindex, sizeof (struct rspamd_binlog_metaindex))) != sizeof (struct rspamd_binlog_metaindex)) { - msg_warn ("cannot read metaindex of file %s, error %d, %s", log->filename, errno, strerror (errno)); + if ((read (log->fd, log->metaindex, + sizeof (struct rspamd_binlog_metaindex))) != + sizeof (struct rspamd_binlog_metaindex)) { + msg_warn ("cannot read metaindex of file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); return FALSE; } /* Current index */ if (log->cur_idx == NULL) { log->cur_idx = g_malloc (sizeof (struct rspamd_index_block)); } - if (lseek (log->fd, log->metaindex->indexes[log->metaindex->last_index], SEEK_SET) == -1) { - msg_info ("cannot seek in file: %s, error: %s", log->filename, strerror (errno)); + if (lseek (log->fd, log->metaindex->indexes[log->metaindex->last_index], + SEEK_SET) == -1) { + msg_info ("cannot seek in file: %s, error: %s", + log->filename, + strerror (errno)); return FALSE; } - if ((read (log->fd, log->cur_idx, sizeof (struct rspamd_index_block))) != sizeof (struct rspamd_index_block)) { - msg_warn ("cannot read index in file %s, error %d, %s", log->filename, errno, strerror (errno)); + if ((read (log->fd, log->cur_idx, + sizeof (struct rspamd_index_block))) != + sizeof (struct rspamd_index_block)) { + msg_warn ("cannot read index in file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); return FALSE; } - log->cur_seq = log->metaindex->last_index * BINLOG_IDX_LEN + log->cur_idx->last_index; + log->cur_seq = log->metaindex->last_index * BINLOG_IDX_LEN + + log->cur_idx->last_index; log->cur_time = log->cur_idx->indexes[log->cur_idx->last_index].time; return TRUE; @@ -130,8 +162,13 @@ binlog_check_file (struct rspamd_binlog *log) static gboolean binlog_create (struct rspamd_binlog *log) { - if ((log->fd = open (log->filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) { - msg_info ("cannot create file %s, error %d, %s", log->filename, errno, strerror (errno)); + if ((log->fd = + open (log->filename, O_RDWR | O_TRUNC | O_CREAT, + S_IWUSR | S_IRUSR)) == -1) { + msg_info ("cannot create file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); return FALSE; } @@ -142,19 +179,25 @@ static gboolean binlog_open_real (struct rspamd_binlog *log) { if ((log->fd = open (log->filename, O_RDWR)) == -1) { - msg_info ("cannot open file %s, error %d, %s", log->filename, errno, strerror (errno)); + msg_info ("cannot open file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); return FALSE; } - + return binlog_check_file (log); } -struct rspamd_binlog* -binlog_open (rspamd_mempool_t *pool, const gchar *path, time_t rotate_time, gint rotate_jitter) +struct rspamd_binlog * +binlog_open (rspamd_mempool_t *pool, + const gchar *path, + time_t rotate_time, + gint rotate_jitter) { struct rspamd_binlog *new; - gint len = strlen (path); + gint len = strlen (path); struct stat st; new = rspamd_mempool_alloc0 (pool, sizeof (struct rspamd_binlog)); @@ -165,15 +208,16 @@ binlog_open (rspamd_mempool_t *pool, const gchar *path, time_t rotate_time, gint if (rotate_time) { new->rotate_jitter = g_random_int_range (0, rotate_jitter); } - + new->filename = rspamd_mempool_alloc (pool, len + sizeof (BINLOG_SUFFIX)); - rspamd_strlcpy (new->filename, path, len + 1); + rspamd_strlcpy (new->filename, path, len + 1); rspamd_strlcpy (new->filename + len, BINLOG_SUFFIX, sizeof (BINLOG_SUFFIX)); if (stat (new->filename, &st) == -1) { /* Check errno to check whether we should create this file */ if (errno != ENOENT) { - msg_err ("cannot stat file: %s, error %s", new->filename, strerror (errno)); + msg_err ("cannot stat file: %s, error %s", new->filename, + strerror (errno)); return NULL; } else { @@ -193,7 +237,7 @@ binlog_open (rspamd_mempool_t *pool, const gchar *path, time_t rotate_time, gint return new; } -void +void binlog_close (struct rspamd_binlog *log) { if (log) { @@ -210,16 +254,18 @@ binlog_close (struct rspamd_binlog *log) static gboolean binlog_tree_callback (gpointer key, gpointer value, gpointer data) { - token_node_t *node = key; - struct rspamd_binlog *log = data; - struct rspamd_binlog_element elt; + token_node_t *node = key; + struct rspamd_binlog *log = data; + struct rspamd_binlog_element elt; elt.h1 = node->h1; elt.h2 = node->h2; elt.value = node->value; - + if (write (log->fd, &elt, sizeof (elt)) == -1) { - msg_info ("cannot write token to file: %s, error: %s", log->filename, strerror (errno)); + msg_info ("cannot write token to file: %s, error: %s", + log->filename, + strerror (errno)); return TRUE; } @@ -233,12 +279,14 @@ write_binlog_tree (struct rspamd_binlog *log, GTree *nodes) struct rspamd_binlog_index *idx; lock_file (log->fd, FALSE); - log->cur_seq ++; + log->cur_seq++; /* Seek to end of file */ if ((seek = lseek (log->fd, 0, SEEK_END)) == -1) { unlock_file (log->fd, FALSE); - msg_info ("cannot seek in file: %s, error: %s", log->filename, strerror (errno)); + msg_info ("cannot seek in file: %s, error: %s", + log->filename, + strerror (errno)); return FALSE; } @@ -251,21 +299,28 @@ write_binlog_tree (struct rspamd_binlog *log, GTree *nodes) idx->time = (guint64)time (NULL); log->cur_time = idx->time; idx->len = g_tree_nnodes (nodes) * sizeof (struct rspamd_binlog_element); - if (lseek (log->fd, log->metaindex->indexes[log->metaindex->last_index], SEEK_SET) == -1) { + if (lseek (log->fd, log->metaindex->indexes[log->metaindex->last_index], + SEEK_SET) == -1) { unlock_file (log->fd, FALSE); - msg_info ("cannot seek in file: %s, error: %s, seek: %L, op: insert index", log->filename, - strerror (errno), log->metaindex->indexes[log->metaindex->last_index]); + msg_info ( + "cannot seek in file: %s, error: %s, seek: %L, op: insert index", + log->filename, + strerror (errno), + log->metaindex->indexes[log->metaindex->last_index]); return FALSE; } - log->cur_idx->last_index ++; - if (write (log->fd, log->cur_idx, sizeof (struct rspamd_index_block)) == -1) { + log->cur_idx->last_index++; + if (write (log->fd, log->cur_idx, + sizeof (struct rspamd_index_block)) == -1) { unlock_file (log->fd, FALSE); - msg_info ("cannot write index to file: %s, error: %s", log->filename, strerror (errno)); + msg_info ("cannot write index to file: %s, error: %s", + log->filename, + strerror (errno)); return FALSE; } unlock_file (log->fd, FALSE); - + return TRUE; } @@ -275,18 +330,24 @@ create_new_metaindex_block (struct rspamd_binlog *log) off_t seek; lock_file (log->fd, FALSE); - - log->metaindex->last_index ++; + + log->metaindex->last_index++; /* Seek to end of file */ if ((seek = lseek (log->fd, 0, SEEK_END)) == -1) { unlock_file (log->fd, FALSE); - msg_info ("cannot seek in file: %s, error: %s", log->filename, strerror (errno)); + msg_info ("cannot seek in file: %s, error: %s", + log->filename, + strerror (errno)); return FALSE; } - if (write (log->fd, log->cur_idx, sizeof (struct rspamd_index_block)) == -1) { + if (write (log->fd, log->cur_idx, + sizeof (struct rspamd_index_block)) == -1) { unlock_file (log->fd, FALSE); g_free (log->cur_idx); - msg_warn ("cannot write file %s, error %d, %s", log->filename, errno, strerror (errno)); + msg_warn ("cannot write file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); return FALSE; } /* Offset to metaindex */ @@ -294,12 +355,17 @@ create_new_metaindex_block (struct rspamd_binlog *log) /* Overwrite all metaindexes */ if (lseek (log->fd, sizeof (struct rspamd_binlog_header), SEEK_SET) == -1) { unlock_file (log->fd, FALSE); - msg_info ("cannot seek in file: %s, error: %s", log->filename, strerror (errno)); + msg_info ("cannot seek in file: %s, error: %s", + log->filename, + strerror (errno)); return FALSE; } - if (write (log->fd, log->metaindex, sizeof (struct rspamd_binlog_metaindex)) == -1) { + if (write (log->fd, log->metaindex, + sizeof (struct rspamd_binlog_metaindex)) == -1) { unlock_file (log->fd, FALSE); - msg_info ("cannot write metaindex in file: %s, error: %s", log->filename, strerror (errno)); + msg_info ("cannot write metaindex in file: %s, error: %s", + log->filename, + strerror (errno)); return FALSE; } bzero (log->cur_idx, sizeof (struct rspamd_index_block)); @@ -311,9 +377,11 @@ create_new_metaindex_block (struct rspamd_binlog *log) static gboolean maybe_rotate_binlog (struct rspamd_binlog *log) { - guint64 now = time (NULL); + guint64 now = time (NULL); - if (log->rotate_time && ((now - log->header.create_time) > (guint)(log->rotate_time + log->rotate_jitter))) { + if (log->rotate_time && + ((now - log->header.create_time) > + (guint)(log->rotate_time + log->rotate_jitter))) { return TRUE; } return FALSE; @@ -322,7 +390,7 @@ maybe_rotate_binlog (struct rspamd_binlog *log) static gboolean rotate_binlog (struct rspamd_binlog *log) { - gchar *backup_name; + gchar *backup_name; struct stat st; lock_file (log->fd, FALSE); @@ -355,13 +423,14 @@ rotate_binlog (struct rspamd_binlog *log) } -gboolean +gboolean binlog_insert (struct rspamd_binlog *log, GTree *nodes) { off_t seek; if (!log || !log->metaindex || !log->cur_idx || !nodes) { - msg_info ("improperly opened binlog: %s", log != NULL ? log->filename : "unknown"); + msg_info ("improperly opened binlog: %s", + log != NULL ? log->filename : "unknown"); return FALSE; } @@ -381,7 +450,9 @@ binlog_insert (struct rspamd_binlog *log, GTree *nodes) if (log->metaindex->last_index < METAINDEX_LEN) { /* Create new index block */ if ((seek = lseek (log->fd, 0, SEEK_END)) == (off_t)-1) { - msg_info ("cannot seek in file: %s, error: %s", log->filename, strerror (errno)); + msg_info ("cannot seek in file: %s, error: %s", + log->filename, + strerror (errno)); return FALSE; } if (!create_new_metaindex_block (log)) { @@ -389,7 +460,7 @@ binlog_insert (struct rspamd_binlog *log, GTree *nodes) } return write_binlog_tree (log, nodes); } - + /* All binlog is filled, we need to rotate it forcefully */ if (!rotate_binlog (log)) { return FALSE; @@ -398,16 +469,20 @@ binlog_insert (struct rspamd_binlog *log, GTree *nodes) return write_binlog_tree (log, nodes); } -gboolean -binlog_sync (struct rspamd_binlog *log, guint64 from_rev, guint64 *from_time, GByteArray **rep) +gboolean +binlog_sync (struct rspamd_binlog *log, + guint64 from_rev, + guint64 *from_time, + GByteArray **rep) { - guint32 metaindex_num; + guint32 metaindex_num; struct rspamd_index_block *idxb; struct rspamd_binlog_index *idx; gboolean idx_mapped = FALSE, res = TRUE, is_first = FALSE; if (!log || !log->metaindex || !log->cur_idx) { - msg_info ("improperly opened binlog: %s", log != NULL ? log->filename : "unknown"); + msg_info ("improperly opened binlog: %s", + log != NULL ? log->filename : "unknown"); return FALSE; } @@ -419,7 +494,7 @@ binlog_sync (struct rspamd_binlog *log, guint64 from_rev, guint64 *from_time, GB /* Unmap old fragment */ g_free ((*rep)->data); } - + if (from_rev == log->cur_seq) { /* Last record */ *rep = NULL; @@ -427,7 +502,11 @@ binlog_sync (struct rspamd_binlog *log, guint64 from_rev, guint64 *from_time, GB } else if (from_rev > log->cur_seq) { /* Slave has more actual copy, write this to log and abort sync */ - msg_warn ("slave has more recent revision of statfile %s: %uL and our is: %uL", log->filename, from_rev, log->cur_seq); + msg_warn ( + "slave has more recent revision of statfile %s: %uL and our is: %uL", + log->filename, + from_rev, + log->cur_seq); *rep = NULL; *from_time = 0; return FALSE; @@ -443,15 +522,24 @@ binlog_sync (struct rspamd_binlog *log, guint64 from_rev, guint64 *from_time, GB lock_file (log->fd, FALSE); idxb = g_malloc (sizeof (struct rspamd_index_block)); idx_mapped = TRUE; - if (lseek (log->fd, log->metaindex->indexes[metaindex_num], SEEK_SET) == -1) { + if (lseek (log->fd, log->metaindex->indexes[metaindex_num], + SEEK_SET) == -1) { unlock_file (log->fd, FALSE); - msg_warn ("cannot seek file %s, error %d, %s", log->filename, errno, strerror (errno)); + msg_warn ("cannot seek file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); res = FALSE; goto end; } - if ((read (log->fd, idxb, sizeof (struct rspamd_index_block))) != sizeof (struct rspamd_index_block)) { + if ((read (log->fd, idxb, + sizeof (struct rspamd_index_block))) != + sizeof (struct rspamd_index_block)) { unlock_file (log->fd, FALSE); - msg_warn ("cannot read index from file %s, error %d, %s", log->filename, errno, strerror (errno)); + msg_warn ("cannot read index from file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); res = FALSE; goto end; } @@ -474,17 +562,27 @@ binlog_sync (struct rspamd_binlog *log, guint64 from_rev, guint64 *from_time, GB /* Now fill reply structure */ (*rep)->len = idx->len; /* Read result */ - msg_info ("update from binlog '%s' from revision: %uL to revision %uL size is %uL", - log->filename, from_rev, log->cur_seq, idx->len); + msg_info ( + "update from binlog '%s' from revision: %uL to revision %uL size is %uL", + log->filename, + from_rev, + log->cur_seq, + idx->len); if (lseek (log->fd, idx->seek, SEEK_SET) == -1) { - msg_warn ("cannot seek file %s, error %d, %s", log->filename, errno, strerror (errno)); + msg_warn ("cannot seek file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); res = FALSE; goto end; } - + (*rep)->data = g_malloc (idx->len); if ((read (log->fd, (*rep)->data, idx->len)) != (ssize_t)idx->len) { - msg_warn ("cannot read file %s, error %d, %s", log->filename, errno, strerror (errno)); + msg_warn ("cannot read file %s, error %d, %s", + log->filename, + errno, + strerror (errno)); res = FALSE; goto end; } @@ -517,8 +615,11 @@ maybe_init_static (void) return TRUE; } -gboolean -maybe_write_binlog (struct rspamd_classifier_config *ccf, struct rspamd_statfile_config *st, stat_file_t *file, GTree *nodes) +gboolean +maybe_write_binlog (struct rspamd_classifier_config *ccf, + struct rspamd_statfile_config *st, + stat_file_t *file, + GTree *nodes) { struct rspamd_binlog *log; @@ -526,8 +627,9 @@ maybe_write_binlog (struct rspamd_classifier_config *ccf, struct rspamd_statfile return FALSE; } - - if (st == NULL || nodes == NULL || st->binlog == NULL || st->binlog->affinity != AFFINITY_MASTER) { + + if (st == NULL || nodes == NULL || st->binlog == NULL || + st->binlog->affinity != AFFINITY_MASTER) { return FALSE; } @@ -536,7 +638,9 @@ maybe_write_binlog (struct rspamd_classifier_config *ccf, struct rspamd_statfile } if ((log = g_hash_table_lookup (binlog_opened, st)) == NULL) { - if ((log = binlog_open (binlog_pool, st->path, st->binlog->rotate_time, st->binlog->rotate_time / 2)) != NULL) { + if ((log = + binlog_open (binlog_pool, st->path, st->binlog->rotate_time, + st->binlog->rotate_time / 2)) != NULL) { g_hash_table_insert (binlog_opened, st, log); } else { @@ -545,7 +649,9 @@ maybe_write_binlog (struct rspamd_classifier_config *ccf, struct rspamd_statfile } if (binlog_insert (log, nodes)) { - msg_info ("set new revision of statfile %s: %uL", st->symbol, log->cur_seq); + msg_info ("set new revision of statfile %s: %uL", + st->symbol, + log->cur_seq); (void)statfile_set_revision (file, log->cur_seq, log->cur_time); return TRUE; } @@ -553,12 +659,13 @@ maybe_write_binlog (struct rspamd_classifier_config *ccf, struct rspamd_statfile return FALSE; } -struct rspamd_binlog* +struct rspamd_binlog * get_binlog_by_statfile (struct rspamd_statfile_config *st) { struct rspamd_binlog *log; - if (st == NULL || st->binlog == NULL || st->binlog->affinity != AFFINITY_MASTER) { + if (st == NULL || st->binlog == NULL || st->binlog->affinity != + AFFINITY_MASTER) { return NULL; } @@ -567,13 +674,15 @@ get_binlog_by_statfile (struct rspamd_statfile_config *st) } if ((log = g_hash_table_lookup (binlog_opened, st)) == NULL) { - if ((log = binlog_open (binlog_pool, st->path, st->binlog->rotate_time, st->binlog->rotate_time / 2)) != NULL) { + if ((log = + binlog_open (binlog_pool, st->path, st->binlog->rotate_time, + st->binlog->rotate_time / 2)) != NULL) { g_hash_table_insert (binlog_opened, st, log); } else { return NULL; } } - + return log; } diff --git a/src/libserver/binlog.h b/src/libserver/binlog.h index 6b77a7613..c18a201f2 100644 --- a/src/libserver/binlog.h +++ b/src/libserver/binlog.h @@ -58,12 +58,15 @@ struct rspamd_classifier_config; /* * Open binlog at specified path with specified rotate params */ -struct rspamd_binlog* binlog_open (rspamd_mempool_t *pool, const gchar *path, time_t rotate_time, gint rotate_jitter); +struct rspamd_binlog * binlog_open (rspamd_mempool_t *pool, + const gchar *path, + time_t rotate_time, + gint rotate_jitter); /* * Get and open binlog for specified statfile */ -struct rspamd_binlog* get_binlog_by_statfile (struct rspamd_statfile_config *st); +struct rspamd_binlog * get_binlog_by_statfile (struct rspamd_statfile_config *st); /* * Close binlog @@ -83,11 +86,17 @@ gboolean binlog_insert (struct rspamd_binlog *log, GTree *nodes); * @param rep a portion of changes for revision is stored here * @return TRUE if there are more revisions to get and FALSE if synchronization is complete */ -gboolean binlog_sync (struct rspamd_binlog *log, guint64 from_rev, guint64 *from_time, GByteArray **rep); +gboolean binlog_sync (struct rspamd_binlog *log, + guint64 from_rev, + guint64 *from_time, + GByteArray **rep); /* * Conditional write to a binlog for specified statfile */ -gboolean maybe_write_binlog (struct rspamd_classifier_config *ccf, struct rspamd_statfile_config *st, stat_file_t *file, GTree *nodes); +gboolean maybe_write_binlog (struct rspamd_classifier_config *ccf, + struct rspamd_statfile_config *st, + stat_file_t *file, + GTree *nodes); #endif diff --git a/src/libserver/buffer.c b/src/libserver/buffer.c index 864f2fad6..403b3dafd 100644 --- a/src/libserver/buffer.c +++ b/src/libserver/buffer.c @@ -29,12 +29,15 @@ #include <sys/sendfile.h> #endif -#define G_DISPATCHER_ERROR dispatcher_error_quark() -#define debug_ip(...) rspamd_conditional_debug(rspamd_main->logger, NULL, __FUNCTION__, __VA_ARGS__) +#define G_DISPATCHER_ERROR dispatcher_error_quark () +#define debug_ip(...) rspamd_conditional_debug (rspamd_main->logger, \ + NULL, \ + __FUNCTION__, \ + __VA_ARGS__) -static void dispatcher_cb (gint fd, short what, void *arg); +static void dispatcher_cb (gint fd, short what, void *arg); -static inline GQuark +static inline GQuark dispatcher_error_quark (void) { return g_quark_from_static_string ("g-dispatcher-error-quark"); @@ -44,11 +47,11 @@ static gboolean sendfile_callback (rspamd_io_dispatcher_t *d) { - GError *err; + GError *err; #ifdef HAVE_SENDFILE # if defined(FREEBSD) || defined(DARWIN) - off_t off = 0; + off_t off = 0; #if defined(FREEBSD) /* FreeBSD version */ if (sendfile (d->sendfile_fd, d->fd, d->offset, 0, NULL, &off, 0) != 0) { @@ -58,13 +61,15 @@ sendfile_callback (rspamd_io_dispatcher_t *d) #endif if (errno != EAGAIN) { if (d->err_callback) { - err = g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror (errno)); + err = + g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror ( + errno)); d->err_callback (err, d->user_data); return FALSE; } } else { - debug_ip("partially write data, retry"); + debug_ip ("partially write data, retry"); /* Wait for other event */ d->offset += off; event_del (d->ev); @@ -76,30 +81,33 @@ sendfile_callback (rspamd_io_dispatcher_t *d) else { if (d->write_callback) { if (!d->write_callback (d->user_data)) { - debug_ip("callback set wanna_die flag, terminating"); + debug_ip ("callback set wanna_die flag, terminating"); return FALSE; } } event_del (d->ev); - event_set (d->ev, d->fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); + event_set (d->ev, d->fd, EV_READ | EV_PERSIST, dispatcher_cb, + (void *)d); event_base_set (d->ev_base, d->ev); event_add (d->ev, d->tv); d->in_sendfile = FALSE; } # else - ssize_t r; + ssize_t r; /* Linux version */ r = sendfile (d->fd, d->sendfile_fd, &d->offset, d->file_size); if (r == -1) { if (errno != EAGAIN) { if (d->err_callback) { - err = g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror (errno)); + err = + g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror ( + errno)); d->err_callback (err, d->user_data); return FALSE; } } else { - debug_ip("partially write data, retry"); + debug_ip ("partially write data, retry"); /* Wait for other event */ event_del (d->ev); event_set (d->ev, d->fd, EV_WRITE, dispatcher_cb, (void *)d); @@ -108,7 +116,7 @@ sendfile_callback (rspamd_io_dispatcher_t *d) } } else if (r + d->offset < (ssize_t)d->file_size) { - debug_ip("partially write data, retry"); + debug_ip ("partially write data, retry"); /* Wait for other event */ event_del (d->ev); event_set (d->ev, d->fd, EV_WRITE, dispatcher_cb, (void *)d); @@ -118,30 +126,33 @@ sendfile_callback (rspamd_io_dispatcher_t *d) else { if (d->write_callback) { if (!d->write_callback (d->user_data)) { - debug_ip("callback set wanna_die flag, terminating"); + debug_ip ("callback set wanna_die flag, terminating"); return FALSE; } } event_del (d->ev); - event_set (d->ev, d->fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); + event_set (d->ev, d->fd, EV_READ | EV_PERSIST, dispatcher_cb, + (void *)d); event_base_set (d->ev_base, d->ev); event_add (d->ev, d->tv); d->in_sendfile = FALSE; } # endif #else - ssize_t r; + ssize_t r; r = write (d->fd, d->map, d->file_size - d->offset); if (r == -1) { if (errno != EAGAIN) { if (d->err_callback) { - err = g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror (errno)); + err = + g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror ( + errno)); d->err_callback (err, d->user_data); return FALSE; } } else { - debug_ip("partially write data, retry"); + debug_ip ("partially write data, retry"); /* Wait for other event */ event_del (d->ev); event_set (d->ev, d->fd, EV_WRITE, dispatcher_cb, (void *)d); @@ -151,7 +162,7 @@ sendfile_callback (rspamd_io_dispatcher_t *d) } else if (r + d->offset < d->file_size) { d->offset += r; - debug_ip("partially write data, retry"); + debug_ip ("partially write data, retry"); /* Wait for other event */ event_del (d->ev); event_set (d->ev, d->fd, EV_WRITE, dispatcher_cb, (void *)d); @@ -161,12 +172,13 @@ sendfile_callback (rspamd_io_dispatcher_t *d) else { if (d->write_callback) { if (!d->write_callback (d->user_data)) { - debug_ip("callback set wanna_die flag, terminating"); + debug_ip ("callback set wanna_die flag, terminating"); return FALSE; } } event_del (d->ev); - event_set (d->ev, d->fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); + event_set (d->ev, d->fd, EV_READ | EV_PERSIST, dispatcher_cb, + (void *)d); event_base_set (d->ev_base, d->ev); event_add (d->ev, d->tv); d->in_sendfile = FALSE; @@ -177,25 +189,25 @@ sendfile_callback (rspamd_io_dispatcher_t *d) #define BUFREMAIN(x) (x)->data->size - ((x)->pos - (x)->data->begin) -#define APPEND_OUT_BUFFER(d, buf) do { \ - DL_APPEND((d)->out_buffers.buffers, buf); \ - (d)->out_buffers.pending ++; \ - } while (0) -#define DELETE_OUT_BUFFER(d, buf) do { \ - DL_DELETE((d)->out_buffers.buffers, (buf)); \ - g_string_free((buf->data), (buf)->allocated); \ - g_slice_free1(sizeof (struct rspamd_out_buffer_s), (buf)); \ - (d)->out_buffers.pending --; \ - } while (0) - -static gboolean +#define APPEND_OUT_BUFFER(d, buf) do { \ + DL_APPEND ((d)->out_buffers.buffers, buf); \ + (d)->out_buffers.pending++; \ +} while (0) +#define DELETE_OUT_BUFFER(d, buf) do { \ + DL_DELETE ((d)->out_buffers.buffers, (buf)); \ + g_string_free ((buf->data), (buf)->allocated); \ + g_slice_free1 (sizeof (struct rspamd_out_buffer_s), (buf)); \ + (d)->out_buffers.pending--; \ +} while (0) + +static gboolean write_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean is_delayed) { - GError *err = NULL; - struct rspamd_out_buffer_s *cur = NULL, *tmp; - ssize_t r; - struct iovec *iov; - guint i, len; + GError *err = NULL; + struct rspamd_out_buffer_s *cur = NULL, *tmp; + ssize_t r; + struct iovec *iov; + guint i, len; len = d->out_buffers.pending; while (len > 0) { @@ -203,24 +215,28 @@ write_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean is_delayed) is_delayed = TRUE; iov = g_slice_alloc (len * sizeof (struct iovec)); i = 0; - DL_FOREACH_SAFE (d->out_buffers.buffers, cur, tmp) { + DL_FOREACH_SAFE (d->out_buffers.buffers, cur, tmp) + { iov[i].iov_base = cur->data->str; iov[i].iov_len = cur->data->len; - i ++; + i++; } /* Now try to write the whole vector */ r = writev (fd, iov, len); if (r == -1 && errno != EAGAIN) { g_slice_free1 (len * sizeof (struct iovec), iov); if (d->err_callback) { - err = g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror (errno)); + err = + g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror ( + errno)); d->err_callback (err, d->user_data); return FALSE; } } else if (r > 0) { /* Find pos inside buffers */ - DL_FOREACH_SAFE (d->out_buffers.buffers, cur, tmp) { + DL_FOREACH_SAFE (d->out_buffers.buffers, cur, tmp) + { if (r >= (ssize_t)cur->data->len) { /* Mark this buffer as read */ r -= cur->data->len; @@ -253,7 +269,7 @@ write_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean is_delayed) } else if (r == -1 && errno == EAGAIN) { g_slice_free1 (len * sizeof (struct iovec), iov); - debug_ip("partially write data, retry"); + debug_ip ("partially write data, retry"); /* Wait for other event */ event_del (d->ev); event_set (d->ev, fd, EV_WRITE, dispatcher_cb, (void *)d); @@ -271,7 +287,7 @@ write_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean is_delayed) if (is_delayed && d->write_callback) { if (!d->write_callback (d->user_data)) { - debug_ip("callback set wanna_die flag, terminating"); + debug_ip ("callback set wanna_die flag, terminating"); return FALSE; } } @@ -295,13 +311,13 @@ write_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean is_delayed) static void read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) { - ssize_t r; - GError *err = NULL; - f_str_t res; - gchar *c, *b; - gchar *end; - size_t len; - enum io_policy saved_policy; + ssize_t r; + GError *err = NULL; + f_str_t res; + gchar *c, *b; + gchar *end; + size_t len; + enum io_policy saved_policy; if (d->wanna_die) { rspamd_remove_dispatcher (d); @@ -309,7 +325,8 @@ read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) } if (d->in_buf == NULL) { - d->in_buf = rspamd_mempool_alloc_tmp (d->pool, sizeof (rspamd_buffer_t)); + d->in_buf = + rspamd_mempool_alloc_tmp (d->pool, sizeof (rspamd_buffer_t)); if (d->policy == BUFFER_LINE || d->policy == BUFFER_ANY) { d->in_buf->data = fstralloc_tmp (d->pool, d->default_buf_size); } @@ -335,7 +352,9 @@ read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) r = read (fd, end, BUFREMAIN (d->in_buf)); if (r == -1 && errno != EAGAIN) { if (d->err_callback) { - err = g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror (errno)); + err = + g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror ( + errno)); d->err_callback (err, d->user_data); return; } @@ -364,7 +383,7 @@ read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) } } else if (r == -1 && errno == EAGAIN) { - debug_ip("partially read data, retry"); + debug_ip ("partially read data, retry"); return; } else { @@ -372,8 +391,12 @@ read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) d->in_buf->pos += r; d->in_buf->data->len += r; } - debug_ip("read %z characters, policy is %s, watermark is: %z, buffer has %z bytes", r, - d->policy == BUFFER_LINE ? "LINE" : "CHARACTER", d->nchars, d->in_buf->data->len); + debug_ip ( + "read %z characters, policy is %s, watermark is: %z, buffer has %z bytes", + r, + d->policy == BUFFER_LINE ? "LINE" : "CHARACTER", + d->nchars, + d->in_buf->data->len); } saved_policy = d->policy; @@ -382,16 +405,16 @@ read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) len = d->in_buf->data->len; b = c; r = 0; - + switch (d->policy) { case BUFFER_LINE: /** Variables: - * b - begin of line - * r - current position in buffer - * *len - length of remaining buffer - * c - pointer to current position (buffer->begin + r) - * res - result string - */ + * b - begin of line + * r - current position in buffer + * *len - length of remaining buffer + * c - pointer to current position (buffer->begin + r) + * res - result string + */ while (r < (ssize_t)len) { if (*c == '\n') { res.begin = b; @@ -404,7 +427,7 @@ read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) } else { /* Include EOL in reply */ - res.len ++; + res.len++; } /* Call callback for a line */ if (d->read_callback) { @@ -468,7 +491,8 @@ read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) d->in_buf->pos = d->in_buf->data->begin; } if (d->policy != saved_policy && (ssize_t)len != r) { - debug_ip("policy changed during callback, restart buffer's processing"); + debug_ip ( + "policy changed during callback, restart buffer's processing"); read_buffers (fd, d, TRUE); return; } @@ -484,13 +508,14 @@ read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) * Actually we do not want to send zero sized * buffers to a read callback */ - if (! (d->want_read && res.len == 0)) { + if (!(d->want_read && res.len == 0)) { if (!d->read_callback (&res, d->user_data)) { return; } } if (d->policy != saved_policy) { - debug_ip("policy changed during callback, restart buffer's processing"); + debug_ip ( + "policy changed during callback, restart buffer's processing"); read_buffers (fd, d, TRUE); return; } @@ -506,10 +531,10 @@ read_buffers (gint fd, rspamd_io_dispatcher_t * d, gboolean skip_read) static void dispatcher_cb (gint fd, short what, void *arg) { - rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *) arg; - GError *err = NULL; + rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *) arg; + GError *err = NULL; - debug_ip("in dispatcher callback, what: %d, fd: %d", (gint)what, fd); + debug_ip ("in dispatcher callback, what: %d, fd: %d", (gint)what, fd); if ((what & EV_TIMEOUT) != 0) { if (d->err_callback) { @@ -538,7 +563,8 @@ dispatcher_cb (gint fd, short what, void *arg) else { /* Want read again */ event_del (d->ev); - event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); + event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, + (void *)d); event_base_set (d->ev_base, d->ev); event_add (d->ev, d->tv); if (d->is_restored && d->write_callback) { @@ -558,11 +584,17 @@ dispatcher_cb (gint fd, short what, void *arg) } -rspamd_io_dispatcher_t * -rspamd_create_dispatcher (struct event_base *base, gint fd, enum io_policy policy, - dispatcher_read_callback_t read_cb, dispatcher_write_callback_t write_cb, dispatcher_err_callback_t err_cb, struct timeval *tv, void *user_data) +rspamd_io_dispatcher_t * +rspamd_create_dispatcher (struct event_base *base, + gint fd, + enum io_policy policy, + dispatcher_read_callback_t read_cb, + dispatcher_write_callback_t write_cb, + dispatcher_err_callback_t err_cb, + struct timeval *tv, + void *user_data) { - rspamd_io_dispatcher_t *new; + rspamd_io_dispatcher_t *new; if (fd == -1) { return NULL; @@ -608,7 +640,8 @@ rspamd_remove_dispatcher (rspamd_io_dispatcher_t * d) struct rspamd_out_buffer_s *cur, *tmp; if (d != NULL) { - DL_FOREACH_SAFE (d->out_buffers.buffers, cur, tmp) { + DL_FOREACH_SAFE (d->out_buffers.buffers, cur, tmp) + { DELETE_OUT_BUFFER (d, cur); } event_del (d->ev); @@ -618,10 +651,12 @@ rspamd_remove_dispatcher (rspamd_io_dispatcher_t * d) } void -rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t * d, enum io_policy policy, size_t nchars) +rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t * d, + enum io_policy policy, + size_t nchars) { - f_str_t *tmp; - gint t; + f_str_t *tmp; + gint t; if (d->policy != policy || nchars != d->nchars) { d->policy = policy; @@ -630,7 +665,8 @@ rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t * d, enum io_policy policy, if (policy == BUFFER_CHARACTER && nchars != 0) { if (d->in_buf && d->in_buf->data->size < nchars) { tmp = fstralloc_tmp (d->pool, d->nchars + 1); - memcpy (tmp->begin, d->in_buf->data->begin, d->in_buf->data->len); + memcpy (tmp->begin, d->in_buf->data->begin, + d->in_buf->data->len); t = d->in_buf->pos - d->in_buf->data->begin; tmp->len = d->in_buf->data->len; d->in_buf->data = tmp; @@ -640,7 +676,8 @@ rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t * d, enum io_policy policy, else if (policy == BUFFER_LINE || policy == BUFFER_ANY) { if (d->in_buf && d->nchars < d->default_buf_size) { tmp = fstralloc_tmp (d->pool, d->default_buf_size); - memcpy (tmp->begin, d->in_buf->data->begin, d->in_buf->data->len); + memcpy (tmp->begin, d->in_buf->data->begin, + d->in_buf->data->len); t = d->in_buf->pos - d->in_buf->data->begin; tmp->len = d->in_buf->data->len; d->in_buf->data = tmp; @@ -650,14 +687,14 @@ rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t * d, enum io_policy policy, } } - debug_ip("new input length watermark is %uz", d->nchars); + debug_ip ("new input length watermark is %uz", d->nchars); } gboolean rspamd_dispatcher_write (rspamd_io_dispatcher_t * d, - const void *data, size_t len, gboolean delayed, gboolean allocated) + const void *data, size_t len, gboolean delayed, gboolean allocated) { - struct rspamd_out_buffer_s *newbuf; + struct rspamd_out_buffer_s *newbuf; newbuf = g_slice_alloc (sizeof (struct rspamd_out_buffer_s)); if (len == 0) { @@ -680,7 +717,7 @@ rspamd_dispatcher_write (rspamd_io_dispatcher_t * d, APPEND_OUT_BUFFER (d, newbuf); if (!delayed) { - debug_ip("plan write event"); + debug_ip ("plan write event"); return write_buffers (d->fd, d, FALSE); } /* Otherwise plan write event */ @@ -692,12 +729,13 @@ rspamd_dispatcher_write (rspamd_io_dispatcher_t * d, return TRUE; } -gboolean rspamd_dispatcher_write_string (rspamd_io_dispatcher_t *d, - GString *str, - gboolean delayed, - gboolean free_on_write) +gboolean +rspamd_dispatcher_write_string (rspamd_io_dispatcher_t *d, + GString *str, + gboolean delayed, + gboolean free_on_write) { - struct rspamd_out_buffer_s *newbuf; + struct rspamd_out_buffer_s *newbuf; newbuf = g_slice_alloc (sizeof (struct rspamd_out_buffer_s)); newbuf->data = str; @@ -706,7 +744,7 @@ gboolean rspamd_dispatcher_write_string (rspamd_io_dispatcher_t *d, APPEND_OUT_BUFFER (d, newbuf); if (!delayed) { - debug_ip("plan write event"); + debug_ip ("plan write event"); return write_buffers (d->fd, d, FALSE); } /* Otherwise plan write event */ @@ -718,7 +756,7 @@ gboolean rspamd_dispatcher_write_string (rspamd_io_dispatcher_t *d, return TRUE; } -gboolean +gboolean rspamd_dispatcher_sendfile (rspamd_io_dispatcher_t *d, gint fd, size_t len) { if (lseek (fd, 0, SEEK_SET) == -1) { @@ -733,9 +771,12 @@ rspamd_dispatcher_sendfile (rspamd_io_dispatcher_t *d, gint fd, size_t len) #ifndef HAVE_SENDFILE #ifdef HAVE_MMAP_NOCORE - if ((d->map = mmap (NULL, len, PROT_READ, MAP_SHARED | MAP_NOCORE, fd, 0)) == MAP_FAILED) { + if ((d->map = + mmap (NULL, len, PROT_READ, MAP_SHARED | MAP_NOCORE, fd, + 0)) == MAP_FAILED) { #else - if ((d->map = mmap (NULL, len, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if ((d->map = + mmap (NULL, len, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { #endif msg_warn ("mmap failed: %s", strerror (errno)); return FALSE; @@ -771,7 +812,8 @@ rspamd_dispacther_cleanup (rspamd_io_dispatcher_t *d) { struct rspamd_out_buffer_s *cur, *tmp; - DL_FOREACH_SAFE (d->out_buffers.buffers, cur, tmp) { + DL_FOREACH_SAFE (d->out_buffers.buffers, cur, tmp) + { DELETE_OUT_BUFFER (d, cur); } /* Cleanup temporary data */ @@ -781,6 +823,6 @@ rspamd_dispacther_cleanup (rspamd_io_dispatcher_t *d) #undef debug_ip -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/libserver/buffer.h b/src/libserver/buffer.h index 5ed42bfb3..6795ff41d 100644 --- a/src/libserver/buffer.h +++ b/src/libserver/buffer.h @@ -18,17 +18,17 @@ typedef void (*dispatcher_err_callback_t)(GError *err, void *user_data); * Types of IO handling */ enum io_policy { - BUFFER_LINE, /**< call handler when we have line ready */ - BUFFER_CHARACTER, /**< call handler when we have some characters */ - BUFFER_ANY /**< call handler whenever we got data in buffer */ + BUFFER_LINE, /**< call handler when we have line ready */ + BUFFER_CHARACTER, /**< call handler when we have some characters */ + BUFFER_ANY /**< call handler whenever we got data in buffer */ }; /** * Buffer structure */ typedef struct rspamd_buffer_s { - f_str_t *data; /**< buffer logic */ - gchar *pos; /**< current position */ + f_str_t *data; /**< buffer logic */ + gchar *pos; /**< current position */ } rspamd_buffer_t; struct rspamd_out_buffer_s { @@ -38,33 +38,33 @@ struct rspamd_out_buffer_s { }; typedef struct rspamd_io_dispatcher_s { - rspamd_buffer_t *in_buf; /**< input buffer */ + rspamd_buffer_t *in_buf; /**< input buffer */ struct { guint pending; struct rspamd_out_buffer_s *buffers; - } out_buffers; /**< output buffers chain */ - struct timeval *tv; /**< io timeout */ - struct event *ev; /**< libevent io event */ - rspamd_mempool_t *pool; /**< where to store data */ - enum io_policy policy; /**< IO policy */ - size_t nchars; /**< how many chars to read */ - gint fd; /**< descriptor */ - guint32 peer_addr; /**< address of peer for debugging */ - gboolean wanna_die; /**< if dispatcher should be stopped */ - dispatcher_read_callback_t read_callback; /**< read callback */ - dispatcher_write_callback_t write_callback; /**< write callback */ - dispatcher_err_callback_t err_callback; /**< error callback */ - void *user_data; /**< user's data for callbacks */ - gulong default_buf_size; /**< default size for buffering */ - off_t offset; /**< for sendfile use */ + } out_buffers; /**< output buffers chain */ + struct timeval *tv; /**< io timeout */ + struct event *ev; /**< libevent io event */ + rspamd_mempool_t *pool; /**< where to store data */ + enum io_policy policy; /**< IO policy */ + size_t nchars; /**< how many chars to read */ + gint fd; /**< descriptor */ + guint32 peer_addr; /**< address of peer for debugging */ + gboolean wanna_die; /**< if dispatcher should be stopped */ + dispatcher_read_callback_t read_callback; /**< read callback */ + dispatcher_write_callback_t write_callback; /**< write callback */ + dispatcher_err_callback_t err_callback; /**< error callback */ + void *user_data; /**< user's data for callbacks */ + gulong default_buf_size; /**< default size for buffering */ + off_t offset; /**< for sendfile use */ size_t file_size; gint sendfile_fd; - gboolean in_sendfile; /**< whether buffer is in sendfile mode */ - gboolean strip_eol; /**< strip or not line ends in BUFFER_LINE policy */ - gboolean is_restored; /**< call a callback when dispatcher is restored */ - gboolean half_closed; /**< connection is half closed */ - gboolean want_read; /**< whether we want to read more data */ - struct event_base *ev_base; /**< event base for io operations */ + gboolean in_sendfile; /**< whether buffer is in sendfile mode */ + gboolean strip_eol; /**< strip or not line ends in BUFFER_LINE policy */ + gboolean is_restored; /**< call a callback when dispatcher is restored */ + gboolean half_closed; /**< connection is half closed */ + gboolean want_read; /**< whether we want to read more data */ + struct event_base *ev_base; /**< event base for io operations */ #ifndef HAVE_SENDFILE void *map; #endif @@ -81,13 +81,14 @@ typedef struct rspamd_io_dispatcher_s { * @param user_data pointer to user's data * @return new dispatcher object or NULL in case of failure */ -rspamd_io_dispatcher_t* rspamd_create_dispatcher (struct event_base *base, gint fd, - enum io_policy policy, - dispatcher_read_callback_t read_cb, - dispatcher_write_callback_t write_cb, - dispatcher_err_callback_t err_cb, - struct timeval *tv, - void *user_data); +rspamd_io_dispatcher_t * rspamd_create_dispatcher (struct event_base *base, + gint fd, + enum io_policy policy, + dispatcher_read_callback_t read_cb, + dispatcher_write_callback_t write_cb, + dispatcher_err_callback_t err_cb, + struct timeval *tv, + void *user_data); /** * Set new policy for dispatcher @@ -95,9 +96,9 @@ rspamd_io_dispatcher_t* rspamd_create_dispatcher (struct event_base *base, gint * @param policy IO policy * @param nchars number of characters in buffer for character policy */ -void rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t *d, - enum io_policy policy, - size_t nchars); +void rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t *d, + enum io_policy policy, + size_t nchars); /** * Write data when it would be possible @@ -106,9 +107,9 @@ void rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t *d, * @param len length of data */ gboolean rspamd_dispatcher_write (rspamd_io_dispatcher_t *d, - const void *data, - size_t len, gboolean delayed, - gboolean allocated) G_GNUC_WARN_UNUSED_RESULT; + const void *data, + size_t len, gboolean delayed, + gboolean allocated) G_GNUC_WARN_UNUSED_RESULT; /** * Write a GString to dispatcher @@ -119,9 +120,9 @@ gboolean rspamd_dispatcher_write (rspamd_io_dispatcher_t *d, * @return TRUE if write has been queued successfully */ gboolean rspamd_dispatcher_write_string (rspamd_io_dispatcher_t *d, - GString *str, - gboolean delayed, - gboolean free_on_write) G_GNUC_WARN_UNUSED_RESULT; + GString *str, + gboolean delayed, + gboolean free_on_write) G_GNUC_WARN_UNUSED_RESULT; /** * Send specified descriptor to dispatcher @@ -129,7 +130,9 @@ gboolean rspamd_dispatcher_write_string (rspamd_io_dispatcher_t *d, * @param fd descriptor of file * @param len length of data */ -gboolean rspamd_dispatcher_sendfile (rspamd_io_dispatcher_t *d, gint fd, size_t len) G_GNUC_WARN_UNUSED_RESULT; +gboolean rspamd_dispatcher_sendfile (rspamd_io_dispatcher_t *d, + gint fd, + size_t len) G_GNUC_WARN_UNUSED_RESULT; /** * Pause IO events on dispatcher diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h index f502d5775..cb62d9640 100644 --- a/src/libserver/cfg_file.h +++ b/src/libserver/cfg_file.h @@ -72,22 +72,22 @@ enum rspamd_log_type { * Regexp structure */ struct rspamd_regexp { - enum rspamd_regexp_type type; /**< regexp type */ - gchar *regexp_text; /**< regexp text representation */ - GRegex *regexp; /**< glib regexp structure */ - GRegex *raw_regexp; /**< glib regexp structure for raw matching */ - gchar *header; /**< header name for header regexps */ - gboolean is_test; /**< true if this expression must be tested */ - gboolean is_raw; /**< true if this regexp is done by raw matching */ - gboolean is_strong; /**< true if headers search must be case sensitive */ + enum rspamd_regexp_type type; /**< regexp type */ + gchar *regexp_text; /**< regexp text representation */ + GRegex *regexp; /**< glib regexp structure */ + GRegex *raw_regexp; /**< glib regexp structure for raw matching */ + gchar *header; /**< header name for header regexps */ + gboolean is_test; /**< true if this expression must be tested */ + gboolean is_raw; /**< true if this regexp is done by raw matching */ + gboolean is_strong; /**< true if headers search must be case sensitive */ }; /** * script module list item */ struct script_module { - gchar *name; /**< name of module */ - gchar *path; /**< path to module */ + gchar *name; /**< name of module */ + gchar *path; /**< path to module */ }; /** @@ -104,13 +104,13 @@ enum lua_var_type { * Module option */ struct rspamd_module_opt { - gchar *param; /**< parameter name */ - gchar *value; /**< parameter value */ - gchar *description; /**< parameter description */ - gchar *group; /**< parameter group */ - gpointer actual_data; /**< parsed data */ - gboolean is_lua; /**< actually this is lua variable */ - enum lua_var_type lua_type; /**< type of lua variable */ + gchar *param; /**< parameter name */ + gchar *value; /**< parameter value */ + gchar *description; /**< parameter description */ + gchar *group; /**< parameter group */ + gpointer actual_data; /**< parsed data */ + gboolean is_lua; /**< actually this is lua variable */ + enum lua_var_type lua_type; /**< type of lua variable */ }; /** @@ -134,22 +134,22 @@ struct rspamd_symbols_group { * Statfile section definition */ struct rspamd_statfile_section { - guint32 code; /**< section's code */ - guint64 size; /**< size of section */ - double weight; /**< weight coefficient for section */ + guint32 code; /**< section's code */ + guint64 size; /**< size of section */ + double weight; /**< weight coefficient for section */ }; /** * Statfile autolearn parameters */ struct statfile_autolearn_params { - const gchar *metric; /**< metric name for autolearn triggering */ - double threshold_min; /**< threshold mark */ - double threshold_max; /**< threshold mark */ - GList *symbols; /**< list of symbols */ + const gchar *metric; /**< metric name for autolearn triggering */ + double threshold_min; /**< threshold mark */ + double threshold_max; /**< threshold mark */ + GList *symbols; /**< list of symbols */ }; -/** +/** * Sync affinity */ enum sync_affinity { @@ -168,38 +168,39 @@ struct statfile_binlog_params { guint16 master_port; }; -typedef double (*statfile_normalize_func)(struct rspamd_config *cfg, long double score, void *params); +typedef double (*statfile_normalize_func)(struct rspamd_config *cfg, + long double score, void *params); /** * Statfile config definition */ struct rspamd_statfile_config { - gchar *symbol; /**< symbol of statfile */ - gchar *path; /**< filesystem pattern (with %r or %f) */ - gchar *label; /**< label of this statfile */ - gsize size; /**< size of statfile */ - GList *sections; /**< list of sections in statfile */ - struct statfile_autolearn_params *autolearn; /**< autolearn params */ - struct statfile_binlog_params *binlog; /**< binlog params */ - statfile_normalize_func normalizer; /**< function that is used as normaliser */ - void *normalizer_data; /**< normalizer function params */ - gchar *normalizer_str; /**< source string (for dump) */ - ucl_object_t *opts; /**< other options */ - gboolean is_spam; /**< spam flag */ + gchar *symbol; /**< symbol of statfile */ + gchar *path; /**< filesystem pattern (with %r or %f) */ + gchar *label; /**< label of this statfile */ + gsize size; /**< size of statfile */ + GList *sections; /**< list of sections in statfile */ + struct statfile_autolearn_params *autolearn; /**< autolearn params */ + struct statfile_binlog_params *binlog; /**< binlog params */ + statfile_normalize_func normalizer; /**< function that is used as normaliser */ + void *normalizer_data; /**< normalizer function params */ + gchar *normalizer_str; /**< source string (for dump) */ + ucl_object_t *opts; /**< other options */ + gboolean is_spam; /**< spam flag */ }; /** * Classifier config definition */ struct rspamd_classifier_config { - GList *statfiles; /**< statfiles list */ - GHashTable *labels; /**< statfiles with labels */ - gchar *metric; /**< metric of this classifier */ - struct classifier *classifier; /**< classifier interface */ - struct tokenizer *tokenizer; /**< tokenizer used for classifier */ - GHashTable *opts; /**< other options */ - GList *pre_callbacks; /**< list of callbacks that are called before classification */ - GList *post_callbacks; /**< list of callbacks that are called after classification */ + GList *statfiles; /**< statfiles list */ + GHashTable *labels; /**< statfiles with labels */ + gchar *metric; /**< metric of this classifier */ + struct classifier *classifier; /**< classifier interface */ + struct tokenizer *tokenizer; /**< tokenizer used for classifier */ + GHashTable *opts; /**< other options */ + GList *pre_callbacks; /**< list of callbacks that are called before classification */ + GList *post_callbacks; /**< list of callbacks that are called after classification */ }; struct rspamd_worker_bind_conf { @@ -211,135 +212,135 @@ struct rspamd_worker_bind_conf { }; struct rspamd_worker_param_parser { - rspamd_rcl_handler_t handler; /**< handler function */ - struct rspamd_rcl_struct_parser parser; /**< parser attributes */ - const gchar *name; /**< parameter's name */ - UT_hash_handle hh; /**< hash by name */ + rspamd_rcl_handler_t handler; /**< handler function */ + struct rspamd_rcl_struct_parser parser; /**< parser attributes */ + const gchar *name; /**< parameter's name */ + UT_hash_handle hh; /**< hash by name */ }; struct rspamd_worker_cfg_parser { - struct rspamd_worker_param_parser *parsers; /**< parsers hash */ - gint type; /**< workers quark */ - gboolean (*def_obj_parser)(const ucl_object_t *obj, gpointer ud); /**< default object parser */ + struct rspamd_worker_param_parser *parsers; /**< parsers hash */ + gint type; /**< workers quark */ + gboolean (*def_obj_parser)(const ucl_object_t *obj, gpointer ud); /**< default object parser */ gpointer def_ud; - UT_hash_handle hh; /**< hash by type */ + UT_hash_handle hh; /**< hash by type */ }; /** * Config params for rspamd worker */ struct rspamd_worker_conf { - worker_t *worker; /**< pointer to worker type */ - GQuark type; /**< type of worker */ - struct rspamd_worker_bind_conf *bind_conf; /**< bind configuration */ - guint16 count; /**< number of workers */ - GList *listen_socks; /**< listening sockets desctiptors */ - guint32 rlimit_nofile; /**< max files limit */ - guint32 rlimit_maxcore; /**< maximum core file size */ - GHashTable *params; /**< params for worker */ - GQueue *active_workers; /**< linked list of spawned workers */ - gboolean has_socket; /**< whether we should make listening socket in main process */ - gpointer *ctx; /**< worker's context */ - ucl_object_t *options; /**< other worker's options */ + worker_t *worker; /**< pointer to worker type */ + GQuark type; /**< type of worker */ + struct rspamd_worker_bind_conf *bind_conf; /**< bind configuration */ + guint16 count; /**< number of workers */ + GList *listen_socks; /**< listening sockets desctiptors */ + guint32 rlimit_nofile; /**< max files limit */ + guint32 rlimit_maxcore; /**< maximum core file size */ + GHashTable *params; /**< params for worker */ + GQueue *active_workers; /**< linked list of spawned workers */ + gboolean has_socket; /**< whether we should make listening socket in main process */ + gpointer *ctx; /**< worker's context */ + ucl_object_t *options; /**< other worker's options */ }; /** * Structure that stores all config data */ struct rspamd_config { - gchar *rspamd_user; /**< user to run as */ - gchar *rspamd_group; /**< group to run as */ - rspamd_mempool_t *cfg_pool; /**< memory pool for config */ - gchar *cfg_name; /**< name of config file */ - gchar *pid_file; /**< name of pid file */ - gchar *temp_dir; /**< dir for temp files */ + gchar *rspamd_user; /**< user to run as */ + gchar *rspamd_group; /**< group to run as */ + rspamd_mempool_t *cfg_pool; /**< memory pool for config */ + gchar *cfg_name; /**< name of config file */ + gchar *pid_file; /**< name of pid file */ + gchar *temp_dir; /**< dir for temp files */ #ifdef WITH_GPERF_TOOLS gchar *profile_path; #endif - gboolean no_fork; /**< if 1 do not call daemon() */ - gboolean config_test; /**< if TRUE do only config file test */ - gboolean raw_mode; /**< work in raw mode instead of utf one */ - gboolean one_shot_mode; /**< rules add only one symbol */ - gboolean check_text_attachements; /**< check text attachements as text */ - gboolean convert_config; /**< convert config to XML format */ - gboolean strict_protocol_headers; /**< strictly check protocol headers */ - - gsize max_diff; /**< maximum diff size for text parts */ - - enum rspamd_log_type log_type; /**< log type */ - gint log_facility; /**< log facility in case of syslog */ - gint log_level; /**< log level trigger */ - gchar *log_file; /**< path to logfile in case of file logging */ - gboolean log_buffered; /**< whether logging is buffered */ - guint32 log_buf_size; /**< length of log buffer */ - gchar *debug_ip_map; /**< turn on debugging for specified ip addresses */ - gboolean log_urls; /**< whether we should log URLs */ - GList *debug_symbols; /**< symbols to debug */ - gboolean log_color; /**< output colors for console output */ - gboolean log_extended; /**< log extended information */ - - guint32 statfile_sync_interval; /**< synchronization interval */ - guint32 statfile_sync_timeout; /**< synchronization timeout */ - gboolean mlock_statfile_pool; /**< use mlock (2) for locking statfiles */ - - gboolean delivery_enable; /**< is delivery agent is enabled */ - gchar *deliver_host; /**< host for mail deliviring */ - struct in_addr deliver_addr; /**< its address */ - guint16 deliver_port; /**< port for deliviring */ - guint16 deliver_family; /**< socket family for delivirnig */ - gchar *deliver_agent_path; /**< deliver to pipe instead of socket */ - gboolean deliver_lmtp; /**< use LMTP instead of SMTP */ - - GList *script_modules; /**< linked list of script modules to load */ - - GList *filters; /**< linked list of all filters */ - GList *workers; /**< linked list of all workers params */ - struct rspamd_worker_cfg_parser *wrk_parsers; /**< hash for worker config parsers, indexed by worker quarks */ - gchar *filters_str; /**< string of filters */ - ucl_object_t *rcl_obj; /**< rcl object */ - GHashTable* metrics; /**< hash of metrics indexed by metric name */ - GList* symbols_groups; /**< groups of symbols */ - GList* metrics_list; /**< linked list of metrics */ - GHashTable* metrics_symbols; /**< hash table of metrics indexed by symbol */ - GHashTable* c_modules; /**< hash of c modules indexed by module name */ - GHashTable* composite_symbols; /**< hash of composite symbols indexed by its name */ + gboolean no_fork; /**< if 1 do not call daemon() */ + gboolean config_test; /**< if TRUE do only config file test */ + gboolean raw_mode; /**< work in raw mode instead of utf one */ + gboolean one_shot_mode; /**< rules add only one symbol */ + gboolean check_text_attachements; /**< check text attachements as text */ + gboolean convert_config; /**< convert config to XML format */ + gboolean strict_protocol_headers; /**< strictly check protocol headers */ + + gsize max_diff; /**< maximum diff size for text parts */ + + enum rspamd_log_type log_type; /**< log type */ + gint log_facility; /**< log facility in case of syslog */ + gint log_level; /**< log level trigger */ + gchar *log_file; /**< path to logfile in case of file logging */ + gboolean log_buffered; /**< whether logging is buffered */ + guint32 log_buf_size; /**< length of log buffer */ + gchar *debug_ip_map; /**< turn on debugging for specified ip addresses */ + gboolean log_urls; /**< whether we should log URLs */ + GList *debug_symbols; /**< symbols to debug */ + gboolean log_color; /**< output colors for console output */ + gboolean log_extended; /**< log extended information */ + + guint32 statfile_sync_interval; /**< synchronization interval */ + guint32 statfile_sync_timeout; /**< synchronization timeout */ + gboolean mlock_statfile_pool; /**< use mlock (2) for locking statfiles */ + + gboolean delivery_enable; /**< is delivery agent is enabled */ + gchar *deliver_host; /**< host for mail deliviring */ + struct in_addr deliver_addr; /**< its address */ + guint16 deliver_port; /**< port for deliviring */ + guint16 deliver_family; /**< socket family for delivirnig */ + gchar *deliver_agent_path; /**< deliver to pipe instead of socket */ + gboolean deliver_lmtp; /**< use LMTP instead of SMTP */ + + GList *script_modules; /**< linked list of script modules to load */ + + GList *filters; /**< linked list of all filters */ + GList *workers; /**< linked list of all workers params */ + struct rspamd_worker_cfg_parser *wrk_parsers; /**< hash for worker config parsers, indexed by worker quarks */ + gchar *filters_str; /**< string of filters */ + ucl_object_t *rcl_obj; /**< rcl object */ + GHashTable * metrics; /**< hash of metrics indexed by metric name */ + GList * symbols_groups; /**< groups of symbols */ + GList * metrics_list; /**< linked list of metrics */ + GHashTable * metrics_symbols; /**< hash table of metrics indexed by symbol */ + GHashTable * c_modules; /**< hash of c modules indexed by module name */ + GHashTable * composite_symbols; /**< hash of composite symbols indexed by its name */ GList *classifiers; /**< list of all classifiers defined */ GList *statfiles; /**< list of all statfiles in config file order */ GHashTable *classifiers_symbols; /**< hashtable indexed by symbol name of classifiers */ - GHashTable* cfg_params; /**< all cfg params indexed by its name in this structure */ - GList *pre_filters; /**< list of pre-processing lua filters */ - GList *post_filters; /**< list of post-processing lua filters */ - gchar *dynamic_conf; /**< path to dynamic configuration */ - GList *current_dynamic_conf; /**< currently loaded dynamic configuration */ - GHashTable* domain_settings; /**< settings per-domains */ - GHashTable* user_settings; /**< settings per-user */ - gchar* domain_settings_str; /**< string representation of settings */ - gchar* user_settings_str; - gint clock_res; /**< resolution of clock used */ - - GList *maps; /**< maps active */ - rspamd_mempool_t *map_pool; /**< static maps pool */ - gdouble map_timeout; /**< maps watch timeout */ - - struct symbols_cache *cache; /**< symbols cache object */ - gchar *cache_filename; /**< filename of cache file */ - struct metric *default_metric; /**< default metric */ - - gchar* checksum; /**< real checksum of config file */ - gchar* dump_checksum; /**< dump checksum of config file */ - gpointer lua_state; /**< pointer to lua state */ - - gchar* rrd_file; /**< rrd file to store statistics */ - - gchar* history_file; /**< file to save rolling history */ - - gdouble dns_timeout; /**< timeout in milliseconds for waiting for dns reply */ - guint32 dns_retransmits; /**< maximum retransmits count */ - guint32 dns_throttling_errors; /**< maximum errors for starting resolver throttling */ - guint32 dns_throttling_time; /**< time in seconds for DNS throttling */ - guint32 dns_io_per_server; /**< number of sockets per DNS server */ - GList *nameservers; /**< list of nameservers or NULL to parse resolv.conf */ + GHashTable * cfg_params; /**< all cfg params indexed by its name in this structure */ + GList *pre_filters; /**< list of pre-processing lua filters */ + GList *post_filters; /**< list of post-processing lua filters */ + gchar *dynamic_conf; /**< path to dynamic configuration */ + GList *current_dynamic_conf; /**< currently loaded dynamic configuration */ + GHashTable * domain_settings; /**< settings per-domains */ + GHashTable * user_settings; /**< settings per-user */ + gchar * domain_settings_str; /**< string representation of settings */ + gchar * user_settings_str; + gint clock_res; /**< resolution of clock used */ + + GList *maps; /**< maps active */ + rspamd_mempool_t *map_pool; /**< static maps pool */ + gdouble map_timeout; /**< maps watch timeout */ + + struct symbols_cache *cache; /**< symbols cache object */ + gchar *cache_filename; /**< filename of cache file */ + struct metric *default_metric; /**< default metric */ + + gchar * checksum; /**< real checksum of config file */ + gchar * dump_checksum; /**< dump checksum of config file */ + gpointer lua_state; /**< pointer to lua state */ + + gchar * rrd_file; /**< rrd file to store statistics */ + + gchar * history_file; /**< file to save rolling history */ + + gdouble dns_timeout; /**< timeout in milliseconds for waiting for dns reply */ + guint32 dns_retransmits; /**< maximum retransmits count */ + guint32 dns_throttling_errors; /**< maximum errors for starting resolver throttling */ + guint32 dns_throttling_time; /**< time in seconds for DNS throttling */ + guint32 dns_io_per_server; /**< number of sockets per DNS server */ + GList *nameservers; /**< list of nameservers or NULL to parse resolv.conf */ }; @@ -351,7 +352,7 @@ struct rspamd_config { * @return TRUE if string was parsed */ gboolean rspamd_parse_host_port_priority (rspamd_mempool_t *pool, - const gchar *str, gchar **addr, guint16 *port, guint *priority); + const gchar *str, gchar **addr, guint16 *port, guint *priority); /** * Parse host:port line @@ -360,7 +361,7 @@ gboolean rspamd_parse_host_port_priority (rspamd_mempool_t *pool, * @return TRUE if string was parsed */ gboolean rspamd_parse_host_port (rspamd_mempool_t *pool, const gchar *str, - gchar **addr, guint16 *port); + gchar **addr, guint16 *port); /** * Parse host:priority line @@ -369,7 +370,7 @@ gboolean rspamd_parse_host_port (rspamd_mempool_t *pool, const gchar *str, * @return TRUE if string was parsed */ gboolean rspamd_parse_host_priority (rspamd_mempool_t *pool, const gchar *str, - gchar **addr, guint *priority); + gchar **addr, guint *priority); /** * Parse bind credits @@ -379,7 +380,7 @@ gboolean rspamd_parse_host_priority (rspamd_mempool_t *pool, const gchar *str, * @return 1 if line was successfully parsed and 0 in case of error */ gboolean rspamd_parse_bind_line (struct rspamd_config *cfg, - struct rspamd_worker_conf *cf, const gchar *str); + struct rspamd_worker_conf *cf, const gchar *str); /** * Init default values @@ -400,9 +401,9 @@ void rspamd_config_free (struct rspamd_config *cfg); * @param opt_name name of option to get * @return module value or NULL if option does not defined */ -const ucl_object_t* rspamd_config_get_module_opt (struct rspamd_config *cfg, - const gchar *module_name, - const gchar *opt_name); +const ucl_object_t * rspamd_config_get_module_opt (struct rspamd_config *cfg, + const gchar *module_name, + const gchar *opt_name); /** * Parse limit @@ -440,36 +441,38 @@ void rspamd_config_unescape_quotes (gchar *line); /* * Convert comma separated string to a list of strings */ -GList* rspamd_config_parse_comma_list (rspamd_mempool_t *pool, - const gchar *line); +GList * rspamd_config_parse_comma_list (rspamd_mempool_t *pool, + const gchar *line); /* * Return a new classifier_config structure, setting default and non-conflicting attributes */ -struct rspamd_classifier_config* rspamd_config_new_classifier (struct rspamd_config *cfg, - struct rspamd_classifier_config *c); +struct rspamd_classifier_config * rspamd_config_new_classifier ( + struct rspamd_config *cfg, + struct rspamd_classifier_config *c); /* * Return a new worker_conf structure, setting default and non-conflicting attributes */ -struct rspamd_worker_conf* rspamd_config_new_worker (struct rspamd_config *cfg, - struct rspamd_worker_conf *c); +struct rspamd_worker_conf * rspamd_config_new_worker (struct rspamd_config *cfg, + struct rspamd_worker_conf *c); /* * Return a new metric structure, setting default and non-conflicting attributes */ -struct metric* rspamd_config_new_metric (struct rspamd_config *cfg, - struct metric *c); +struct metric * rspamd_config_new_metric (struct rspamd_config *cfg, + struct metric *c); /* * Return a new statfile structure, setting default and non-conflicting attributes */ -struct rspamd_statfile_config* rspamd_config_new_statfile (struct rspamd_config *cfg, - struct rspamd_statfile_config *c); +struct rspamd_statfile_config * rspamd_config_new_statfile ( + struct rspamd_config *cfg, + struct rspamd_statfile_config *c); /* * Read XML configuration file */ gboolean rspamd_config_read (struct rspamd_config *cfg, - const gchar *filename, const gchar *convert_to, - rspamd_rcl_section_fin_t logger_fin, gpointer logger_ud); + const gchar *filename, const gchar *convert_to, + rspamd_rcl_section_fin_t logger_fin, gpointer logger_ud); /* * Register symbols of classifiers inside metrics @@ -484,17 +487,17 @@ gboolean rspamd_config_check_statfiles (struct rspamd_classifier_config *cf); /* * Find classifier config by name */ -struct rspamd_classifier_config* rspamd_config_find_classifier ( - struct rspamd_config *cfg, - const gchar *name); +struct rspamd_classifier_config * rspamd_config_find_classifier ( + struct rspamd_config *cfg, + const gchar *name); /* * Parse input `ip_list` to radix tree `tree`. Now supports only IPv4 addresses. */ gboolean rspamd_config_parse_ip_list (const gchar *ip_list, - radix_tree_t **tree); + radix_tree_t **tree); #endif /* ifdef CFG_FILE_H */ -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/libserver/cfg_rcl.c b/src/libserver/cfg_rcl.c index f9524fd62..75a659203 100644 --- a/src/libserver/cfg_rcl.c +++ b/src/libserver/cfg_rcl.c @@ -34,7 +34,7 @@ */ static gboolean rspamd_rcl_logging_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) + gpointer ud, struct rspamd_rcl_section *section, GError **err) { const ucl_object_t *val; const gchar *facility, *log_type, *log_level; @@ -45,11 +45,15 @@ rspamd_rcl_logging_handler (struct rspamd_config *cfg, const ucl_object_t *obj, /* Need to get filename */ val = ucl_object_find_key (obj, "filename"); if (val == NULL || val->type != UCL_STRING) { - g_set_error (err, CFG_RCL_ERROR, ENOENT, "filename attribute must be specified for file logging type"); + g_set_error (err, + CFG_RCL_ERROR, + ENOENT, + "filename attribute must be specified for file logging type"); return FALSE; } cfg->log_type = RSPAMD_LOG_FILE; - cfg->log_file = rspamd_mempool_strdup (cfg->cfg_pool, ucl_object_tostring (val)); + cfg->log_file = rspamd_mempool_strdup (cfg->cfg_pool, + ucl_object_tostring (val)); } else if (g_ascii_strcasecmp (log_type, "syslog") == 0) { /* Need to get facility */ @@ -58,74 +62,84 @@ rspamd_rcl_logging_handler (struct rspamd_config *cfg, const ucl_object_t *obj, val = ucl_object_find_key (obj, "facility"); if (val != NULL && ucl_object_tostring_safe (val, &facility)) { if (g_ascii_strcasecmp (facility, "LOG_AUTH") == 0 || - g_ascii_strcasecmp (facility, "auth") == 0 ) { + g_ascii_strcasecmp (facility, "auth") == 0 ) { cfg->log_facility = LOG_AUTH; } else if (g_ascii_strcasecmp (facility, "LOG_CRON") == 0 || - g_ascii_strcasecmp (facility, "cron") == 0 ) { + g_ascii_strcasecmp (facility, "cron") == 0 ) { cfg->log_facility = LOG_CRON; } else if (g_ascii_strcasecmp (facility, "LOG_DAEMON") == 0 || - g_ascii_strcasecmp (facility, "daemon") == 0 ) { + g_ascii_strcasecmp (facility, "daemon") == 0 ) { cfg->log_facility = LOG_DAEMON; } else if (g_ascii_strcasecmp (facility, "LOG_MAIL") == 0 || - g_ascii_strcasecmp (facility, "mail") == 0) { + g_ascii_strcasecmp (facility, "mail") == 0) { cfg->log_facility = LOG_MAIL; } else if (g_ascii_strcasecmp (facility, "LOG_USER") == 0 || - g_ascii_strcasecmp (facility, "user") == 0 ) { + g_ascii_strcasecmp (facility, "user") == 0 ) { cfg->log_facility = LOG_USER; } else if (g_ascii_strcasecmp (facility, "LOG_LOCAL0") == 0 || - g_ascii_strcasecmp (facility, "local0") == 0) { + g_ascii_strcasecmp (facility, "local0") == 0) { cfg->log_facility = LOG_LOCAL0; } else if (g_ascii_strcasecmp (facility, "LOG_LOCAL1") == 0 || - g_ascii_strcasecmp (facility, "local1") == 0) { + g_ascii_strcasecmp (facility, "local1") == 0) { cfg->log_facility = LOG_LOCAL1; } else if (g_ascii_strcasecmp (facility, "LOG_LOCAL2") == 0 || - g_ascii_strcasecmp (facility, "local2") == 0) { + g_ascii_strcasecmp (facility, "local2") == 0) { cfg->log_facility = LOG_LOCAL2; } else if (g_ascii_strcasecmp (facility, "LOG_LOCAL3") == 0 || - g_ascii_strcasecmp (facility, "local3") == 0) { + g_ascii_strcasecmp (facility, "local3") == 0) { cfg->log_facility = LOG_LOCAL3; } else if (g_ascii_strcasecmp (facility, "LOG_LOCAL4") == 0 || - g_ascii_strcasecmp (facility, "local4") == 0) { + g_ascii_strcasecmp (facility, "local4") == 0) { cfg->log_facility = LOG_LOCAL4; } else if (g_ascii_strcasecmp (facility, "LOG_LOCAL5") == 0 || - g_ascii_strcasecmp (facility, "local5") == 0) { + g_ascii_strcasecmp (facility, "local5") == 0) { cfg->log_facility = LOG_LOCAL5; } else if (g_ascii_strcasecmp (facility, "LOG_LOCAL6") == 0 || - g_ascii_strcasecmp (facility, "local6") == 0) { + g_ascii_strcasecmp (facility, "local6") == 0) { cfg->log_facility = LOG_LOCAL6; } else if (g_ascii_strcasecmp (facility, "LOG_LOCAL7") == 0 || - g_ascii_strcasecmp (facility, "local7") == 0) { + g_ascii_strcasecmp (facility, "local7") == 0) { cfg->log_facility = LOG_LOCAL7; } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "invalid log facility: %s", facility); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "invalid log facility: %s", + facility); return FALSE; } } } - else if (g_ascii_strcasecmp (log_type, "stderr") == 0 || g_ascii_strcasecmp (log_type, "console") == 0) { + else if (g_ascii_strcasecmp (log_type, + "stderr") == 0 || g_ascii_strcasecmp (log_type, "console") == 0) { cfg->log_type = RSPAMD_LOG_CONSOLE; } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "invalid log type: %s", log_type); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "invalid log type: %s", + log_type); return FALSE; } } else { /* No type specified */ - msg_warn ("logging type is not specified correctly, log output to the console"); + msg_warn ( + "logging type is not specified correctly, log output to the console"); } /* Handle log level */ @@ -144,7 +158,11 @@ rspamd_rcl_logging_handler (struct rspamd_config *cfg, const ucl_object_t *obj, cfg->log_level = G_LOG_LEVEL_DEBUG; } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "invalid log level: %s", log_level); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "invalid log level: %s", + log_level); return FALSE; } } @@ -154,7 +172,7 @@ rspamd_rcl_logging_handler (struct rspamd_config *cfg, const ucl_object_t *obj, static gboolean rspamd_rcl_options_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) + gpointer ud, struct rspamd_rcl_section *section, GError **err) { const ucl_object_t *dns; struct rspamd_rcl_section *dns_section; @@ -163,7 +181,8 @@ rspamd_rcl_options_handler (struct rspamd_config *cfg, const ucl_object_t *obj, dns = ucl_object_find_key (obj, "dns"); if (dns_section != NULL && dns != NULL) { - if (!rspamd_rcl_section_parse_defaults (dns_section, cfg, dns, cfg, err)) { + if (!rspamd_rcl_section_parse_defaults (dns_section, cfg, dns, cfg, + err)) { return FALSE; } } @@ -174,8 +193,8 @@ rspamd_rcl_options_handler (struct rspamd_config *cfg, const ucl_object_t *obj, static gint rspamd_symbols_group_find_func (gconstpointer a, gconstpointer b) { - const struct rspamd_symbols_group *gr = a; - const gchar *uv = b; + const struct rspamd_symbols_group *gr = a; + const gchar *uv = b; return g_ascii_strcasecmp (gr->name, uv); } @@ -190,7 +209,7 @@ rspamd_symbols_group_find_func (gconstpointer a, gconstpointer b) */ static gboolean rspamd_rcl_insert_symbol (struct rspamd_config *cfg, struct metric *metric, - const ucl_object_t *obj, gboolean is_legacy, GError **err) + const ucl_object_t *obj, gboolean is_legacy, GError **err) { const gchar *group = "ungrouped", *description = NULL, *sym_name; gdouble symbol_score, *score_ptr; @@ -226,7 +245,11 @@ rspamd_rcl_insert_symbol (struct rspamd_config *cfg, struct metric *metric, else if (obj->type == UCL_OBJECT) { val = ucl_object_find_key (obj, "weight"); if (val == NULL || !ucl_object_todouble_safe (val, &symbol_score)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "invalid symbol score: %s", sym_name); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "invalid symbol score: %s", + sym_name); return FALSE; } val = ucl_object_find_key (obj, "description"); @@ -239,11 +262,16 @@ rspamd_rcl_insert_symbol (struct rspamd_config *cfg, struct metric *metric, } } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "invalid symbol type: %s", sym_name); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "invalid symbol type: %s", + sym_name); return FALSE; } - sym_def = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct rspamd_symbol_def)); + sym_def = + rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct rspamd_symbol_def)); score_ptr = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (gdouble)); *score_ptr = symbol_score; @@ -253,9 +281,12 @@ rspamd_rcl_insert_symbol (struct rspamd_config *cfg, struct metric *metric, g_hash_table_insert (metric->symbols, sym_def->name, score_ptr); - if ((metric_list = g_hash_table_lookup (cfg->metrics_symbols, sym_def->name)) == NULL) { + if ((metric_list = + g_hash_table_lookup (cfg->metrics_symbols, sym_def->name)) == NULL) { metric_list = g_list_prepend (NULL, metric); - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)g_list_free, metric_list); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)g_list_free, + metric_list); g_hash_table_insert (cfg->metrics_symbols, sym_def->name, metric_list); } else { @@ -266,10 +297,14 @@ rspamd_rcl_insert_symbol (struct rspamd_config *cfg, struct metric *metric, } /* Search for symbol group */ - group_list = g_list_find_custom (cfg->symbols_groups, group, rspamd_symbols_group_find_func); + group_list = g_list_find_custom (cfg->symbols_groups, + group, + rspamd_symbols_group_find_func); if (group_list == NULL) { /* Create new group */ - sym_group = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct rspamd_symbols_group)); + sym_group = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct rspamd_symbols_group)); sym_group->name = rspamd_mempool_strdup (cfg->cfg_pool, group); sym_group->symbols = NULL; cfg->symbols_groups = g_list_prepend (cfg->symbols_groups, sym_group); @@ -285,7 +320,7 @@ rspamd_rcl_insert_symbol (struct rspamd_config *cfg, struct metric *metric, static gboolean rspamd_rcl_metric_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) + gpointer ud, struct rspamd_rcl_section *section, GError **err) { const ucl_object_t *val, *cur; const gchar *metric_name, *subject_name, *semicolon, *act_str; @@ -314,13 +349,18 @@ rspamd_rcl_metric_handler (struct rspamd_config *cfg, const ucl_object_t *obj, val = ucl_object_find_key (obj, "actions"); if (val != NULL) { if (val->type != UCL_OBJECT) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "actions must be an object"); + g_set_error (err, CFG_RCL_ERROR, EINVAL, + "actions must be an object"); return FALSE; } while ((cur = ucl_iterate_object (val, &it, true)) != NULL) { if (!check_action_str (ucl_object_key (cur), &action_value) || - !ucl_object_todouble_safe (cur, &action_score)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "invalid action definition: %s", ucl_object_key (cur)); + !ucl_object_todouble_safe (cur, &action_score)) { + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "invalid action definition: %s", + ucl_object_key (cur)); return FALSE; } action = &metric->actions[action_value]; @@ -338,7 +378,8 @@ rspamd_rcl_metric_handler (struct rspamd_config *cfg, const ucl_object_t *obj, have_actions = TRUE; } val = ucl_object_find_key (obj, "action"); - LL_FOREACH (val, cur) { + LL_FOREACH (val, cur) + { if (cur->type == UCL_STRING) { act_str = ucl_object_tostring (cur); semicolon = strchr (act_str, ':'); @@ -354,7 +395,11 @@ rspamd_rcl_metric_handler (struct rspamd_config *cfg, const ucl_object_t *obj, } } if (new && !have_actions) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "metric %s has no actions", metric_name); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "metric %s has no actions", + metric_name); return FALSE; } } @@ -366,7 +411,8 @@ rspamd_rcl_metric_handler (struct rspamd_config *cfg, const ucl_object_t *obj, val = val->value.ov; } if (val->type != UCL_OBJECT) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "symbols must be an object"); + g_set_error (err, CFG_RCL_ERROR, EINVAL, + "symbols must be an object"); return FALSE; } it = NULL; @@ -384,17 +430,25 @@ rspamd_rcl_metric_handler (struct rspamd_config *cfg, const ucl_object_t *obj, val = val->value.ov; } if (val->type != UCL_OBJECT) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "symbols must be an object"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "symbols must be an object"); return FALSE; } - LL_FOREACH (val, cur) { + LL_FOREACH (val, cur) + { if (!rspamd_rcl_insert_symbol (cfg, metric, cur, TRUE, err)) { return FALSE; } } } else if (new) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "metric %s has no symbols", metric_name); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "metric %s has no symbols", + metric_name); return FALSE; } } @@ -420,7 +474,7 @@ rspamd_rcl_metric_handler (struct rspamd_config *cfg, const ucl_object_t *obj, static gboolean rspamd_rcl_worker_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) + gpointer ud, struct rspamd_rcl_section *section, GError **err) { const ucl_object_t *val, *cur; ucl_object_iter_t it = NULL; @@ -437,7 +491,11 @@ rspamd_rcl_worker_handler (struct rspamd_config *cfg, const ucl_object_t *obj, wrk = rspamd_config_new_worker (cfg, NULL); wrk->worker = rspamd_get_worker_by_type (qtype); if (wrk->worker == NULL) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "unknown worker type: %s", worker_type); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "unknown worker type: %s", + worker_type); return FALSE; } wrk->type = qtype; @@ -446,7 +504,11 @@ rspamd_rcl_worker_handler (struct rspamd_config *cfg, const ucl_object_t *obj, } } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "unknown worker type: %s", worker_type); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "unknown worker type: %s", + worker_type); return FALSE; } } @@ -460,12 +522,17 @@ rspamd_rcl_worker_handler (struct rspamd_config *cfg, const ucl_object_t *obj, if (val->type == UCL_ARRAY) { val = val->value.ov; } - LL_FOREACH (val, cur) { + LL_FOREACH (val, cur) + { if (!ucl_object_tostring_safe (cur, &worker_bind)) { continue; } if (!rspamd_parse_bind_line (cfg, wrk, worker_bind)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot parse bind line: %s", worker_bind); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot parse bind line: %s", + worker_bind); return FALSE; } } @@ -483,13 +550,14 @@ rspamd_rcl_worker_handler (struct rspamd_config *cfg, const ucl_object_t *obj, while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) { HASH_FIND_STR (wparser->parsers, ucl_object_key (cur), whandler); if (whandler != NULL) { - if (!whandler->handler (cfg, cur, &whandler->parser, section, err)) { + if (!whandler->handler (cfg, cur, &whandler->parser, section, + err)) { return FALSE; } } } if (wparser->def_obj_parser != NULL) { - if (! wparser->def_obj_parser (obj, wparser->def_ud)) { + if (!wparser->def_obj_parser (obj, wparser->def_ud)) { return FALSE; } } @@ -503,7 +571,7 @@ rspamd_rcl_worker_handler (struct rspamd_config *cfg, const ucl_object_t *obj, static void rspamd_rcl_set_lua_globals (struct rspamd_config *cfg, lua_State *L) { - struct rspamd_config **pcfg; + struct rspamd_config **pcfg; /* First check for global variable 'config' */ lua_getglobal (L, "config"); @@ -542,9 +610,10 @@ rspamd_rcl_set_lua_globals (struct rspamd_config *cfg, lua_State *L) static gboolean rspamd_rcl_lua_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) + gpointer ud, struct rspamd_rcl_section *section, GError **err) { - const gchar *lua_src = rspamd_mempool_strdup (cfg->cfg_pool, ucl_object_tostring (obj)); + const gchar *lua_src = rspamd_mempool_strdup (cfg->cfg_pool, + ucl_object_tostring (obj)); gchar *cur_dir, *lua_dir, *lua_file, *tmp1, *tmp2; lua_State *L = cfg->lua_state; @@ -557,10 +626,15 @@ rspamd_rcl_lua_handler (struct rspamd_config *cfg, const ucl_object_t *obj, if (getcwd (cur_dir, PATH_MAX) != NULL && chdir (lua_dir) != -1) { /* Load file */ if (luaL_loadfile (L, lua_file) != 0) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot load lua file %s: %s", - lua_src, lua_tostring (L, -1)); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot load lua file %s: %s", + lua_src, + lua_tostring (L, -1)); if (chdir (cur_dir) == -1) { - msg_err ("cannot chdir to %s: %s", cur_dir, strerror (errno));; + msg_err ("cannot chdir to %s: %s", cur_dir, + strerror (errno));; } g_free (cur_dir); g_free (tmp1); @@ -570,10 +644,15 @@ rspamd_rcl_lua_handler (struct rspamd_config *cfg, const ucl_object_t *obj, rspamd_rcl_set_lua_globals (cfg, L); /* Now do it */ if (lua_pcall (L, 0, LUA_MULTRET, 0) != 0) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot init lua file %s: %s", - lua_src, lua_tostring (L, -1)); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot init lua file %s: %s", + lua_src, + lua_tostring (L, -1)); if (chdir (cur_dir) == -1) { - msg_err ("cannot chdir to %s: %s", cur_dir, strerror (errno));; + msg_err ("cannot chdir to %s: %s", cur_dir, + strerror (errno));; } g_free (cur_dir); g_free (tmp1); @@ -583,7 +662,7 @@ rspamd_rcl_lua_handler (struct rspamd_config *cfg, const ucl_object_t *obj, } else { g_set_error (err, CFG_RCL_ERROR, ENOENT, "cannot chdir to %s: %s", - lua_src, strerror (errno)); + lua_src, strerror (errno)); if (chdir (cur_dir) == -1) { msg_err ("cannot chdir to %s: %s", cur_dir, strerror (errno));; } @@ -602,7 +681,7 @@ rspamd_rcl_lua_handler (struct rspamd_config *cfg, const ucl_object_t *obj, } else { g_set_error (err, CFG_RCL_ERROR, ENOENT, "cannot find to %s: %s", - lua_src, strerror (errno)); + lua_src, strerror (errno)); return FALSE; } @@ -610,7 +689,9 @@ rspamd_rcl_lua_handler (struct rspamd_config *cfg, const ucl_object_t *obj, } static gboolean -rspamd_rcl_add_module_path (struct rspamd_config *cfg, const gchar *path, GError **err) +rspamd_rcl_add_module_path (struct rspamd_config *cfg, + const gchar *path, + GError **err) { struct stat st; struct script_module *cur_mod; @@ -620,7 +701,12 @@ rspamd_rcl_add_module_path (struct rspamd_config *cfg, const gchar *path, GError guint i; if (stat (path, &st) == -1) { - g_set_error (err, CFG_RCL_ERROR, errno, "cannot stat path %s, %s", path, strerror (errno)); + g_set_error (err, + CFG_RCL_ERROR, + errno, + "cannot stat path %s, %s", + path, + strerror (errno)); return FALSE; } @@ -632,23 +718,33 @@ rspamd_rcl_add_module_path (struct rspamd_config *cfg, const gchar *path, GError snprintf (pattern, len, "%s%s", path, "*.lua"); if (glob (pattern, GLOB_DOOFFS, NULL, &globbuf) == 0) { - for (i = 0; i < globbuf.gl_pathc; i ++) { - cur_mod = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct script_module)); - cur_mod->path = rspamd_mempool_strdup (cfg->cfg_pool, globbuf.gl_pathv[i]); - cfg->script_modules = g_list_prepend (cfg->script_modules, cur_mod); + for (i = 0; i < globbuf.gl_pathc; i++) { + cur_mod = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct script_module)); + cur_mod->path = rspamd_mempool_strdup (cfg->cfg_pool, + globbuf.gl_pathv[i]); + cfg->script_modules = g_list_prepend (cfg->script_modules, + cur_mod); } globfree (&globbuf); g_free (pattern); } else { - g_set_error (err, CFG_RCL_ERROR, errno, "glob failed for %s, %s", pattern, strerror (errno)); + g_set_error (err, + CFG_RCL_ERROR, + errno, + "glob failed for %s, %s", + pattern, + strerror (errno)); g_free (pattern); return FALSE; } } else { /* Handle single file */ - cur_mod = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct script_module)); + cur_mod = + rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct script_module)); cur_mod->path = rspamd_mempool_strdup (cfg->cfg_pool, path); cfg->script_modules = g_list_prepend (cfg->script_modules, cur_mod); } @@ -658,7 +754,7 @@ rspamd_rcl_add_module_path (struct rspamd_config *cfg, const gchar *path, GError static gboolean rspamd_rcl_modules_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) + gpointer ud, struct rspamd_rcl_section *section, GError **err) { const ucl_object_t *val, *cur; const gchar *data; @@ -666,21 +762,27 @@ rspamd_rcl_modules_handler (struct rspamd_config *cfg, const ucl_object_t *obj, if (obj->type == UCL_OBJECT) { val = ucl_object_find_key (obj, "path"); - LL_FOREACH (val, cur) { + LL_FOREACH (val, cur) + { if (ucl_object_tostring_safe (cur, &data)) { - if (!rspamd_rcl_add_module_path (cfg, rspamd_mempool_strdup (cfg->cfg_pool, data), err)) { + if (!rspamd_rcl_add_module_path (cfg, + rspamd_mempool_strdup (cfg->cfg_pool, data), err)) { return FALSE; } } } } else if (ucl_object_tostring_safe (obj, &data)) { - if (!rspamd_rcl_add_module_path (cfg, rspamd_mempool_strdup (cfg->cfg_pool, data), err)) { + if (!rspamd_rcl_add_module_path (cfg, + rspamd_mempool_strdup (cfg->cfg_pool, data), err)) { return FALSE; } } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "module parameter has wrong type (must be an object or a string)"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "module parameter has wrong type (must be an object or a string)"); return FALSE; } @@ -689,7 +791,7 @@ rspamd_rcl_modules_handler (struct rspamd_config *cfg, const ucl_object_t *obj, static gboolean rspamd_rcl_statfile_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) + gpointer ud, struct rspamd_rcl_section *section, GError **err) { struct rspamd_classifier_config *ccf = ud; const ucl_object_t *val; @@ -703,7 +805,9 @@ rspamd_rcl_statfile_handler (struct rspamd_config *cfg, const ucl_object_t *obj, val = ucl_object_find_key (obj, "binlog"); if (val != NULL && ucl_object_tostring_safe (val, &data)) { if (st->binlog == NULL) { - st->binlog = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct statfile_binlog_params)); + st->binlog = + rspamd_mempool_alloc0 (cfg->cfg_pool, + sizeof (struct statfile_binlog_params)); } if (g_ascii_strcasecmp (data, "master") == 0) { st->binlog->affinity = AFFINITY_MASTER; @@ -721,7 +825,8 @@ rspamd_rcl_statfile_handler (struct rspamd_config *cfg, const ucl_object_t *obj, } val = ucl_object_find_key (obj, "binlog_master"); if (val != NULL && ucl_object_tostring_safe (val, &data)) { - if (!rspamd_parse_host_port (cfg->cfg_pool, data, &st->binlog->master_addr, &st->binlog->master_port)) { + if (!rspamd_parse_host_port (cfg->cfg_pool, data, + &st->binlog->master_addr, &st->binlog->master_port)) { msg_err ("cannot parse master address: %s", data); return FALSE; } @@ -737,19 +842,26 @@ rspamd_rcl_statfile_handler (struct rspamd_config *cfg, const ucl_object_t *obj, labels = g_list_append (labels, st); } else { - g_hash_table_insert (ccf->labels, st->label, g_list_prepend (NULL, st)); + g_hash_table_insert (ccf->labels, st->label, + g_list_prepend (NULL, st)); } } if (st->symbol != NULL) { g_hash_table_insert (cfg->classifiers_symbols, st->symbol, st); } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "statfile must have a symbol defined"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "statfile must have a symbol defined"); return FALSE; } if (st->path == NULL) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "statfile must have a path defined"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "statfile must have a path defined"); return FALSE; } @@ -757,19 +869,29 @@ rspamd_rcl_statfile_handler (struct rspamd_config *cfg, const ucl_object_t *obj, val = ucl_object_find_key (obj, "spam"); if (val == NULL) { - msg_info ("statfile %s has no explicit 'spam' setting, trying to guess by symbol", st->symbol); - if (rspamd_strncasestr (st->symbol, "spam", strlen (st->symbol)) != NULL) { + msg_info ( + "statfile %s has no explicit 'spam' setting, trying to guess by symbol", + st->symbol); + if (rspamd_strncasestr (st->symbol, "spam", + strlen (st->symbol)) != NULL) { st->is_spam = TRUE; } - else if (rspamd_strncasestr (st->symbol, "ham", strlen (st->symbol)) != NULL) { + else if (rspamd_strncasestr (st->symbol, "ham", + strlen (st->symbol)) != NULL) { st->is_spam = FALSE; } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot guess spam setting from %s", st->symbol); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot guess spam setting from %s", + st->symbol); return FALSE; } - msg_info ("guessed that statfile with symbol %s is %s", st->symbol, st->is_spam ? - "spam" : "ham"); + msg_info ("guessed that statfile with symbol %s is %s", + st->symbol, + st->is_spam ? + "spam" : "ham"); } return TRUE; } @@ -778,8 +900,11 @@ rspamd_rcl_statfile_handler (struct rspamd_config *cfg, const ucl_object_t *obj, } static gboolean -rspamd_rcl_classifier_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) +rspamd_rcl_classifier_handler (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err) { const ucl_object_t *val, *cur; ucl_object_iter_t it = NULL; @@ -791,7 +916,10 @@ rspamd_rcl_classifier_handler (struct rspamd_config *cfg, const ucl_object_t *ob val = ucl_object_find_key (obj, "type"); if (val == NULL || !ucl_object_tostring_safe (val, &type)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "classifier should have type defined"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "classifier should have type defined"); return FALSE; } @@ -819,22 +947,31 @@ rspamd_rcl_classifier_handler (struct rspamd_config *cfg, const ucl_object_t *ob key = ucl_object_key (val); if (key != NULL) { if (g_ascii_strcasecmp (key, "statfile") == 0) { - LL_FOREACH (val, cur) { - res = rspamd_rcl_statfile_handler (cfg, cur, ccf, stat_section, err); + LL_FOREACH (val, cur) + { + res = rspamd_rcl_statfile_handler (cfg, + cur, + ccf, + stat_section, + err); if (!res) { return FALSE; } } } - else if (g_ascii_strcasecmp (key, "type") == 0 && val->type == UCL_STRING) { + else if (g_ascii_strcasecmp (key, + "type") == 0 && val->type == UCL_STRING) { continue; } - else if (g_ascii_strcasecmp (key, "tokenizer") == 0 && val->type == UCL_STRING) { + else if (g_ascii_strcasecmp (key, + "tokenizer") == 0 && val->type == UCL_STRING) { ccf->tokenizer = get_tokenizer (ucl_object_tostring (val)); } else { /* Just insert a value of option to the hash */ - g_hash_table_insert (ccf->opts, (gpointer)key, (gpointer)ucl_object_tostring_forced (val)); + g_hash_table_insert (ccf->opts, + (gpointer)key, + (gpointer)ucl_object_tostring_forced (val)); } } } @@ -848,8 +985,11 @@ rspamd_rcl_classifier_handler (struct rspamd_config *cfg, const ucl_object_t *ob } static gboolean -rspamd_rcl_composite_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) +rspamd_rcl_composite_handler (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err) { const ucl_object_t *val; struct expression *expr; @@ -859,7 +999,10 @@ rspamd_rcl_composite_handler (struct rspamd_config *cfg, const ucl_object_t *obj val = ucl_object_find_key (obj, "name"); if (val == NULL || !ucl_object_tostring_safe (val, &composite_name)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "composite must have a name defined"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "composite must have a name defined"); return FALSE; } @@ -870,19 +1013,31 @@ rspamd_rcl_composite_handler (struct rspamd_config *cfg, const ucl_object_t *obj val = ucl_object_find_key (obj, "expression"); if (val == NULL || !ucl_object_tostring_safe (val, &composite_expression)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "composite must have an expression defined"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "composite must have an expression defined"); return FALSE; } - if ((expr = parse_expression (cfg->cfg_pool, (gchar *)composite_expression)) == NULL) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot parse composite expression: %s", composite_expression); + if ((expr = + parse_expression (cfg->cfg_pool, + (gchar *)composite_expression)) == NULL) { + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot parse composite expression: %s", + composite_expression); return FALSE; } - composite = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct rspamd_composite)); + composite = + rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct rspamd_composite)); composite->expr = expr; composite->id = g_hash_table_size (cfg->composite_symbols) + 1; - g_hash_table_insert (cfg->composite_symbols, (gpointer)composite_name, composite); + g_hash_table_insert (cfg->composite_symbols, + (gpointer)composite_name, + composite); if (new) { register_virtual_symbol (&cfg->cache, composite_name, 1); @@ -897,7 +1052,7 @@ rspamd_rcl_composite_handler (struct rspamd_config *cfg, const ucl_object_t *obj */ static gboolean rspamd_rcl_empty_handler (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) + gpointer ud, struct rspamd_rcl_section *section, GError **err) { return rspamd_rcl_section_parse_defaults (section, cfg, obj, cfg, err); } @@ -912,10 +1067,10 @@ rspamd_rcl_empty_handler (struct rspamd_config *cfg, const ucl_object_t *obj, * @param strict_type turn on strict check for types for this section * @return newly created structure */ -static inline struct rspamd_rcl_section* +static inline struct rspamd_rcl_section * rspamd_rcl_add_section (struct rspamd_rcl_section **top, - const gchar *name, rspamd_rcl_handler_t handler, - enum ucl_type type, gboolean required, gboolean strict_type) + const gchar *name, rspamd_rcl_handler_t handler, + enum ucl_type type, gboolean required, gboolean strict_type) { struct rspamd_rcl_section *new; @@ -939,8 +1094,11 @@ rspamd_rcl_add_section (struct rspamd_rcl_section **top, * @return newly created structure */ static inline struct rspamd_rcl_default_handler_data * -rspamd_rcl_add_default_handler (struct rspamd_rcl_section *section, const gchar *name, - rspamd_rcl_handler_t handler, gsize offset, gint flags) +rspamd_rcl_add_default_handler (struct rspamd_rcl_section *section, + const gchar *name, + rspamd_rcl_handler_t handler, + gsize offset, + gint flags) { struct rspamd_rcl_default_handler_data *new; @@ -950,11 +1108,12 @@ rspamd_rcl_add_default_handler (struct rspamd_rcl_section *section, const gchar new->pd.offset = offset; new->pd.flags = flags; - HASH_ADD_KEYPTR (hh, section->default_parser, new->key, strlen (new->key), new); + HASH_ADD_KEYPTR (hh, section->default_parser, new->key, strlen ( + new->key), new); return new; } -struct rspamd_rcl_section* +struct rspamd_rcl_section * rspamd_rcl_config_init (void) { struct rspamd_rcl_section *new = NULL, *sub, *ssub; @@ -963,138 +1122,283 @@ rspamd_rcl_config_init (void) /** * Logging section */ - sub = rspamd_rcl_add_section (&new, "logging", rspamd_rcl_logging_handler, UCL_OBJECT, - FALSE, TRUE); + sub = rspamd_rcl_add_section (&new, + "logging", + rspamd_rcl_logging_handler, + UCL_OBJECT, + FALSE, + TRUE); /* Default handlers */ - rspamd_rcl_add_default_handler (sub, "log_buffer", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_config, log_buf_size), 0); - rspamd_rcl_add_default_handler (sub, "log_urls", rspamd_rcl_parse_struct_boolean, - G_STRUCT_OFFSET (struct rspamd_config, log_urls), 0); - rspamd_rcl_add_default_handler (sub, "debug_ip", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_config, debug_ip_map), 0); - rspamd_rcl_add_default_handler (sub, "debug_symbols", rspamd_rcl_parse_struct_string_list, - G_STRUCT_OFFSET (struct rspamd_config, debug_symbols), 0); - rspamd_rcl_add_default_handler (sub, "log_color", rspamd_rcl_parse_struct_boolean, - G_STRUCT_OFFSET (struct rspamd_config, log_color), 0); + rspamd_rcl_add_default_handler (sub, + "log_buffer", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_config, log_buf_size), + 0); + rspamd_rcl_add_default_handler (sub, + "log_urls", + rspamd_rcl_parse_struct_boolean, + G_STRUCT_OFFSET (struct rspamd_config, log_urls), + 0); + rspamd_rcl_add_default_handler (sub, + "debug_ip", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_config, debug_ip_map), + 0); + rspamd_rcl_add_default_handler (sub, + "debug_symbols", + rspamd_rcl_parse_struct_string_list, + G_STRUCT_OFFSET (struct rspamd_config, debug_symbols), + 0); + rspamd_rcl_add_default_handler (sub, + "log_color", + rspamd_rcl_parse_struct_boolean, + G_STRUCT_OFFSET (struct rspamd_config, log_color), + 0); /** * Options section */ - sub = rspamd_rcl_add_section (&new, "options", rspamd_rcl_options_handler, UCL_OBJECT, - FALSE, TRUE); - rspamd_rcl_add_default_handler (sub, "cache_file", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_config, cache_filename), RSPAMD_CL_FLAG_STRING_PATH); + sub = rspamd_rcl_add_section (&new, + "options", + rspamd_rcl_options_handler, + UCL_OBJECT, + FALSE, + TRUE); + rspamd_rcl_add_default_handler (sub, + "cache_file", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_config, cache_filename), + RSPAMD_CL_FLAG_STRING_PATH); /* Old DNS configuration */ - rspamd_rcl_add_default_handler (sub, "dns_nameserver", rspamd_rcl_parse_struct_string_list, - G_STRUCT_OFFSET (struct rspamd_config, nameservers), 0); - rspamd_rcl_add_default_handler (sub, "dns_timeout", rspamd_rcl_parse_struct_time, - G_STRUCT_OFFSET (struct rspamd_config, dns_timeout), RSPAMD_CL_FLAG_TIME_FLOAT); - rspamd_rcl_add_default_handler (sub, "dns_retransmits", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_config, dns_retransmits), RSPAMD_CL_FLAG_INT_32); - rspamd_rcl_add_default_handler (sub, "dns_sockets", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_config, dns_io_per_server), RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_add_default_handler (sub, + "dns_nameserver", + rspamd_rcl_parse_struct_string_list, + G_STRUCT_OFFSET (struct rspamd_config, nameservers), + 0); + rspamd_rcl_add_default_handler (sub, + "dns_timeout", + rspamd_rcl_parse_struct_time, + G_STRUCT_OFFSET (struct rspamd_config, dns_timeout), + RSPAMD_CL_FLAG_TIME_FLOAT); + rspamd_rcl_add_default_handler (sub, + "dns_retransmits", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_config, dns_retransmits), + RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_add_default_handler (sub, + "dns_sockets", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_config, dns_io_per_server), + RSPAMD_CL_FLAG_INT_32); /* New DNS configiration */ ssub = rspamd_rcl_add_section (&sub->subsections, "dns", NULL, - UCL_OBJECT, FALSE, TRUE); - rspamd_rcl_add_default_handler (ssub, "nameserver", rspamd_rcl_parse_struct_string_list, - G_STRUCT_OFFSET (struct rspamd_config, nameservers), 0); - rspamd_rcl_add_default_handler (ssub, "timeout", rspamd_rcl_parse_struct_time, - G_STRUCT_OFFSET (struct rspamd_config, dns_timeout), RSPAMD_CL_FLAG_TIME_FLOAT); - rspamd_rcl_add_default_handler (ssub, "retransmits", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_config, dns_retransmits), RSPAMD_CL_FLAG_INT_32); - rspamd_rcl_add_default_handler (ssub, "sockets", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_config, dns_io_per_server), RSPAMD_CL_FLAG_INT_32); - - rspamd_rcl_add_default_handler (sub, "raw_mode", rspamd_rcl_parse_struct_boolean, - G_STRUCT_OFFSET (struct rspamd_config, raw_mode), 0); - rspamd_rcl_add_default_handler (sub, "one_shot", rspamd_rcl_parse_struct_boolean, - G_STRUCT_OFFSET (struct rspamd_config, one_shot_mode), 0); - rspamd_rcl_add_default_handler (sub, "check_attachements", rspamd_rcl_parse_struct_boolean, - G_STRUCT_OFFSET (struct rspamd_config, check_text_attachements), 0); - rspamd_rcl_add_default_handler (sub, "tempdir", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_config, temp_dir), RSPAMD_CL_FLAG_STRING_PATH); - rspamd_rcl_add_default_handler (sub, "pidfile", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_config, pid_file), RSPAMD_CL_FLAG_STRING_PATH); - rspamd_rcl_add_default_handler (sub, "filters", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_config, filters_str), 0); - rspamd_rcl_add_default_handler (sub, "sync_interval", rspamd_rcl_parse_struct_time, - G_STRUCT_OFFSET (struct rspamd_config, statfile_sync_interval), RSPAMD_CL_FLAG_TIME_INTEGER); - rspamd_rcl_add_default_handler (sub, "sync_timeout", rspamd_rcl_parse_struct_time, - G_STRUCT_OFFSET (struct rspamd_config, statfile_sync_timeout), RSPAMD_CL_FLAG_TIME_INTEGER); - rspamd_rcl_add_default_handler (sub, "max_diff", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_config, max_diff), RSPAMD_CL_FLAG_INT_SIZE); - rspamd_rcl_add_default_handler (sub, "map_watch_interval", rspamd_rcl_parse_struct_time, - G_STRUCT_OFFSET (struct rspamd_config, map_timeout), RSPAMD_CL_FLAG_TIME_FLOAT); - rspamd_rcl_add_default_handler (sub, "dynamic_conf", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_config, dynamic_conf), 0); + UCL_OBJECT, FALSE, TRUE); + rspamd_rcl_add_default_handler (ssub, + "nameserver", + rspamd_rcl_parse_struct_string_list, + G_STRUCT_OFFSET (struct rspamd_config, nameservers), + 0); + rspamd_rcl_add_default_handler (ssub, + "timeout", + rspamd_rcl_parse_struct_time, + G_STRUCT_OFFSET (struct rspamd_config, dns_timeout), + RSPAMD_CL_FLAG_TIME_FLOAT); + rspamd_rcl_add_default_handler (ssub, + "retransmits", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_config, dns_retransmits), + RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_add_default_handler (ssub, + "sockets", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_config, dns_io_per_server), + RSPAMD_CL_FLAG_INT_32); + + rspamd_rcl_add_default_handler (sub, + "raw_mode", + rspamd_rcl_parse_struct_boolean, + G_STRUCT_OFFSET (struct rspamd_config, raw_mode), + 0); + rspamd_rcl_add_default_handler (sub, + "one_shot", + rspamd_rcl_parse_struct_boolean, + G_STRUCT_OFFSET (struct rspamd_config, one_shot_mode), + 0); + rspamd_rcl_add_default_handler (sub, + "check_attachements", + rspamd_rcl_parse_struct_boolean, + G_STRUCT_OFFSET (struct rspamd_config, check_text_attachements), + 0); + rspamd_rcl_add_default_handler (sub, + "tempdir", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_config, temp_dir), + RSPAMD_CL_FLAG_STRING_PATH); + rspamd_rcl_add_default_handler (sub, + "pidfile", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_config, pid_file), + RSPAMD_CL_FLAG_STRING_PATH); + rspamd_rcl_add_default_handler (sub, + "filters", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_config, filters_str), + 0); + rspamd_rcl_add_default_handler (sub, + "sync_interval", + rspamd_rcl_parse_struct_time, + G_STRUCT_OFFSET (struct rspamd_config, statfile_sync_interval), + RSPAMD_CL_FLAG_TIME_INTEGER); + rspamd_rcl_add_default_handler (sub, + "sync_timeout", + rspamd_rcl_parse_struct_time, + G_STRUCT_OFFSET (struct rspamd_config, statfile_sync_timeout), + RSPAMD_CL_FLAG_TIME_INTEGER); + rspamd_rcl_add_default_handler (sub, + "max_diff", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_config, max_diff), + RSPAMD_CL_FLAG_INT_SIZE); + rspamd_rcl_add_default_handler (sub, + "map_watch_interval", + rspamd_rcl_parse_struct_time, + G_STRUCT_OFFSET (struct rspamd_config, map_timeout), + RSPAMD_CL_FLAG_TIME_FLOAT); + rspamd_rcl_add_default_handler (sub, + "dynamic_conf", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_config, dynamic_conf), + 0); rspamd_rcl_add_default_handler (sub, "rrd", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_config, rrd_file), RSPAMD_CL_FLAG_STRING_PATH); - rspamd_rcl_add_default_handler (sub, "history_file", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_config, history_file), RSPAMD_CL_FLAG_STRING_PATH); - rspamd_rcl_add_default_handler (sub, "use_mlock", rspamd_rcl_parse_struct_boolean, - G_STRUCT_OFFSET (struct rspamd_config, mlock_statfile_pool), 0); - rspamd_rcl_add_default_handler (sub, "strict_protocol_headers", rspamd_rcl_parse_struct_boolean, - G_STRUCT_OFFSET (struct rspamd_config, strict_protocol_headers), 0); + G_STRUCT_OFFSET (struct rspamd_config, + rrd_file), RSPAMD_CL_FLAG_STRING_PATH); + rspamd_rcl_add_default_handler (sub, + "history_file", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_config, history_file), + RSPAMD_CL_FLAG_STRING_PATH); + rspamd_rcl_add_default_handler (sub, + "use_mlock", + rspamd_rcl_parse_struct_boolean, + G_STRUCT_OFFSET (struct rspamd_config, mlock_statfile_pool), + 0); + rspamd_rcl_add_default_handler (sub, + "strict_protocol_headers", + rspamd_rcl_parse_struct_boolean, + G_STRUCT_OFFSET (struct rspamd_config, strict_protocol_headers), + 0); /** * Metric section */ - sub = rspamd_rcl_add_section (&new, "metric", rspamd_rcl_metric_handler, UCL_OBJECT, - FALSE, TRUE); + sub = rspamd_rcl_add_section (&new, + "metric", + rspamd_rcl_metric_handler, + UCL_OBJECT, + FALSE, + TRUE); /** * Worker section */ - sub = rspamd_rcl_add_section (&new, "worker", rspamd_rcl_worker_handler, UCL_OBJECT, - FALSE, TRUE); - rspamd_rcl_add_default_handler (sub, "count", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_worker_conf, count), RSPAMD_CL_FLAG_INT_16); - rspamd_rcl_add_default_handler (sub, "max_files", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_worker_conf, rlimit_nofile), RSPAMD_CL_FLAG_INT_32); - rspamd_rcl_add_default_handler (sub, "max_core", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_worker_conf, rlimit_maxcore), RSPAMD_CL_FLAG_INT_32); + sub = rspamd_rcl_add_section (&new, + "worker", + rspamd_rcl_worker_handler, + UCL_OBJECT, + FALSE, + TRUE); + rspamd_rcl_add_default_handler (sub, + "count", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_worker_conf, count), + RSPAMD_CL_FLAG_INT_16); + rspamd_rcl_add_default_handler (sub, + "max_files", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_worker_conf, rlimit_nofile), + RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_add_default_handler (sub, + "max_core", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_worker_conf, rlimit_maxcore), + RSPAMD_CL_FLAG_INT_32); /** * Lua handler */ - sub = rspamd_rcl_add_section (&new, "lua", rspamd_rcl_lua_handler, UCL_STRING, - FALSE, TRUE); + sub = rspamd_rcl_add_section (&new, + "lua", + rspamd_rcl_lua_handler, + UCL_STRING, + FALSE, + TRUE); /** * Modules handler */ - sub = rspamd_rcl_add_section (&new, "modules", rspamd_rcl_modules_handler, UCL_OBJECT, - FALSE, FALSE); + sub = rspamd_rcl_add_section (&new, + "modules", + rspamd_rcl_modules_handler, + UCL_OBJECT, + FALSE, + FALSE); /** * Classifiers handler */ - sub = rspamd_rcl_add_section (&new, "classifier", rspamd_rcl_classifier_handler, UCL_OBJECT, - FALSE, TRUE); - ssub = rspamd_rcl_add_section (&sub->subsections, "statfile", rspamd_rcl_statfile_handler, - UCL_OBJECT, TRUE, TRUE); - rspamd_rcl_add_default_handler (ssub, "symbol", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_statfile_config, symbol), 0); - rspamd_rcl_add_default_handler (ssub, "path", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_statfile_config, path), RSPAMD_CL_FLAG_STRING_PATH); - rspamd_rcl_add_default_handler (ssub, "label", rspamd_rcl_parse_struct_string, - G_STRUCT_OFFSET (struct rspamd_statfile_config, label), 0); - rspamd_rcl_add_default_handler (ssub, "size", rspamd_rcl_parse_struct_integer, - G_STRUCT_OFFSET (struct rspamd_statfile_config, size), RSPAMD_CL_FLAG_INT_SIZE); - rspamd_rcl_add_default_handler (ssub, "spam", rspamd_rcl_parse_struct_boolean, - G_STRUCT_OFFSET (struct rspamd_statfile_config, is_spam), 0); + sub = rspamd_rcl_add_section (&new, + "classifier", + rspamd_rcl_classifier_handler, + UCL_OBJECT, + FALSE, + TRUE); + ssub = rspamd_rcl_add_section (&sub->subsections, + "statfile", + rspamd_rcl_statfile_handler, + UCL_OBJECT, + TRUE, + TRUE); + rspamd_rcl_add_default_handler (ssub, + "symbol", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_statfile_config, symbol), + 0); + rspamd_rcl_add_default_handler (ssub, + "path", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_statfile_config, path), + RSPAMD_CL_FLAG_STRING_PATH); + rspamd_rcl_add_default_handler (ssub, + "label", + rspamd_rcl_parse_struct_string, + G_STRUCT_OFFSET (struct rspamd_statfile_config, label), + 0); + rspamd_rcl_add_default_handler (ssub, + "size", + rspamd_rcl_parse_struct_integer, + G_STRUCT_OFFSET (struct rspamd_statfile_config, size), + RSPAMD_CL_FLAG_INT_SIZE); + rspamd_rcl_add_default_handler (ssub, + "spam", + rspamd_rcl_parse_struct_boolean, + G_STRUCT_OFFSET (struct rspamd_statfile_config, is_spam), + 0); /** * Composites handler */ - sub = rspamd_rcl_add_section (&new, "composite", rspamd_rcl_composite_handler, UCL_OBJECT, - FALSE, TRUE); + sub = rspamd_rcl_add_section (&new, + "composite", + rspamd_rcl_composite_handler, + UCL_OBJECT, + FALSE, + TRUE); return new; } struct rspamd_rcl_section * rspamd_rcl_config_get_section (struct rspamd_rcl_section *top, - const char *path) + const char *path) { struct rspamd_rcl_section *cur, *found; char **path_components; @@ -1109,7 +1413,7 @@ rspamd_rcl_config_get_section (struct rspamd_rcl_section *top, ncomponents = g_strv_length (path_components); cur = top; - for (i = 0; i < ncomponents; i ++) { + for (i = 0; i < ncomponents; i++) { if (cur == NULL) { g_strfreev (path_components); return NULL; @@ -1128,23 +1432,27 @@ rspamd_rcl_config_get_section (struct rspamd_rcl_section *top, gboolean rspamd_read_rcl_config (struct rspamd_rcl_section *top, - struct rspamd_config *cfg, const ucl_object_t *obj, GError **err) + struct rspamd_config *cfg, const ucl_object_t *obj, GError **err) { const ucl_object_t *found, *cur_obj; struct rspamd_rcl_section *cur, *tmp; if (obj->type != UCL_OBJECT) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "top configuration must be an object"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "top configuration must be an object"); return FALSE; } /* Iterate over known sections and ignore unknown ones */ - HASH_ITER (hh, top, cur, tmp) { + HASH_ITER (hh, top, cur, tmp) + { found = ucl_object_find_key (obj, cur->name); if (found == NULL) { if (cur->required) { g_set_error (err, CFG_RCL_ERROR, ENOENT, - "required section %s is missing", cur->name); + "required section %s is missing", cur->name); return FALSE; } } @@ -1153,18 +1461,23 @@ rspamd_read_rcl_config (struct rspamd_rcl_section *top, if (cur->strict_type) { if (cur->type != found->type) { g_set_error (err, CFG_RCL_ERROR, EINVAL, - "object in section %s has invalid type", cur->name); + "object in section %s has invalid type", cur->name); return FALSE; } } - LL_FOREACH (found, cur_obj) { + LL_FOREACH (found, cur_obj) + { if (cur->handler != NULL) { if (!cur->handler (cfg, cur_obj, NULL, cur, err)) { return FALSE; } } else { - rspamd_rcl_section_parse_defaults (cur, cfg, cur_obj, cfg, err); + rspamd_rcl_section_parse_defaults (cur, + cfg, + cur_obj, + cfg, + err); } } } @@ -1178,19 +1491,24 @@ rspamd_read_rcl_config (struct rspamd_rcl_section *top, return TRUE; } -gboolean rspamd_rcl_section_parse_defaults (struct rspamd_rcl_section *section, - struct rspamd_config *cfg, const ucl_object_t *obj, gpointer ptr, - GError **err) +gboolean +rspamd_rcl_section_parse_defaults (struct rspamd_rcl_section *section, + struct rspamd_config *cfg, const ucl_object_t *obj, gpointer ptr, + GError **err) { const ucl_object_t *found; struct rspamd_rcl_default_handler_data *cur, *tmp; if (obj->type != UCL_OBJECT) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "default configuration must be an object"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "default configuration must be an object"); return FALSE; } - HASH_ITER (hh, section->default_parser, cur, tmp) { + HASH_ITER (hh, section->default_parser, cur, tmp) + { found = ucl_object_find_key (obj, cur->key); if (found != NULL) { cur->pd.user_struct = ptr; @@ -1204,8 +1522,11 @@ gboolean rspamd_rcl_section_parse_defaults (struct rspamd_rcl_section *section, } gboolean -rspamd_rcl_parse_struct_string (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) +rspamd_rcl_parse_struct_string (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err) { struct rspamd_rcl_struct_parser *pd = ud; gchar **target; @@ -1214,7 +1535,8 @@ rspamd_rcl_parse_struct_string (struct rspamd_config *cfg, const ucl_object_t *o target = (gchar **)(((gchar *)pd->user_struct) + pd->offset); switch (obj->type) { case UCL_STRING: - *target = rspamd_mempool_strdup (cfg->cfg_pool, ucl_copy_value_trash (obj)); + *target = + rspamd_mempool_strdup (cfg->cfg_pool, ucl_copy_value_trash (obj)); break; case UCL_INT: *target = rspamd_mempool_alloc (cfg->cfg_pool, num_str_len); @@ -1229,7 +1551,10 @@ rspamd_rcl_parse_struct_string (struct rspamd_config *cfg, const ucl_object_t *o rspamd_snprintf (*target, num_str_len, "%b", (gboolean)obj->value.iv); break; default: - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert object or array to string"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert object or array to string"); return FALSE; } @@ -1237,8 +1562,11 @@ rspamd_rcl_parse_struct_string (struct rspamd_config *cfg, const ucl_object_t *o } gboolean -rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) +rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err) { struct rspamd_rcl_struct_parser *pd = ud; union { @@ -1253,7 +1581,10 @@ rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, const ucl_object_t * if (pd->flags == RSPAMD_CL_FLAG_INT_32) { target.i32p = (gint32 *)(((gchar *)pd->user_struct) + pd->offset); if (!ucl_object_toint_safe (obj, &val)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert param to integer"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert param to integer"); return FALSE; } *target.i32p = val; @@ -1261,7 +1592,10 @@ rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, const ucl_object_t * else if (pd->flags == RSPAMD_CL_FLAG_INT_64) { target.i64p = (gint64 *)(((gchar *)pd->user_struct) + pd->offset); if (!ucl_object_toint_safe (obj, &val)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert param to integer"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert param to integer"); return FALSE; } *target.i64p = val; @@ -1269,7 +1603,10 @@ rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, const ucl_object_t * else if (pd->flags == RSPAMD_CL_FLAG_INT_SIZE) { target.sp = (gsize *)(((gchar *)pd->user_struct) + pd->offset); if (!ucl_object_toint_safe (obj, &val)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert param to integer"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert param to integer"); return FALSE; } *target.sp = val; @@ -1277,7 +1614,10 @@ rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, const ucl_object_t * else if (pd->flags == RSPAMD_CL_FLAG_INT_16) { target.i16p = (gint16 *)(((gchar *)pd->user_struct) + pd->offset); if (!ucl_object_toint_safe (obj, &val)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert param to integer"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert param to integer"); return FALSE; } *target.i16p = val; @@ -1285,7 +1625,10 @@ rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, const ucl_object_t * else { target.ip = (gint *)(((gchar *)pd->user_struct) + pd->offset); if (!ucl_object_toint_safe (obj, &val)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert param to integer"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert param to integer"); return FALSE; } *target.ip = val; @@ -1295,8 +1638,11 @@ rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, const ucl_object_t * } gboolean -rspamd_rcl_parse_struct_double (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) +rspamd_rcl_parse_struct_double (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err) { struct rspamd_rcl_struct_parser *pd = ud; gdouble *target; @@ -1304,7 +1650,10 @@ rspamd_rcl_parse_struct_double (struct rspamd_config *cfg, const ucl_object_t *o target = (gdouble *)(((gchar *)pd->user_struct) + pd->offset); if (!ucl_object_todouble_safe (obj, target)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert param to double"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert param to double"); return FALSE; } @@ -1312,8 +1661,11 @@ rspamd_rcl_parse_struct_double (struct rspamd_config *cfg, const ucl_object_t *o } gboolean -rspamd_rcl_parse_struct_time (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) +rspamd_rcl_parse_struct_time (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err) { struct rspamd_rcl_struct_parser *pd = ud; union { @@ -1326,17 +1678,22 @@ rspamd_rcl_parse_struct_time (struct rspamd_config *cfg, const ucl_object_t *obj gdouble val; if (!ucl_object_todouble_safe (obj, &val)) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert param to double"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert param to double"); return FALSE; } if (pd->flags == RSPAMD_CL_FLAG_TIME_TIMEVAL) { - target.ptv = (struct timeval *)(((gchar *)pd->user_struct) + pd->offset); + target.ptv = + (struct timeval *)(((gchar *)pd->user_struct) + pd->offset); target.ptv->tv_sec = (glong)val; target.ptv->tv_usec = (val - (glong)val) * 1000000; } else if (pd->flags == RSPAMD_CL_FLAG_TIME_TIMESPEC) { - target.pts = (struct timespec *)(((gchar *)pd->user_struct) + pd->offset); + target.pts = + (struct timespec *)(((gchar *)pd->user_struct) + pd->offset); target.pts->tv_sec = (glong)val; target.pts->tv_nsec = (val - (glong)val) * 1000000000000LL; } @@ -1353,7 +1710,10 @@ rspamd_rcl_parse_struct_time (struct rspamd_config *cfg, const ucl_object_t *obj *target.pu32 = val * 1000; } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "invalid flags to parse time value"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "invalid flags to parse time value"); return FALSE; } @@ -1361,8 +1721,11 @@ rspamd_rcl_parse_struct_time (struct rspamd_config *cfg, const ucl_object_t *obj } gboolean -rspamd_rcl_parse_struct_string_list (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) +rspamd_rcl_parse_struct_string_list (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err) { struct rspamd_rcl_struct_parser *pd = ud; GList **target; @@ -1374,14 +1737,19 @@ rspamd_rcl_parse_struct_string_list (struct rspamd_config *cfg, const ucl_object target = (GList **)(((gchar *)pd->user_struct) + pd->offset); if (obj->type != UCL_ARRAY) { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "an array of strings is expected"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "an array of strings is expected"); return FALSE; } while ((cur = ucl_iterate_object (obj, &iter, true)) != NULL) { switch (cur->type) { case UCL_STRING: - val = rspamd_mempool_strdup (cfg->cfg_pool, ucl_copy_value_trash (cur)); + val = + rspamd_mempool_strdup (cfg->cfg_pool, + ucl_copy_value_trash (cur)); break; case UCL_INT: val = rspamd_mempool_alloc (cfg->cfg_pool, num_str_len); @@ -1396,21 +1764,29 @@ rspamd_rcl_parse_struct_string_list (struct rspamd_config *cfg, const ucl_object rspamd_snprintf (val, num_str_len, "%b", (gboolean)cur->value.iv); break; default: - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert an object or array to string"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert an object or array to string"); return FALSE; } *target = g_list_prepend (*target, val); } /* Add a destructor */ - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)g_list_free, *target); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)g_list_free, + *target); return TRUE; } gboolean -rspamd_rcl_parse_struct_boolean (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err) +rspamd_rcl_parse_struct_boolean (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err) { struct rspamd_rcl_struct_parser *pd = ud; gboolean *target; @@ -1424,7 +1800,10 @@ rspamd_rcl_parse_struct_boolean (struct rspamd_config *cfg, const ucl_object_t * *target = obj->value.iv; } else { - g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot convert an object to boolean"); + g_set_error (err, + CFG_RCL_ERROR, + EINVAL, + "cannot convert an object to boolean"); return FALSE; } @@ -1432,8 +1811,13 @@ rspamd_rcl_parse_struct_boolean (struct rspamd_config *cfg, const ucl_object_t * } void -rspamd_rcl_register_worker_option (struct rspamd_config *cfg, gint type, const gchar *name, - rspamd_rcl_handler_t handler, gpointer target, gsize offset, gint flags) +rspamd_rcl_register_worker_option (struct rspamd_config *cfg, + gint type, + const gchar *name, + rspamd_rcl_handler_t handler, + gpointer target, + gsize offset, + gint flags) { struct rspamd_worker_param_parser *nhandler; struct rspamd_worker_cfg_parser *nparser; @@ -1441,18 +1825,24 @@ rspamd_rcl_register_worker_option (struct rspamd_config *cfg, gint type, const g HASH_FIND_INT (cfg->wrk_parsers, &type, nparser); if (nparser == NULL) { /* Allocate new parser for this worker */ - nparser = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_worker_cfg_parser)); + nparser = + rspamd_mempool_alloc0 (cfg->cfg_pool, + sizeof (struct rspamd_worker_cfg_parser)); nparser->type = type; HASH_ADD_INT (cfg->wrk_parsers, type, nparser); } HASH_FIND_STR (nparser->parsers, name, nhandler); if (nhandler != NULL) { - msg_warn ("handler for parameter %s is already registered for worker type %s", - name, g_quark_to_string (type)); + msg_warn ( + "handler for parameter %s is already registered for worker type %s", + name, + g_quark_to_string (type)); return; } - nhandler = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_worker_param_parser)); + nhandler = + rspamd_mempool_alloc0 (cfg->cfg_pool, + sizeof (struct rspamd_worker_param_parser)); nhandler->name = name; nhandler->parser.flags = flags; nhandler->parser.offset = offset; @@ -1464,13 +1854,15 @@ rspamd_rcl_register_worker_option (struct rspamd_config *cfg, gint type, const g void rspamd_rcl_register_worker_parser (struct rspamd_config *cfg, gint type, - gboolean (*func)(ucl_object_t *, gpointer), gpointer ud) + gboolean (*func)(ucl_object_t *, gpointer), gpointer ud) { struct rspamd_worker_cfg_parser *nparser; HASH_FIND_INT (cfg->wrk_parsers, &type, nparser); if (nparser == NULL) { /* Allocate new parser for this worker */ - nparser = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_worker_cfg_parser)); + nparser = + rspamd_mempool_alloc0 (cfg->cfg_pool, + sizeof (struct rspamd_worker_cfg_parser)); nparser->type = type; HASH_ADD_INT (cfg->wrk_parsers, type, nparser); } diff --git a/src/libserver/cfg_rcl.h b/src/libserver/cfg_rcl.h index 6db0b0d81..6ba197be8 100644 --- a/src/libserver/cfg_rcl.h +++ b/src/libserver/cfg_rcl.h @@ -63,15 +63,17 @@ struct rspamd_rcl_struct_parser { * @param err error object * @return TRUE if a section has been parsed */ -typedef gboolean (*rspamd_rcl_handler_t) (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err); +typedef gboolean (*rspamd_rcl_handler_t) (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, struct rspamd_rcl_section *section, GError **err); /** * A handler type that is called at the end of section parsing * @param cfg configuration * @param ud user data */ -typedef void (*rspamd_rcl_section_fin_t)(struct rspamd_config *cfg, gpointer ud); +typedef void (*rspamd_rcl_section_fin_t)(struct rspamd_config *cfg, + gpointer ud); struct rspamd_rcl_default_handler_data { struct rspamd_rcl_struct_parser pd; @@ -81,12 +83,12 @@ struct rspamd_rcl_default_handler_data { }; struct rspamd_rcl_section { - const gchar *name; /**< name of section */ - rspamd_rcl_handler_t handler; /**< handler of section attributes */ - enum ucl_type type; /**< type of attribute */ - gboolean required; /**< whether this param is required */ - gboolean strict_type; /**< whether we need strict type */ - UT_hash_handle hh; /** hash handle */ + const gchar *name; /**< name of section */ + rspamd_rcl_handler_t handler; /**< handler of section attributes */ + enum ucl_type type; /**< type of attribute */ + gboolean required; /**< whether this param is required */ + gboolean strict_type; /**< whether we need strict type */ + UT_hash_handle hh; /** hash handle */ struct rspamd_rcl_section *subsections; /**< hash table of subsections */ struct rspamd_rcl_default_handler_data *default_parser; /**< generic parsing fields */ rspamd_rcl_section_fin_t fin; /** called at the end of section parsing */ @@ -97,7 +99,7 @@ struct rspamd_rcl_section { * Init common sections known to rspamd * @return top section */ -struct rspamd_rcl_section* rspamd_rcl_config_init (void); +struct rspamd_rcl_section * rspamd_rcl_config_init (void); /** * Get a section specified by path, it understand paths separated by '/' character @@ -105,8 +107,9 @@ struct rspamd_rcl_section* rspamd_rcl_config_init (void); * @param path '/' divided path * @return */ -struct rspamd_rcl_section *rspamd_rcl_config_get_section (struct rspamd_rcl_section *top, - const char *path); +struct rspamd_rcl_section * rspamd_rcl_config_get_section ( + struct rspamd_rcl_section *top, + const char *path); /** * Read RCL configuration and parse it to a config file @@ -116,7 +119,7 @@ struct rspamd_rcl_section *rspamd_rcl_config_get_section (struct rspamd_rcl_sect * @return TRUE if an object can be parsed */ gboolean rspamd_read_rcl_config (struct rspamd_rcl_section *top, - struct rspamd_config *cfg, const ucl_object_t *obj, GError **err); + struct rspamd_config *cfg, const ucl_object_t *obj, GError **err); /** @@ -129,8 +132,8 @@ gboolean rspamd_read_rcl_config (struct rspamd_rcl_section *top, * @return TRUE if the object has been parsed */ gboolean rspamd_rcl_section_parse_defaults (struct rspamd_rcl_section *section, - struct rspamd_config *cfg, const ucl_object_t *obj, gpointer ptr, - GError **err); + struct rspamd_config *cfg, const ucl_object_t *obj, gpointer ptr, + GError **err); /** * Here is a section of common handlers that accepts rcl_struct_parser * which itself contains a struct pointer and the offset of a member in a @@ -146,8 +149,11 @@ gboolean rspamd_rcl_section_parse_defaults (struct rspamd_rcl_section *section, * @param err error pointer * @return TRUE if a string value has been successfully parsed */ -gboolean rspamd_rcl_parse_struct_string (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err); +gboolean rspamd_rcl_parse_struct_string (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err); /** * Parse an integer field of a structure @@ -158,8 +164,11 @@ gboolean rspamd_rcl_parse_struct_string (struct rspamd_config *cfg, const ucl_ob * @param err error pointer * @return TRUE if a value has been successfully parsed */ -gboolean rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err); +gboolean rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err); /** @@ -171,8 +180,11 @@ gboolean rspamd_rcl_parse_struct_integer (struct rspamd_config *cfg, const ucl_o * @param err error pointer * @return TRUE if a value has been successfully parsed */ -gboolean rspamd_rcl_parse_struct_double (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err); +gboolean rspamd_rcl_parse_struct_double (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err); /** * Parse a time field of a structure @@ -183,8 +195,11 @@ gboolean rspamd_rcl_parse_struct_double (struct rspamd_config *cfg, const ucl_ob * @param err error pointer * @return TRUE if a value has been successfully parsed */ -gboolean rspamd_rcl_parse_struct_time (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err); +gboolean rspamd_rcl_parse_struct_time (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err); /** * Parse a string list field of a structure presented by a GList* object @@ -195,8 +210,11 @@ gboolean rspamd_rcl_parse_struct_time (struct rspamd_config *cfg, const ucl_obje * @param err error pointer * @return TRUE if a value has been successfully parsed */ -gboolean rspamd_rcl_parse_struct_string_list (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err); +gboolean rspamd_rcl_parse_struct_string_list (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err); /** * Parse a boolean field of a structure @@ -207,8 +225,11 @@ gboolean rspamd_rcl_parse_struct_string_list (struct rspamd_config *cfg, const u * @param err error pointer * @return TRUE if a value has been successfully parsed */ -gboolean rspamd_rcl_parse_struct_boolean (struct rspamd_config *cfg, const ucl_object_t *obj, - gpointer ud, struct rspamd_rcl_section *section, GError **err); +gboolean rspamd_rcl_parse_struct_boolean (struct rspamd_config *cfg, + const ucl_object_t *obj, + gpointer ud, + struct rspamd_rcl_section *section, + GError **err); /** * Utility functions @@ -223,8 +244,13 @@ gboolean rspamd_rcl_parse_struct_boolean (struct rspamd_config *cfg, const ucl_o * @param target opaque target structure * @param offset offset inside a structure */ -void rspamd_rcl_register_worker_option (struct rspamd_config *cfg, gint type, const gchar *name, - rspamd_rcl_handler_t handler, gpointer target, gsize offset, gint flags); +void rspamd_rcl_register_worker_option (struct rspamd_config *cfg, + gint type, + const gchar *name, + rspamd_rcl_handler_t handler, + gpointer target, + gsize offset, + gint flags); /** * Regiester a default parser for a worker @@ -234,5 +260,5 @@ void rspamd_rcl_register_worker_option (struct rspamd_config *cfg, gint type, co * @param ud userdata for handler function */ void rspamd_rcl_register_worker_parser (struct rspamd_config *cfg, gint type, - gboolean (*func)(ucl_object_t *, gpointer), gpointer ud); + gboolean (*func)(ucl_object_t *, gpointer), gpointer ud); #endif /* CFG_RCL_H_ */ diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c index e1652ac55..8084baea1 100644 --- a/src/libserver/cfg_utils.c +++ b/src/libserver/cfg_utils.c @@ -44,18 +44,22 @@ struct rspamd_ucl_map_cbdata { struct rspamd_config *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 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 **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; + 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; @@ -90,12 +94,18 @@ parse_host_port_priority_strv (rspamd_mempool_t *pool, gchar **tokens, 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)); + 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)); + msg_warn ("cannot parse port: %s, error: %s", + tokens[1], + *err_str, + strerror (errno)); hints.ai_flags ^= AI_NUMERICSERV; } else { @@ -114,7 +124,11 @@ parse_host_port_priority_strv (rspamd_mempool_t *pool, gchar **tokens, 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)); + msg_warn ( + "cannot parse priority: %s, at symbol %c, error: %s", + tokens[1], + *err_str, + strerror (errno)); } else { *priority = priority_parsed; @@ -131,23 +145,32 @@ parse_host_port_priority_strv (rspamd_mempool_t *pool, gchar **tokens, } if ((r = getaddrinfo (cur_tok, cur_port, &hints, &res)) == 0) { - memcpy (&addr_holder, res->ai_addr, MIN (sizeof (addr_holder), res->ai_addrlen)); + 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); + 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); + 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)); + msg_err ("address resolution for %s failed: %s", + tokens[0], + gai_strerror (r)); goto err; } @@ -161,10 +184,14 @@ err: } gboolean -rspamd_parse_host_port_priority (rspamd_mempool_t *pool, const gchar *str, gchar **addr, guint16 *port, guint *priority) +rspamd_parse_host_port_priority (rspamd_mempool_t *pool, + const gchar *str, + gchar **addr, + guint16 *port, + guint *priority) { - gchar **tokens; - gboolean ret; + gchar **tokens; + gboolean ret; tokens = g_strsplit_set (str, ":", 0); if (!tokens || !tokens[0]) { @@ -179,19 +206,27 @@ rspamd_parse_host_port_priority (rspamd_mempool_t *pool, const gchar *str, gchar } gboolean -rspamd_parse_host_port (rspamd_mempool_t *pool, const gchar *str, gchar **addr, guint16 *port) +rspamd_parse_host_port (rspamd_mempool_t *pool, + const gchar *str, + gchar **addr, + guint16 *port) { return rspamd_parse_host_port_priority (pool, str, addr, port, NULL); } gboolean -rspamd_parse_host_priority (rspamd_mempool_t *pool, const gchar *str, gchar **addr, guint *priority) +rspamd_parse_host_priority (rspamd_mempool_t *pool, + const gchar *str, + gchar **addr, + guint *priority) { return rspamd_parse_host_port_priority (pool, str, addr, NULL, priority); } gboolean -rspamd_parse_bind_line (struct rspamd_config *cfg, struct rspamd_worker_conf *cf, const gchar *str) +rspamd_parse_bind_line (struct rspamd_config *cfg, + struct rspamd_worker_conf *cf, + const gchar *str) { struct rspamd_worker_bind_conf *cnf; gchar **tokens, *tmp, *err; @@ -206,7 +241,9 @@ rspamd_parse_bind_line (struct rspamd_config *cfg, struct rspamd_worker_conf *cf return FALSE; } - cnf = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_worker_bind_conf)); + 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; @@ -221,16 +258,18 @@ rspamd_parse_bind_line (struct rspamd_config *cfg, struct rspamd_worker_conf *cf 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))) { + &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 = + 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))) { + &cnf->bind_host, &cnf->bind_port, NULL, DEFAULT_BIND_PORT))) { LL_PREPEND (cf->bind_conf, cnf); } tokens[0] = tmp; @@ -287,8 +326,10 @@ rspamd_config_defaults (struct rspamd_config *cfg) 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->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); @@ -301,8 +342,8 @@ rspamd_config_defaults (struct rspamd_config *cfg) void rspamd_config_free (struct rspamd_config *cfg) { - GList *cur; - struct rspamd_symbols_group *gr; + GList *cur; + struct rspamd_symbols_group *gr; remove_all_maps (cfg); ucl_obj_unref (cfg->rcl_obj); @@ -337,8 +378,10 @@ rspamd_config_free (struct rspamd_config *cfg) rspamd_mempool_delete (cfg->cfg_pool); } -const ucl_object_t * -rspamd_config_get_module_opt (struct rspamd_config *cfg, const gchar *module_name, const gchar *opt_name) +const ucl_object_t * +rspamd_config_get_module_opt (struct rspamd_config *cfg, + const gchar *module_name, + const gchar *opt_name) { const ucl_object_t *res = NULL, *sec; @@ -353,8 +396,8 @@ rspamd_config_get_module_opt (struct rspamd_config *cfg, const gchar *module_nam guint64 rspamd_config_parse_limit (const gchar *limit, guint len) { - guint64 result = 0; - const gchar *err_str; + guint64 result = 0; + const gchar *err_str; if (!limit || *limit == '\0' || len == 0) { return 0; @@ -377,7 +420,9 @@ rspamd_config_parse_limit (const gchar *limit, guint len) result *= 1073741824L; } else if (len > 0 && err_str - limit != (gint)len) { - msg_warn ("invalid limit value '%s' at position '%s'", limit, err_str); + msg_warn ("invalid limit value '%s' at position '%s'", + limit, + err_str); result = 0; } } @@ -388,8 +433,8 @@ rspamd_config_parse_limit (const gchar *limit, guint len) gchar rspamd_config_parse_flag (const gchar *str) { - guint len; - gchar c; + guint len; + gchar c; if (!str || !*str) { return -1; @@ -439,15 +484,16 @@ rspamd_config_parse_flag (const gchar *str) } gboolean -rspamd_config_calculate_checksum (struct rspamd_config *cfg) +rspamd_config_calculate_checksum (struct rspamd_config *cfg) { - gint fd; - void *map; - struct stat st; + 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"); + msg_err ( + "config file %s is no longer available, cannot calculate checksum"); return FALSE; } if (stat (cfg->cfg_name, &st) == -1) { @@ -456,37 +502,40 @@ rspamd_config_calculate_checksum (struct rspamd_config *cfg) } /* Now mmap this file to simplify reading process */ - if ((map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + 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); + 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 rspamd_config_post_load (struct rspamd_config *cfg) { #ifdef HAVE_CLOCK_GETTIME - struct timespec ts; + struct timespec ts; #endif - struct metric *def_metric; + 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); + clock_getres (CLOCK_VIRTUAL, &ts); # else - clock_getres (CLOCK_REALTIME, &ts); + clock_getres (CLOCK_REALTIME, &ts); # endif cfg->clock_res = (gint)log10 (1000000 / ts.tv_nsec); @@ -496,12 +545,13 @@ rspamd_config_post_load (struct rspamd_config *cfg) if (cfg->clock_res > 3) { cfg->clock_res = 3; } -#else +#else /* For gettimeofday */ cfg->clock_res = 1; #endif - if ((def_metric = g_hash_table_lookup (cfg->metrics, DEFAULT_METRIC)) == NULL) { + if ((def_metric = + g_hash_table_lookup (cfg->metrics, DEFAULT_METRIC)) == NULL) { def_metric = rspamd_config_new_metric (cfg, NULL); def_metric->name = DEFAULT_METRIC; def_metric->actions[METRIC_ACTION_REJECT].score = DEFAULT_SCORE; @@ -520,14 +570,18 @@ rspamd_config_post_load (struct rspamd_config *cfg) void parse_err (const gchar *fmt, ...) { - va_list aq; - gchar logbuf[BUFSIZ], readbuf[32]; - gint r; + 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 = 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); @@ -537,14 +591,18 @@ parse_err (const gchar *fmt, ...) void parse_warn (const gchar *fmt, ...) { - va_list aq; - gchar logbuf[BUFSIZ], readbuf[32]; - gint r; + 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 = 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); @@ -555,7 +613,7 @@ parse_warn (const gchar *fmt, ...) void rspamd_config_unescape_quotes (gchar *line) { - gchar *c = line, *t; + gchar *c = line, *t; while (*c) { if (*c == '\\' && *(c + 1) == '"') { @@ -569,12 +627,12 @@ rspamd_config_unescape_quotes (gchar *line) } } -GList * +GList * rspamd_config_parse_comma_list (rspamd_mempool_t * pool, const gchar *line) { - GList *res = NULL; - const gchar *c, *p; - gchar *str; + GList *res = NULL; + const gchar *c, *p; + gchar *str; c = line; p = c; @@ -585,42 +643,57 @@ rspamd_config_parse_comma_list (rspamd_mempool_t * pool, const gchar *line) rspamd_strlcpy (str, c, p - c + 1); res = g_list_prepend (res, str); /* Skip spaces */ - while (g_ascii_isspace (*(++p))); + 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); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_list_free, + res); } return res; } -struct rspamd_classifier_config * -rspamd_config_new_classifier (struct rspamd_config *cfg, struct rspamd_classifier_config *c) +struct rspamd_classifier_config * +rspamd_config_new_classifier (struct rspamd_config *cfg, + struct rspamd_classifier_config *c) { if (c == NULL) { - c = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_classifier_config)); + c = + rspamd_mempool_alloc0 (cfg->cfg_pool, + sizeof (struct rspamd_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); + 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); + 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 rspamd_statfile_config* -rspamd_config_new_statfile (struct rspamd_config *cfg, struct rspamd_statfile_config *c) +struct rspamd_statfile_config * +rspamd_config_new_statfile (struct rspamd_config *cfg, + struct rspamd_statfile_config *c) { if (c == NULL) { - c = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_statfile_config)); + c = + rspamd_mempool_alloc0 (cfg->cfg_pool, + sizeof (struct rspamd_statfile_config)); } return c; @@ -635,25 +708,36 @@ rspamd_config_new_metric (struct rspamd_config *cfg, struct metric *c) 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 ++) { + 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); + 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 rspamd_worker_conf * -rspamd_config_new_worker (struct rspamd_config *cfg, struct rspamd_worker_conf *c) +rspamd_config_new_worker (struct rspamd_config *cfg, + struct rspamd_worker_conf *c) { if (c == NULL) { - c = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_worker_conf)); + c = + rspamd_mempool_alloc0 (cfg->cfg_pool, + sizeof (struct rspamd_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); + 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 @@ -662,13 +746,13 @@ rspamd_config_new_worker (struct rspamd_config *cfg, struct rspamd_worker_conf * 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) +rspamd_include_map_handler (const guchar *data, gsize len, void * ud) { struct rspamd_config *cfg = (struct rspamd_config *)ud; struct rspamd_ucl_map_cbdata *cbdata, **pcbdata; @@ -683,7 +767,12 @@ rspamd_include_map_handler (const guchar *data, gsize len, void* ud) cbdata->cfg = cfg; *pcbdata = cbdata; - return add_map (cfg, map_line, "ucl include", rspamd_ucl_read_cb, rspamd_ucl_fin_cb, (void **)pcbdata); + return add_map (cfg, + map_line, + "ucl include", + rspamd_ucl_read_cb, + rspamd_ucl_fin_cb, + (void **)pcbdata); } /* @@ -709,32 +798,45 @@ rspamd_include_map_handler (const guchar *data, gsize len, void* ud) 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_WWWDIR_MACRO, RSPAMD_WWWDIR); - ucl_parser_register_variable (parser, RSPAMD_PREFIX_MACRO, RSPAMD_PREFIX); + 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_WWWDIR_MACRO, + RSPAMD_WWWDIR); + 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 rspamd_config *cfg) +rspamd_ucl_add_conf_macros (struct ucl_parser *parser, + struct rspamd_config *cfg) { - ucl_parser_register_macro (parser, "include_map", rspamd_include_map_handler, cfg); + ucl_parser_register_macro (parser, + "include_map", + rspamd_include_map_handler, + cfg); } gboolean rspamd_config_read (struct rspamd_config *cfg, const gchar *filename, - const gchar *convert_to, rspamd_rcl_section_fin_t logger_fin, - gpointer logger_ud) + 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; + struct stat st; + gint fd; + gchar *data; + GError *err = NULL; + struct rspamd_rcl_section *top, *logger; gboolean res; struct ucl_parser *parser; @@ -745,10 +847,11 @@ rspamd_config_read (struct rspamd_config *cfg, const gchar *filename, 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) { + 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; @@ -776,7 +879,7 @@ rspamd_config_read (struct rspamd_config *cfg, const gchar *filename, top = rspamd_rcl_config_init (); err = NULL; - HASH_FIND_STR(top, "logging", logger); + HASH_FIND_STR (top, "logging", logger); if (logger != NULL) { logger->fin = logger_fin; logger->fin_ud = logger_ud; @@ -793,7 +896,7 @@ rspamd_config_read (struct rspamd_config *cfg, const gchar *filename, static void symbols_classifiers_callback (gpointer key, gpointer value, gpointer ud) { - struct rspamd_config *cfg = ud; + struct rspamd_config *cfg = ud; register_virtual_symbol (&cfg->cache, key, 1.0); } @@ -801,14 +904,16 @@ symbols_classifiers_callback (gpointer key, gpointer value, gpointer ud) void rspamd_config_insert_classify_symbols (struct rspamd_config *cfg) { - g_hash_table_foreach (cfg->classifiers_symbols, symbols_classifiers_callback, cfg); + g_hash_table_foreach (cfg->classifiers_symbols, + symbols_classifiers_callback, + cfg); } -struct rspamd_classifier_config* +struct rspamd_classifier_config * rspamd_config_find_classifier (struct rspamd_config *cfg, const gchar *name) { - GList *cur; - struct rspamd_classifier_config *cf; + GList *cur; + struct rspamd_classifier_config *cf; if (name == NULL) { return NULL; @@ -831,9 +936,9 @@ rspamd_config_find_classifier (struct rspamd_config *cfg, const gchar *name) gboolean rspamd_config_check_statfiles (struct rspamd_classifier_config *cf) { - struct rspamd_statfile_config *st; - gboolean has_other = FALSE, res = FALSE, cur_class; - GList *cur; + struct rspamd_statfile_config *st; + gboolean has_other = FALSE, res = FALSE, cur_class; + GList *cur; /* First check classes directly */ cur = cf->statfiles; @@ -884,8 +989,11 @@ rspamd_config_check_statfiles (struct rspamd_classifier_config *cf) return res; } -static gchar* -rspamd_ucl_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +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; @@ -905,7 +1013,8 @@ rspamd_ucl_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map 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; + struct rspamd_ucl_map_cbdata *cbdata = data->cur_data, *prev = + data->prev_data; ucl_object_t *obj; struct ucl_parser *parser; guint32 checksum; @@ -926,8 +1035,11 @@ rspamd_ucl_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) 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)); + 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 { @@ -939,16 +1051,18 @@ rspamd_ucl_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) } } else { - msg_info ("do not reload map %s, checksum is the same: %d", data->map->uri, checksum); + msg_info ("do not reload map %s, checksum is the same: %d", + data->map->uri, + checksum); } } gboolean rspamd_config_parse_ip_list (const gchar *ip_list, radix_tree_t **tree) { - gchar **strvec, **cur; - struct in_addr ina; - guint32 mask; + gchar **strvec, **cur; + struct in_addr ina; + guint32 mask; strvec = g_strsplit_set (ip_list, ",", 0); cur = strvec; @@ -961,7 +1075,7 @@ rspamd_config_parse_ip_list (const gchar *ip_list, radix_tree_t **tree) } radix32tree_add (*tree, htonl (ina.s_addr), mask, 1); } - cur ++; + cur++; } return (*tree != NULL); diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c index abc8ddc05..c074153ab 100644 --- a/src/libserver/dkim.c +++ b/src/libserver/dkim.c @@ -28,20 +28,57 @@ #include "dns.h" /* Parser of dkim params */ -typedef gboolean (*dkim_parse_param_f) (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); - -static gboolean rspamd_dkim_parse_signature (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_signalg (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_domain (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_canonalg (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_ignore (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_selector (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_hdrlist (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_version (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_timestamp (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_expiration (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_bodyhash (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); -static gboolean rspamd_dkim_parse_bodylength (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err); +typedef gboolean (*dkim_parse_param_f) (rspamd_dkim_context_t * ctx, + const gchar *param, gsize len, GError **err); + +static gboolean rspamd_dkim_parse_signature (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_signalg (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_domain (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_canonalg (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_ignore (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_selector (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_hdrlist (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_version (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_timestamp (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_expiration (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_bodyhash (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); +static gboolean rspamd_dkim_parse_bodylength (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); static const dkim_parse_param_f parser_funcs[] = { @@ -75,7 +112,10 @@ dkim_error_quark (void) /* Parsers implementation */ static gboolean -rspamd_dkim_parse_signature (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_signature (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { ctx->b = rspamd_mempool_alloc (ctx->pool, len + 1); rspamd_strlcpy (ctx->b, param, len + 1); @@ -93,7 +133,10 @@ rspamd_dkim_parse_signature (rspamd_dkim_context_t* ctx, const gchar *param, gsi } static gboolean -rspamd_dkim_parse_signalg (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_signalg (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { if (len == 8) { if (memcmp (param, "rsa-sha1", len) == 0) { @@ -108,12 +151,18 @@ rspamd_dkim_parse_signalg (rspamd_dkim_context_t* ctx, const gchar *param, gsize } } - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_INVALID_A, "invalid dkim sign algorithm"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_INVALID_A, + "invalid dkim sign algorithm"); return FALSE; } static gboolean -rspamd_dkim_parse_domain (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_domain (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { ctx->domain = rspamd_mempool_alloc (ctx->pool, len + 1); rspamd_strlcpy (ctx->domain, param, len + 1); @@ -121,10 +170,13 @@ rspamd_dkim_parse_domain (rspamd_dkim_context_t* ctx, const gchar *param, gsize } static gboolean -rspamd_dkim_parse_canonalg (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_canonalg (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { - const gchar *p, *slash = NULL, *end = param + len; - gsize sl = 0; + const gchar *p, *slash = NULL, *end = param + len; + gsize sl = 0; p = param; while (p != end) { @@ -132,8 +184,8 @@ rspamd_dkim_parse_canonalg (rspamd_dkim_context_t* ctx, const gchar *param, gsiz slash = p; break; } - p ++; - sl ++; + p++; + sl++; } if (slash == NULL) { @@ -160,7 +212,7 @@ rspamd_dkim_parse_canonalg (rspamd_dkim_context_t* ctx, const gchar *param, gsiz } /* Check body */ len -= sl + 1; - slash ++; + slash++; if (len == 6 && memcmp (slash, "simple", len) == 0) { ctx->body_canon_type = DKIM_CANON_SIMPLE; return TRUE; @@ -172,32 +224,41 @@ rspamd_dkim_parse_canonalg (rspamd_dkim_context_t* ctx, const gchar *param, gsiz } err: - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_INVALID_A, "invalid dkim canonization algorithm"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_INVALID_A, + "invalid dkim canonization algorithm"); return FALSE; } static gboolean -rspamd_dkim_parse_ignore (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_ignore (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { /* Just ignore unused params */ return TRUE; } static gboolean -rspamd_dkim_parse_selector (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_selector (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { ctx->selector = rspamd_mempool_alloc (ctx->pool, len + 1); rspamd_strlcpy (ctx->selector, param, len + 1); return TRUE; } -static struct rspamd_dkim_header* +static struct rspamd_dkim_header * rspamd_dkim_find_header (GPtrArray *arr, const gchar *name, gsize len) { - guint i; - struct rspamd_dkim_header *h; + guint i; + struct rspamd_dkim_header *h; - for (i = 0; i < arr->len; i ++) { + for (i = 0; i < arr->len; i++) { h = g_ptr_array_index (arr, i); if (g_ascii_strncasecmp (h->name, name, len) == 0) { return h; @@ -210,26 +271,29 @@ rspamd_dkim_find_header (GPtrArray *arr, const gchar *name, gsize len) static void rspamd_dkim_hlist_free (void *ud) { - GPtrArray *a = ud; + GPtrArray *a = ud; g_ptr_array_free (a, TRUE); } static gboolean -rspamd_dkim_parse_hdrlist (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_hdrlist (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { - const gchar *c, *p, *end = param + len; - gchar *h; - gboolean from_found = FALSE; - guint count = 0; - struct rspamd_dkim_header *new; + const gchar *c, *p, *end = param + len; + gchar *h; + gboolean from_found = FALSE; + guint count = 0; + struct rspamd_dkim_header *new; p = param; while (p <= end) { if ((*p == ':' || p == end)) { - count ++; + count++; } - p ++; + p++; } if (count > 0) { @@ -243,12 +307,15 @@ rspamd_dkim_parse_hdrlist (rspamd_dkim_context_t* ctx, const gchar *param, gsize p = param; while (p <= end) { if ((*p == ':' || p == end) && p - c > 0) { - if ((new = rspamd_dkim_find_header (ctx->hlist, c, p - c)) != NULL) { - new->count ++; + if ((new = + rspamd_dkim_find_header (ctx->hlist, c, p - c)) != NULL) { + new->count++; } else { /* Insert new header to the list */ - new = rspamd_mempool_alloc (ctx->pool, sizeof (struct rspamd_dkim_header)); + new = + rspamd_mempool_alloc (ctx->pool, + sizeof (struct rspamd_dkim_header)); h = rspamd_mempool_alloc (ctx->pool, p - c + 1); rspamd_strlcpy (h, c, p - c + 1); g_strstrip (h); @@ -261,35 +328,49 @@ rspamd_dkim_parse_hdrlist (rspamd_dkim_context_t* ctx, const gchar *param, gsize g_ptr_array_add (ctx->hlist, new); } c = p + 1; - p ++; + p++; } else { - p ++; + p++; } } if (!ctx->hlist) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_INVALID_H, "invalid dkim header list"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_INVALID_H, + "invalid dkim header list"); return FALSE; } else { if (!from_found) { g_ptr_array_free (ctx->hlist, TRUE); - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_INVALID_H, "invalid dkim header list, from header is missing"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_INVALID_H, + "invalid dkim header list, from header is missing"); return FALSE; } /* Reverse list */ - rspamd_mempool_add_destructor (ctx->pool, (rspamd_mempool_destruct_t)rspamd_dkim_hlist_free, ctx->hlist); + rspamd_mempool_add_destructor (ctx->pool, + (rspamd_mempool_destruct_t)rspamd_dkim_hlist_free, + ctx->hlist); } return TRUE; } static gboolean -rspamd_dkim_parse_version (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_version (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { if (len != 1 || *param != '1') { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_VERSION, "invalid dkim version"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_VERSION, + "invalid dkim version"); return FALSE; } @@ -298,12 +379,18 @@ rspamd_dkim_parse_version (rspamd_dkim_context_t* ctx, const gchar *param, gsize } static gboolean -rspamd_dkim_parse_timestamp (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_timestamp (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { - gulong val; + gulong val; if (!rspamd_strtoul (param, len, &val)) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_UNKNOWN, "invalid dkim timestamp"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "invalid dkim timestamp"); return FALSE; } ctx->timestamp = val; @@ -312,12 +399,18 @@ rspamd_dkim_parse_timestamp (rspamd_dkim_context_t* ctx, const gchar *param, gsi } static gboolean -rspamd_dkim_parse_expiration (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_expiration (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { - gulong val; + gulong val; if (!rspamd_strtoul (param, len, &val)) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_UNKNOWN, "invalid dkim expiration"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "invalid dkim expiration"); return FALSE; } ctx->expiration = val; @@ -326,7 +419,10 @@ rspamd_dkim_parse_expiration (rspamd_dkim_context_t* ctx, const gchar *param, gs } static gboolean -rspamd_dkim_parse_bodyhash (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_bodyhash (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { ctx->bh = rspamd_mempool_alloc (ctx->pool, len + 1); rspamd_strlcpy (ctx->bh, param, len + 1); @@ -344,12 +440,18 @@ rspamd_dkim_parse_bodyhash (rspamd_dkim_context_t* ctx, const gchar *param, gsiz } static gboolean -rspamd_dkim_parse_bodylength (rspamd_dkim_context_t* ctx, const gchar *param, gsize len, GError **err) +rspamd_dkim_parse_bodylength (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) { - gulong val; + gulong val; if (!rspamd_strtoul (param, len, &val)) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_INVALID_L, "invalid dkim body length"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_INVALID_L, + "invalid dkim body length"); return FALSE; } ctx->len = val; @@ -364,21 +466,24 @@ rspamd_dkim_parse_bodylength (rspamd_dkim_context_t* ctx, const gchar *param, gs * @param err pointer to error object * @return new context or NULL */ -rspamd_dkim_context_t* -rspamd_create_dkim_context (const gchar *sig, rspamd_mempool_t *pool, guint time_jitter, GError **err) +rspamd_dkim_context_t * +rspamd_create_dkim_context (const gchar *sig, + rspamd_mempool_t *pool, + guint time_jitter, + GError **err) { - const gchar *p, *c, *tag = NULL, *end; - gsize taglen; - gint param = DKIM_PARAM_UNKNOWN; - time_t now; - rspamd_dkim_context_t *new; + const gchar *p, *c, *tag = NULL, *end; + gsize taglen; + gint param = DKIM_PARAM_UNKNOWN; + time_t now; + rspamd_dkim_context_t *new; enum { DKIM_STATE_TAG = 0, DKIM_STATE_AFTER_TAG, DKIM_STATE_VALUE, DKIM_STATE_SKIP_SPACES = 99, DKIM_STATE_ERROR = 100 - } state, next_state; + } state, next_state; new = rspamd_mempool_alloc0 (pool, sizeof (rspamd_dkim_context_t)); @@ -400,17 +505,20 @@ rspamd_create_dkim_context (const gchar *sig, rspamd_mempool_t *pool, guint time taglen = p - c; while (*p && g_ascii_isspace (*p)) { /* Skip spaces before '=' sign */ - p ++; + p++; } if (*p != '=') { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_UNKNOWN, "invalid dkim param"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "invalid dkim param"); state = DKIM_STATE_ERROR; } else { state = DKIM_STATE_SKIP_SPACES; next_state = DKIM_STATE_AFTER_TAG; param = DKIM_PARAM_UNKNOWN; - p ++; + p++; tag = c; } } @@ -418,19 +526,22 @@ rspamd_create_dkim_context (const gchar *sig, rspamd_mempool_t *pool, guint time state = DKIM_STATE_SKIP_SPACES; next_state = DKIM_STATE_AFTER_TAG; param = DKIM_PARAM_UNKNOWN; - p ++; + p++; tag = c; } else { - taglen ++; - p ++; + taglen++; + p++; } break; case DKIM_STATE_AFTER_TAG: /* We got tag at tag and len at taglen */ switch (taglen) { case 0: - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_UNKNOWN, "zero length dkim param"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "zero length dkim param"); state = DKIM_STATE_ERROR; break; case 1: @@ -476,7 +587,11 @@ rspamd_create_dkim_context (const gchar *sig, rspamd_mempool_t *pool, guint time param = DKIM_PARAM_COPIEDHDRS; break; default: - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_UNKNOWN, "invalid dkim param: %c", *tag); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "invalid dkim param: %c", + *tag); state = DKIM_STATE_ERROR; break; } @@ -486,12 +601,21 @@ rspamd_create_dkim_context (const gchar *sig, rspamd_mempool_t *pool, guint time param = DKIM_PARAM_BODYHASH; } else { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_UNKNOWN, "invalid dkim param: %c%c", tag[0], tag[1]); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "invalid dkim param: %c%c", + tag[0], + tag[1]); state = DKIM_STATE_ERROR; } break; default: - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_UNKNOWN, "invalid dkim param length: %zd", taglen); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "invalid dkim param length: %zd", + taglen); state = DKIM_STATE_ERROR; break; } @@ -503,32 +627,34 @@ rspamd_create_dkim_context (const gchar *sig, rspamd_mempool_t *pool, guint time break; case DKIM_STATE_VALUE: if (*p == ';') { - if (param == DKIM_PARAM_UNKNOWN || !parser_funcs[param](new, c, p - c, err)) { + if (param == DKIM_PARAM_UNKNOWN || + !parser_funcs[param](new, c, p - c, err)) { state = DKIM_STATE_ERROR; } else { state = DKIM_STATE_SKIP_SPACES; next_state = DKIM_STATE_TAG; - p ++; + p++; taglen = 0; } } else if (p == end) { - if (param == DKIM_PARAM_UNKNOWN || !parser_funcs[param](new, c, p - c + 1, err)) { + if (param == DKIM_PARAM_UNKNOWN || + !parser_funcs[param](new, c, p - c + 1, err)) { state = DKIM_STATE_ERROR; } else { /* Finish processing */ - p ++; + p++; } } else { - p ++; + p++; } break; case DKIM_STATE_SKIP_SPACES: if (g_ascii_isspace (*p)) { - p ++; + p++; } else { c = p; @@ -550,62 +676,105 @@ rspamd_create_dkim_context (const gchar *sig, rspamd_mempool_t *pool, guint time /* Now check validity of signature */ if (new->b == NULL) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_EMPTY_B, "b parameter missing"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_EMPTY_B, + "b parameter missing"); return NULL; } if (new->bh == NULL) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_EMPTY_BH, "bh parameter missing"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_EMPTY_BH, + "bh parameter missing"); return NULL; } if (new->domain == NULL) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_EMPTY_D, "domain parameter missing"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_EMPTY_D, + "domain parameter missing"); return NULL; } if (new->selector == NULL) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_EMPTY_S, "selector parameter missing"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_EMPTY_S, + "selector parameter missing"); return NULL; } if (new->ver == 0) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_EMPTY_V, "v parameter missing"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_EMPTY_V, + "v parameter missing"); return NULL; } if (new->hlist == NULL) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_EMPTY_H, "h parameter missing"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_EMPTY_H, + "h parameter missing"); return NULL; } if (new->sig_alg == DKIM_SIGN_UNKNOWN) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_EMPTY_S, "s parameter missing"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_EMPTY_S, + "s parameter missing"); return NULL; } if (new->sig_alg == DKIM_SIGN_RSASHA1) { /* Check bh length */ if (new->bhlen != (guint)g_checksum_type_get_length (G_CHECKSUM_SHA1)) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_BADSIG, "signature has incorrect length: %ud", new->bhlen); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_BADSIG, + "signature has incorrect length: %ud", + new->bhlen); return NULL; } } else if (new->sig_alg == DKIM_SIGN_RSASHA256) { - if (new->bhlen != (guint)g_checksum_type_get_length (G_CHECKSUM_SHA256)) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_BADSIG, "signature has incorrect length: %ud", new->bhlen); + if (new->bhlen != + (guint)g_checksum_type_get_length (G_CHECKSUM_SHA256)) { + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_BADSIG, + "signature has incorrect length: %ud", + new->bhlen); return NULL; } } /* Check expiration */ now = time (NULL); - if (new->timestamp && now < new->timestamp && new->timestamp - now > (gint)time_jitter) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_FUTURE, "signature was made in future, ignoring"); + if (new->timestamp && now < new->timestamp && new->timestamp - now > + (gint)time_jitter) { + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_FUTURE, + "signature was made in future, ignoring"); return NULL; } if (new->expiration && new->expiration < now) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_EXPIRED, "signature has expired"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_EXPIRED, + "signature has expired"); return NULL; } /* Now create dns key to request further */ - taglen = strlen (new->domain) + strlen (new->selector) + sizeof (DKIM_DNSKEYNAME) + 2; + taglen = strlen (new->domain) + strlen (new->selector) + + sizeof (DKIM_DNSKEYNAME) + 2; new->dns_key = rspamd_mempool_alloc (new->pool, taglen); - rspamd_snprintf (new->dns_key, taglen, "%s.%s.%s", new->selector, DKIM_DNSKEYNAME, new->domain); + rspamd_snprintf (new->dns_key, + taglen, + "%s.%s.%s", + new->selector, + DKIM_DNSKEYNAME, + new->domain); /* Create checksums for further operations */ if (new->sig_alg == DKIM_SIGN_RSASHA1) { @@ -617,12 +786,19 @@ rspamd_create_dkim_context (const gchar *sig, rspamd_mempool_t *pool, guint time new->headers_hash = g_checksum_new (G_CHECKSUM_SHA256); } else { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_BADSIG, "signature has unsupported signature algorithm"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_BADSIG, + "signature has unsupported signature algorithm"); return NULL; } - rspamd_mempool_add_destructor (new->pool, (rspamd_mempool_destruct_t)g_checksum_free, new->body_hash); - rspamd_mempool_add_destructor (new->pool, (rspamd_mempool_destruct_t)g_checksum_free, new->headers_hash); + rspamd_mempool_add_destructor (new->pool, + (rspamd_mempool_destruct_t)g_checksum_free, + new->body_hash); + rspamd_mempool_add_destructor (new->pool, + (rspamd_mempool_destruct_t)g_checksum_free, + new->headers_hash); return new; } @@ -633,10 +809,10 @@ struct rspamd_dkim_key_cbdata { gpointer ud; }; -static rspamd_dkim_key_t* +static rspamd_dkim_key_t * rspamd_dkim_make_key (const gchar *keydata, guint keylen, GError **err) { - rspamd_dkim_key_t *key = NULL; + rspamd_dkim_key_t *key = NULL; if (keylen < 3) { msg_err ("DKIM key is too short to be valid"); @@ -660,21 +836,30 @@ rspamd_dkim_make_key (const gchar *keydata, guint keylen, GError **err) #ifdef HAVE_OPENSSL key->key_bio = BIO_new_mem_buf (key->keydata, key->decoded_len); if (key->key_bio == NULL) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_KEYFAIL, "cannot make ssl bio from key"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_KEYFAIL, + "cannot make ssl bio from key"); rspamd_dkim_key_free (key); return NULL; } key->key_evp = d2i_PUBKEY_bio (key->key_bio, NULL); if (key->key_evp == NULL) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_KEYFAIL, "cannot extract pubkey from bio"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_KEYFAIL, + "cannot extract pubkey from bio"); rspamd_dkim_key_free (key); return NULL; } key->key_rsa = EVP_PKEY_get1_RSA (key->key_evp); if (key->key_rsa == NULL) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_KEYFAIL, "cannot extract rsa key from evp key"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_KEYFAIL, + "cannot extract rsa key from evp key"); rspamd_dkim_key_free (key); return NULL; } @@ -699,16 +884,16 @@ rspamd_dkim_key_free (rspamd_dkim_key_t *key) BIO_free (key->key_bio); } #endif - g_slice_free1 (key->keylen, key->keydata); + g_slice_free1 (key->keylen, key->keydata); g_slice_free1 (sizeof (rspamd_dkim_key_t), key); } -static rspamd_dkim_key_t* +static rspamd_dkim_key_t * rspamd_dkim_parse_key (const gchar *txt, gsize *keylen, GError **err) { - const gchar *c, *p, *end; - gint state = 0; - gsize len; + const gchar *c, *p, *end; + gint state = 0; + gsize len; c = txt; p = txt; @@ -725,7 +910,7 @@ rspamd_dkim_parse_key (const gchar *txt, gsize *keylen, GError **err) } else { /* Ignore everything */ - p ++; + p++; } break; case 1: @@ -735,17 +920,21 @@ rspamd_dkim_parse_key (const gchar *txt, gsize *keylen, GError **err) return rspamd_dkim_make_key (c, len, err); } else { - p ++; + p++; } break; } } if (p - c == 0) { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_KEYREVOKED, "key was revoked"); + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_KEYREVOKED, + "key was revoked"); } else { - g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_KEYFAIL, "key was not found"); + g_set_error (err, DKIM_ERROR, DKIM_SIGERROR_KEYFAIL, + "key was not found"); } return NULL; @@ -755,21 +944,28 @@ rspamd_dkim_parse_key (const gchar *txt, gsize *keylen, GError **err) static void rspamd_dkim_dns_cb (struct rdns_reply *reply, gpointer arg) { - struct rspamd_dkim_key_cbdata *cbdata = arg; - rspamd_dkim_key_t *key = NULL; - GError *err = NULL; - struct rdns_reply_entry *elt; - gsize keylen = 0; + struct rspamd_dkim_key_cbdata *cbdata = arg; + rspamd_dkim_key_t *key = NULL; + GError *err = NULL; + struct rdns_reply_entry *elt; + gsize keylen = 0; if (reply->code != RDNS_RC_NOERROR) { - g_set_error (&err, DKIM_ERROR, DKIM_SIGERROR_NOKEY, "dns request to %s failed: %s", cbdata->ctx->dns_key, - rdns_strerror (reply->code)); + g_set_error (&err, + DKIM_ERROR, + DKIM_SIGERROR_NOKEY, + "dns request to %s failed: %s", + cbdata->ctx->dns_key, + rdns_strerror (reply->code)); cbdata->handler (NULL, 0, cbdata->ctx, cbdata->ud, err); } else { - LL_FOREACH (reply->entries, elt) { + LL_FOREACH (reply->entries, elt) + { if (elt->type == RDNS_REQUEST_TXT) { - key = rspamd_dkim_parse_key (elt->content.txt.data, &keylen, &err); + key = rspamd_dkim_parse_key (elt->content.txt.data, + &keylen, + &err); if (key) { key->ttl = elt->ttl; break; @@ -793,30 +989,41 @@ rspamd_dkim_dns_cb (struct rdns_reply *reply, gpointer arg) * @return */ gboolean -rspamd_get_dkim_key (rspamd_dkim_context_t *ctx, struct rspamd_dns_resolver *resolver, - struct rspamd_async_session *s, dkim_key_handler_f handler, gpointer ud) +rspamd_get_dkim_key (rspamd_dkim_context_t *ctx, + struct rspamd_dns_resolver *resolver, + struct rspamd_async_session *s, + dkim_key_handler_f handler, + gpointer ud) { - struct rspamd_dkim_key_cbdata *cbdata; + struct rspamd_dkim_key_cbdata *cbdata; - g_return_val_if_fail (ctx != NULL, FALSE); + g_return_val_if_fail (ctx != NULL, FALSE); g_return_val_if_fail (ctx->dns_key != NULL, FALSE); - cbdata = rspamd_mempool_alloc (ctx->pool, sizeof (struct rspamd_dkim_key_cbdata)); + cbdata = + rspamd_mempool_alloc (ctx->pool, + sizeof (struct rspamd_dkim_key_cbdata)); cbdata->ctx = ctx; cbdata->handler = handler; cbdata->ud = ud; - return make_dns_request (resolver, s, ctx->pool, rspamd_dkim_dns_cb, cbdata, RDNS_REQUEST_TXT, ctx->dns_key); + return make_dns_request (resolver, + s, + ctx->pool, + rspamd_dkim_dns_cb, + cbdata, + RDNS_REQUEST_TXT, + ctx->dns_key); } static gboolean rspamd_dkim_relaxed_body_step (GChecksum *ck, const gchar **start, guint remain) { - const gchar *h; - static gchar buf[BUFSIZ]; - gchar *t; - guint len, inlen; - gboolean got_sp, finished = FALSE; + const gchar *h; + static gchar buf[BUFSIZ]; + gchar *t; + guint len, inlen; + gboolean got_sp, finished = FALSE; if (remain > sizeof (buf)) { len = sizeof (buf); @@ -835,16 +1042,16 @@ rspamd_dkim_relaxed_body_step (GChecksum *ck, const gchar **start, guint remain) /* Ignore spaces at the end of line */ if (got_sp) { got_sp = FALSE; - t --; + t--; } /* Replace a single \n or \r with \r\n */ if (*h == '\n' && *(h - 1) != '\r') { - *t ++ = '\r'; - inlen --; + *t++ = '\r'; + inlen--; } else if (*h == '\r' && *(h + 1) != '\n') { - *t ++ = *h ++; - *t ++ = '\n'; + *t++ = *h++; + *t++ = '\n'; if (inlen > 1) { inlen -= 2; } @@ -852,22 +1059,22 @@ rspamd_dkim_relaxed_body_step (GChecksum *ck, const gchar **start, guint remain) /* It is safe as inlen = sizeof (buf) - 1 */ inlen = 0; } - len --; + len--; continue; } } else if (g_ascii_isspace (*h)) { if (got_sp) { /* Ignore multiply spaces */ - h ++; - len --; + h++; + len--; continue; } else { *t++ = ' '; - h ++; - inlen --; - len --; + h++; + inlen--; + len--; got_sp = TRUE; continue; } @@ -876,15 +1083,15 @@ rspamd_dkim_relaxed_body_step (GChecksum *ck, const gchar **start, guint remain) got_sp = FALSE; } *t++ = *h++; - inlen --; - len --; + inlen--; + len--; } *start = h; if (!finished && *(t - 1) == ' ' && g_ascii_isspace (*h)) { /* Avoid border problems */ - t --; + t--; } #if 0 msg_debug ("update signature with buffer: %*s", t - buf, buf); @@ -897,11 +1104,11 @@ rspamd_dkim_relaxed_body_step (GChecksum *ck, const gchar **start, guint remain) static gboolean rspamd_dkim_simple_body_step (GChecksum *ck, const gchar **start, guint remain) { - const gchar *h; - static gchar buf[BUFSIZ]; - gchar *t; - guint len, inlen; - gboolean finished = FALSE; + const gchar *h; + static gchar buf[BUFSIZ]; + gchar *t; + guint len, inlen; + gboolean finished = FALSE; if (remain > sizeof (buf)) { len = sizeof (buf); @@ -918,12 +1125,12 @@ rspamd_dkim_simple_body_step (GChecksum *ck, const gchar **start, guint remain) if (*h == '\r' || *h == '\n') { /* Replace a single \n or \r with \r\n */ if (*h == '\n' && *(h - 1) != '\r') { - *t ++ = '\r'; - inlen --; + *t++ = '\r'; + inlen--; } else if (*h == '\r' && *(h + 1) != '\n') { - *t ++ = *h ++; - *t ++ = '\n'; + *t++ = *h++; + *t++ = '\n'; if (inlen > 1) { inlen -= 2; } @@ -931,13 +1138,13 @@ rspamd_dkim_simple_body_step (GChecksum *ck, const gchar **start, guint remain) /* It is safe as inlen = sizeof (buf) - 1 */ inlen = 0; } - len --; + len--; continue; } } *t++ = *h++; - inlen --; - len --; + inlen--; + len--; } *start = h; @@ -951,7 +1158,9 @@ rspamd_dkim_simple_body_step (GChecksum *ck, const gchar **start, guint remain) } static gboolean -rspamd_dkim_canonize_body (rspamd_dkim_context_t *ctx, const gchar *start, const gchar *end) +rspamd_dkim_canonize_body (rspamd_dkim_context_t *ctx, + const gchar *start, + const gchar *end) { const gchar *p; @@ -972,10 +1181,10 @@ rspamd_dkim_canonize_body (rspamd_dkim_context_t *ctx, const gchar *start, const p -= 2; } else if (*p == '\n' && *(p - 1) == '\n') { - p --; + p--; } else if (*p == '\r' && *(p - 1) == '\r') { - p --; + p--; } else { break; @@ -994,10 +1203,12 @@ rspamd_dkim_canonize_body (rspamd_dkim_context_t *ctx, const gchar *start, const else { if (ctx->body_canon_type == DKIM_CANON_SIMPLE) { /* Simple canonization */ - while (rspamd_dkim_simple_body_step (ctx->body_hash, &start, end - start)); + while (rspamd_dkim_simple_body_step (ctx->body_hash, &start, + end - start)) ; } else { - while (rspamd_dkim_relaxed_body_step (ctx->body_hash, &start, end - start)); + while (rspamd_dkim_relaxed_body_step (ctx->body_hash, &start, + end - start)) ; } } return TRUE; @@ -1011,29 +1222,29 @@ rspamd_dkim_canonize_body (rspamd_dkim_context_t *ctx, const gchar *start, const static void rspamd_dkim_hash_update (GChecksum *ck, const gchar *begin, gsize len) { - const gchar *p, *c, *end; + const gchar *p, *c, *end; end = begin + len; p = begin; c = p; while (p != end) { if (*p == '\r') { - g_checksum_update (ck, c, p - c); + g_checksum_update (ck, c, p - c); g_checksum_update (ck, CRLF, sizeof (CRLF) - 1); - p ++; + p++; if (*p == '\n') { - p ++; + p++; } c = p; } else if (*p == '\n') { - g_checksum_update (ck, c, p - c); + g_checksum_update (ck, c, p - c); g_checksum_update (ck, CRLF, sizeof (CRLF) - 1); - p ++; + p++; c = p; } else { - p ++; + p++; } } if (p != c) { @@ -1043,10 +1254,12 @@ rspamd_dkim_hash_update (GChecksum *ck, const gchar *begin, gsize len) /* Update hash by signature value (ignoring b= tag) */ static void -rspamd_dkim_signature_update (rspamd_dkim_context_t *ctx, const gchar *begin, guint len) +rspamd_dkim_signature_update (rspamd_dkim_context_t *ctx, + const gchar *begin, + guint len) { - const gchar *p, *c, *end; - gboolean tag, skip; + const gchar *p, *c, *end; + gboolean tag, skip; end = begin + len; p = begin; @@ -1057,7 +1270,9 @@ rspamd_dkim_signature_update (rspamd_dkim_context_t *ctx, const gchar *begin, gu while (p < end) { if (tag && p[0] == 'b' && p[1] == '=') { /* Add to signature */ - msg_debug ("initial update hash with signature part: %*s", p - c + 2, c); + msg_debug ("initial update hash with signature part: %*s", + p - c + 2, + c); rspamd_dkim_hash_update (ctx->headers_hash, c, p - c + 2); skip = TRUE; } @@ -1071,13 +1286,13 @@ rspamd_dkim_signature_update (rspamd_dkim_context_t *ctx, const gchar *begin, gu else if (tag && *p == '=') { tag = FALSE; } - p ++; + p++; } - p --; + p--; /* Skip \r\n at the end */ while ((*p == '\r' || *p == '\n') && p >= c) { - p --; + p--; } if (p - c + 1 > 0) { @@ -1087,12 +1302,15 @@ rspamd_dkim_signature_update (rspamd_dkim_context_t *ctx, const gchar *begin, gu } static gboolean -rspamd_dkim_canonize_header_relaxed (rspamd_dkim_context_t *ctx, const gchar *header, const gchar *header_name, gboolean is_sign) +rspamd_dkim_canonize_header_relaxed (rspamd_dkim_context_t *ctx, + const gchar *header, + const gchar *header_name, + gboolean is_sign) { - const gchar *h; - gchar *t, *buf; - guint inlen; - gboolean got_sp, allocated = FALSE; + const gchar *h; + gchar *t, *buf; + guint inlen; + gboolean got_sp, allocated = FALSE; inlen = strlen (header) + strlen (header_name) + sizeof (":" CRLF); if (inlen > BUFSIZ) { @@ -1108,7 +1326,7 @@ rspamd_dkim_canonize_header_relaxed (rspamd_dkim_context_t *ctx, const gchar *he t = buf; h = header_name; while (*h) { - *t ++ = g_ascii_tolower (*h++); + *t++ = g_ascii_tolower (*h++); } *t++ = ':'; @@ -1116,30 +1334,30 @@ rspamd_dkim_canonize_header_relaxed (rspamd_dkim_context_t *ctx, const gchar *he h = header; /* Skip spaces at the beginning */ while (g_ascii_isspace (*h)) { - h ++; + h++; } got_sp = FALSE; while (*h) { if (g_ascii_isspace (*h)) { if (got_sp) { - h ++; + h++; continue; } else { got_sp = TRUE; - *t ++ = ' '; - h ++; + *t++ = ' '; + h++; continue; } } else { got_sp = FALSE; } - *t ++ = *h ++; + *t++ = *h++; } if (g_ascii_isspace (*(t - 1))) { - t --; + t--; } *t++ = '\r'; *t++ = '\n'; @@ -1167,18 +1385,25 @@ struct rspamd_dkim_sign_chunk { }; static gboolean -rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *headers, - const gchar *header_name, guint count, gboolean is_sign) +rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, + const gchar *headers, + const gchar *header_name, + guint count, + gboolean is_sign) { - const gchar *p, *c; - gint state = 0, hlen; - gboolean found = FALSE; - GArray *to_sign; - struct rspamd_dkim_sign_chunk chunk, *elt; - gint i; + const gchar *p, *c; + gint state = 0, hlen; + gboolean found = FALSE; + GArray *to_sign; + struct rspamd_dkim_sign_chunk chunk, *elt; + gint i; /* This process is very similar to raw headers processing */ - to_sign = g_array_sized_new (FALSE, FALSE, sizeof (struct rspamd_dkim_sign_chunk), count); + to_sign = + g_array_sized_new (FALSE, + FALSE, + sizeof (struct rspamd_dkim_sign_chunk), + count); p = headers; c = p; hlen = strlen (header_name); @@ -1204,7 +1429,7 @@ rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *hea state = 1; } } - p ++; + p++; break; case 1: /* Skip header state */ @@ -1213,7 +1438,7 @@ rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *hea state = 0; c = p + 1; } - p ++; + p++; break; case 2: /* c contains the beginning of header */ @@ -1233,7 +1458,7 @@ rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *hea state = 0; found = TRUE; } - p ++; + p++; break; } } @@ -1241,16 +1466,25 @@ rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *hea if (found) { if (!is_sign) { - for (i = to_sign->len - 1; i >= 0 && count > 0; i --, count --) { - elt = &g_array_index (to_sign, struct rspamd_dkim_sign_chunk, i); + for (i = to_sign->len - 1; i >= 0 && count > 0; i--, count--) { + elt = + &g_array_index (to_sign, struct rspamd_dkim_sign_chunk, i); if (!chunk.append_crlf) { - msg_debug ("update signature with header: %*s", elt->len, elt->begin); - rspamd_dkim_hash_update (ctx->headers_hash, elt->begin, elt->len); + msg_debug ("update signature with header: %*s", + elt->len, + elt->begin); + rspamd_dkim_hash_update (ctx->headers_hash, + elt->begin, + elt->len); } else { - msg_debug ("update signature with header: %*s", elt->len + 1, elt->begin); - rspamd_dkim_hash_update (ctx->headers_hash, elt->begin, elt->len + 1); + msg_debug ("update signature with header: %*s", + elt->len + 1, + elt->begin); + rspamd_dkim_hash_update (ctx->headers_hash, + elt->begin, + elt->len + 1); } } } @@ -1271,15 +1505,22 @@ rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *hea } static gboolean -rspamd_dkim_canonize_header (rspamd_dkim_context_t *ctx, struct rspamd_task *task, const gchar *header_name, - guint count, gboolean is_sig) +rspamd_dkim_canonize_header (rspamd_dkim_context_t *ctx, + struct rspamd_task *task, + const gchar *header_name, + guint count, + gboolean is_sig) { - struct raw_header *rh, *rh_iter; - guint rh_num = 0; - GList *nh = NULL, *cur; + struct raw_header *rh, *rh_iter; + guint rh_num = 0; + GList *nh = NULL, *cur; if (ctx->header_canon_type == DKIM_CANON_SIMPLE) { - return rspamd_dkim_canonize_header_simple (ctx, task->raw_headers_str, header_name, count, is_sig); + return rspamd_dkim_canonize_header_simple (ctx, + task->raw_headers_str, + header_name, + count, + is_sig); } else { rh = g_hash_table_lookup (task->raw_headers, header_name); @@ -1287,7 +1528,7 @@ rspamd_dkim_canonize_header (rspamd_dkim_context_t *ctx, struct rspamd_task *tas if (!is_sig) { rh_iter = rh; while (rh_iter) { - rh_num ++; + rh_num++; rh_iter = rh_iter->next; } @@ -1301,7 +1542,7 @@ rspamd_dkim_canonize_header (rspamd_dkim_context_t *ctx, struct rspamd_task *tas rh_iter = rh; while (rh_num) { rh_iter = rh_iter->next; - rh_num --; + rh_num--; } /* Now insert required headers */ while (rh_iter) { @@ -1311,7 +1552,8 @@ rspamd_dkim_canonize_header (rspamd_dkim_context_t *ctx, struct rspamd_task *tas cur = nh; while (cur) { rh = cur->data; - if (! rspamd_dkim_canonize_header_relaxed (ctx, rh->value, header_name, is_sig)) { + if (!rspamd_dkim_canonize_header_relaxed (ctx, rh->value, + header_name, is_sig)) { g_list_free (nh); return FALSE; } @@ -1323,7 +1565,10 @@ rspamd_dkim_canonize_header (rspamd_dkim_context_t *ctx, struct rspamd_task *tas } else { /* For signature check just use the first dkim header */ - rspamd_dkim_canonize_header_relaxed (ctx, rh->value, header_name, is_sig); + rspamd_dkim_canonize_header_relaxed (ctx, + rh->value, + header_name, + is_sig); } return TRUE; } @@ -1341,21 +1586,23 @@ rspamd_dkim_canonize_header (rspamd_dkim_context_t *ctx, struct rspamd_task *tas * @return */ gint -rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct rspamd_task *task) +rspamd_dkim_check (rspamd_dkim_context_t *ctx, + rspamd_dkim_key_t *key, + struct rspamd_task *task) { - const gchar *p, *headers_end = NULL, *end, *body_end; - gboolean got_cr = FALSE, got_crlf = FALSE, got_lf = FALSE; - gchar *digest; - gsize dlen; - gint res = DKIM_CONTINUE; - guint i; - struct rspamd_dkim_header *dh; + const gchar *p, *headers_end = NULL, *end, *body_end; + gboolean got_cr = FALSE, got_crlf = FALSE, got_lf = FALSE; + gchar *digest; + gsize dlen; + gint res = DKIM_CONTINUE; + guint i; + struct rspamd_dkim_header *dh; #ifdef HAVE_OPENSSL - gint nid; + gint nid; #endif - g_return_val_if_fail (ctx != NULL, DKIM_ERROR); - g_return_val_if_fail (key != NULL, DKIM_ERROR); + g_return_val_if_fail (ctx != NULL, DKIM_ERROR); + g_return_val_if_fail (key != NULL, DKIM_ERROR); g_return_val_if_fail (task->msg != NULL, DKIM_ERROR); /* First of all find place of body */ @@ -1422,7 +1669,7 @@ rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct rs got_cr = FALSE; got_crlf = FALSE; } - p ++; + p++; } /* Start canonization of body part */ @@ -1442,7 +1689,7 @@ rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct rs return DKIM_RECORD_ERROR; } /* Now canonize headers */ - for (i = 0; i < ctx->hlist->len; i ++) { + for (i = 0; i < ctx->hlist->len; i++) { dh = g_ptr_array_index (ctx->hlist, i); rspamd_dkim_canonize_header (ctx, task, dh->name, dh->count, FALSE); } diff --git a/src/libserver/dkim.h b/src/libserver/dkim.h index 29ec479b7..8305e2e4a 100644 --- a/src/libserver/dkim.h +++ b/src/libserver/dkim.h @@ -35,100 +35,100 @@ /* Main types and definitions */ -#define DKIM_SIGNHEADER "DKIM-Signature" - /* DKIM signature header */ +#define DKIM_SIGNHEADER "DKIM-Signature" +/* DKIM signature header */ /* special DNS tokens */ -#define DKIM_DNSKEYNAME "_domainkey" - /* reserved DNS sub-zone */ -#define DKIM_DNSPOLICYNAME "_adsp" /* reserved DNS sub-zone */ +#define DKIM_DNSKEYNAME "_domainkey" +/* reserved DNS sub-zone */ +#define DKIM_DNSPOLICYNAME "_adsp" /* reserved DNS sub-zone */ /* Canonization methods */ -#define DKIM_CANON_UNKNOWN (-1) /* unknown method */ -#define DKIM_CANON_SIMPLE 0 /* as specified in DKIM spec */ -#define DKIM_CANON_RELAXED 1 /* as specified in DKIM spec */ +#define DKIM_CANON_UNKNOWN (-1) /* unknown method */ +#define DKIM_CANON_SIMPLE 0 /* as specified in DKIM spec */ +#define DKIM_CANON_RELAXED 1 /* as specified in DKIM spec */ -#define DKIM_CANON_DEFAULT DKIM_CANON_SIMPLE +#define DKIM_CANON_DEFAULT DKIM_CANON_SIMPLE /* Signature methods */ -#define DKIM_SIGN_UNKNOWN (-2) /* unknown method */ -#define DKIM_SIGN_DEFAULT (-1) /* use internal default */ -#define DKIM_SIGN_RSASHA1 0 /* an RSA-signed SHA1 digest */ -#define DKIM_SIGN_RSASHA256 1 /* an RSA-signed SHA256 digest */ +#define DKIM_SIGN_UNKNOWN (-2) /* unknown method */ +#define DKIM_SIGN_DEFAULT (-1) /* use internal default */ +#define DKIM_SIGN_RSASHA1 0 /* an RSA-signed SHA1 digest */ +#define DKIM_SIGN_RSASHA256 1 /* an RSA-signed SHA256 digest */ /* Params */ -#define DKIM_PARAM_UNKNOWN (-1) /* unknown */ -#define DKIM_PARAM_SIGNATURE 0 /* b */ -#define DKIM_PARAM_SIGNALG 1 /* a */ -#define DKIM_PARAM_DOMAIN 2 /* d */ -#define DKIM_PARAM_CANONALG 3 /* c */ -#define DKIM_PARAM_QUERYMETHOD 4 /* q */ -#define DKIM_PARAM_SELECTOR 5 /* s */ -#define DKIM_PARAM_HDRLIST 6 /* h */ -#define DKIM_PARAM_VERSION 7 /* v */ -#define DKIM_PARAM_IDENTITY 8 /* i */ -#define DKIM_PARAM_TIMESTAMP 9 /* t */ -#define DKIM_PARAM_EXPIRATION 10 /* x */ -#define DKIM_PARAM_COPIEDHDRS 11 /* z */ -#define DKIM_PARAM_BODYHASH 12 /* bh */ -#define DKIM_PARAM_BODYLENGTH 13 /* l */ +#define DKIM_PARAM_UNKNOWN (-1) /* unknown */ +#define DKIM_PARAM_SIGNATURE 0 /* b */ +#define DKIM_PARAM_SIGNALG 1 /* a */ +#define DKIM_PARAM_DOMAIN 2 /* d */ +#define DKIM_PARAM_CANONALG 3 /* c */ +#define DKIM_PARAM_QUERYMETHOD 4 /* q */ +#define DKIM_PARAM_SELECTOR 5 /* s */ +#define DKIM_PARAM_HDRLIST 6 /* h */ +#define DKIM_PARAM_VERSION 7 /* v */ +#define DKIM_PARAM_IDENTITY 8 /* i */ +#define DKIM_PARAM_TIMESTAMP 9 /* t */ +#define DKIM_PARAM_EXPIRATION 10 /* x */ +#define DKIM_PARAM_COPIEDHDRS 11 /* z */ +#define DKIM_PARAM_BODYHASH 12 /* bh */ +#define DKIM_PARAM_BODYLENGTH 13 /* l */ /* Errors (from OpenDKIM) */ -#define DKIM_SIGERROR_UNKNOWN (-1) /* unknown error */ -#define DKIM_SIGERROR_OK 0 /* no error */ -#define DKIM_SIGERROR_VERSION 1 /* unsupported version */ -#define DKIM_SIGERROR_DOMAIN 2 /* invalid domain (d=/i=) */ -#define DKIM_SIGERROR_EXPIRED 3 /* signature expired */ -#define DKIM_SIGERROR_FUTURE 4 /* signature in the future */ -#define DKIM_SIGERROR_TIMESTAMPS 5 /* x= < t= */ -#define DKIM_SIGERROR_UNUSED 6 /* OBSOLETE */ -#define DKIM_SIGERROR_INVALID_HC 7 /* c= invalid (header) */ -#define DKIM_SIGERROR_INVALID_BC 8 /* c= invalid (body) */ -#define DKIM_SIGERROR_MISSING_A 9 /* a= missing */ -#define DKIM_SIGERROR_INVALID_A 10 /* a= invalid */ -#define DKIM_SIGERROR_MISSING_H 11 /* h= missing */ -#define DKIM_SIGERROR_INVALID_L 12 /* l= invalid */ -#define DKIM_SIGERROR_INVALID_Q 13 /* q= invalid */ -#define DKIM_SIGERROR_INVALID_QO 14 /* q= option invalid */ -#define DKIM_SIGERROR_MISSING_D 15 /* d= missing */ -#define DKIM_SIGERROR_EMPTY_D 16 /* d= empty */ -#define DKIM_SIGERROR_MISSING_S 17 /* s= missing */ -#define DKIM_SIGERROR_EMPTY_S 18 /* s= empty */ -#define DKIM_SIGERROR_MISSING_B 19 /* b= missing */ -#define DKIM_SIGERROR_EMPTY_B 20 /* b= empty */ -#define DKIM_SIGERROR_CORRUPT_B 21 /* b= corrupt */ -#define DKIM_SIGERROR_NOKEY 22 /* no key found in DNS */ -#define DKIM_SIGERROR_DNSSYNTAX 23 /* DNS reply corrupt */ -#define DKIM_SIGERROR_KEYFAIL 24 /* DNS query failed */ -#define DKIM_SIGERROR_MISSING_BH 25 /* bh= missing */ -#define DKIM_SIGERROR_EMPTY_BH 26 /* bh= empty */ -#define DKIM_SIGERROR_CORRUPT_BH 27 /* bh= corrupt */ -#define DKIM_SIGERROR_BADSIG 28 /* signature mismatch */ -#define DKIM_SIGERROR_SUBDOMAIN 29 /* unauthorized subdomain */ -#define DKIM_SIGERROR_MULTIREPLY 30 /* multiple records returned */ -#define DKIM_SIGERROR_EMPTY_H 31 /* h= empty */ -#define DKIM_SIGERROR_INVALID_H 32 /* h= missing req'd entries */ -#define DKIM_SIGERROR_TOOLARGE_L 33 /* l= value exceeds body size */ -#define DKIM_SIGERROR_MBSFAILED 34 /* "must be signed" failure */ -#define DKIM_SIGERROR_KEYVERSION 35 /* unknown key version */ -#define DKIM_SIGERROR_KEYUNKNOWNHASH 36 /* unknown key hash */ -#define DKIM_SIGERROR_KEYHASHMISMATCH 37 /* sig-key hash mismatch */ -#define DKIM_SIGERROR_NOTEMAILKEY 38 /* not an e-mail key */ -#define DKIM_SIGERROR_UNUSED2 39 /* OBSOLETE */ -#define DKIM_SIGERROR_KEYTYPEMISSING 40 /* key type missing */ -#define DKIM_SIGERROR_KEYTYPEUNKNOWN 41 /* key type unknown */ -#define DKIM_SIGERROR_KEYREVOKED 42 /* key revoked */ -#define DKIM_SIGERROR_KEYDECODE 43 /* key couldn't be decoded */ -#define DKIM_SIGERROR_MISSING_V 44 /* v= tag missing */ -#define DKIM_SIGERROR_EMPTY_V 45 /* v= tag empty */ +#define DKIM_SIGERROR_UNKNOWN (-1) /* unknown error */ +#define DKIM_SIGERROR_OK 0 /* no error */ +#define DKIM_SIGERROR_VERSION 1 /* unsupported version */ +#define DKIM_SIGERROR_DOMAIN 2 /* invalid domain (d=/i=) */ +#define DKIM_SIGERROR_EXPIRED 3 /* signature expired */ +#define DKIM_SIGERROR_FUTURE 4 /* signature in the future */ +#define DKIM_SIGERROR_TIMESTAMPS 5 /* x= < t= */ +#define DKIM_SIGERROR_UNUSED 6 /* OBSOLETE */ +#define DKIM_SIGERROR_INVALID_HC 7 /* c= invalid (header) */ +#define DKIM_SIGERROR_INVALID_BC 8 /* c= invalid (body) */ +#define DKIM_SIGERROR_MISSING_A 9 /* a= missing */ +#define DKIM_SIGERROR_INVALID_A 10 /* a= invalid */ +#define DKIM_SIGERROR_MISSING_H 11 /* h= missing */ +#define DKIM_SIGERROR_INVALID_L 12 /* l= invalid */ +#define DKIM_SIGERROR_INVALID_Q 13 /* q= invalid */ +#define DKIM_SIGERROR_INVALID_QO 14 /* q= option invalid */ +#define DKIM_SIGERROR_MISSING_D 15 /* d= missing */ +#define DKIM_SIGERROR_EMPTY_D 16 /* d= empty */ +#define DKIM_SIGERROR_MISSING_S 17 /* s= missing */ +#define DKIM_SIGERROR_EMPTY_S 18 /* s= empty */ +#define DKIM_SIGERROR_MISSING_B 19 /* b= missing */ +#define DKIM_SIGERROR_EMPTY_B 20 /* b= empty */ +#define DKIM_SIGERROR_CORRUPT_B 21 /* b= corrupt */ +#define DKIM_SIGERROR_NOKEY 22 /* no key found in DNS */ +#define DKIM_SIGERROR_DNSSYNTAX 23 /* DNS reply corrupt */ +#define DKIM_SIGERROR_KEYFAIL 24 /* DNS query failed */ +#define DKIM_SIGERROR_MISSING_BH 25 /* bh= missing */ +#define DKIM_SIGERROR_EMPTY_BH 26 /* bh= empty */ +#define DKIM_SIGERROR_CORRUPT_BH 27 /* bh= corrupt */ +#define DKIM_SIGERROR_BADSIG 28 /* signature mismatch */ +#define DKIM_SIGERROR_SUBDOMAIN 29 /* unauthorized subdomain */ +#define DKIM_SIGERROR_MULTIREPLY 30 /* multiple records returned */ +#define DKIM_SIGERROR_EMPTY_H 31 /* h= empty */ +#define DKIM_SIGERROR_INVALID_H 32 /* h= missing req'd entries */ +#define DKIM_SIGERROR_TOOLARGE_L 33 /* l= value exceeds body size */ +#define DKIM_SIGERROR_MBSFAILED 34 /* "must be signed" failure */ +#define DKIM_SIGERROR_KEYVERSION 35 /* unknown key version */ +#define DKIM_SIGERROR_KEYUNKNOWNHASH 36 /* unknown key hash */ +#define DKIM_SIGERROR_KEYHASHMISMATCH 37 /* sig-key hash mismatch */ +#define DKIM_SIGERROR_NOTEMAILKEY 38 /* not an e-mail key */ +#define DKIM_SIGERROR_UNUSED2 39 /* OBSOLETE */ +#define DKIM_SIGERROR_KEYTYPEMISSING 40 /* key type missing */ +#define DKIM_SIGERROR_KEYTYPEUNKNOWN 41 /* key type unknown */ +#define DKIM_SIGERROR_KEYREVOKED 42 /* key revoked */ +#define DKIM_SIGERROR_KEYDECODE 43 /* key couldn't be decoded */ +#define DKIM_SIGERROR_MISSING_V 44 /* v= tag missing */ +#define DKIM_SIGERROR_EMPTY_V 45 /* v= tag empty */ /* Check results */ -#define DKIM_CONTINUE 0 /* continue */ -#define DKIM_REJECT 1 /* reject */ -#define DKIM_TRYAGAIN 2 /* try again later */ -#define DKIM_NOTFOUND 3 /* requested record not found */ -#define DKIM_RECORD_ERROR 4 /* error requesting record */ +#define DKIM_CONTINUE 0 /* continue */ +#define DKIM_REJECT 1 /* reject */ +#define DKIM_TRYAGAIN 2 /* try again later */ +#define DKIM_NOTFOUND 3 /* requested record not found */ +#define DKIM_RECORD_ERROR 4 /* error requesting record */ typedef struct rspamd_dkim_context_s { rspamd_mempool_t *pool; @@ -167,7 +167,8 @@ rspamd_dkim_key_t; struct rspamd_task; /* Err MUST be freed if it is not NULL, key is allocated by slice allocator */ -typedef void (*dkim_key_handler_f)(rspamd_dkim_key_t *key, gsize keylen, rspamd_dkim_context_t *ctx, gpointer ud, GError *err); +typedef void (*dkim_key_handler_f)(rspamd_dkim_key_t *key, gsize keylen, + rspamd_dkim_context_t *ctx, gpointer ud, GError *err); /** * Create new dkim context from signature @@ -177,7 +178,10 @@ typedef void (*dkim_key_handler_f)(rspamd_dkim_key_t *key, gsize keylen, rspamd_ * @param err pointer to error object * @return new context or NULL */ -rspamd_dkim_context_t* rspamd_create_dkim_context (const gchar *sig, rspamd_mempool_t *pool, guint time_jitter, GError **err); +rspamd_dkim_context_t * rspamd_create_dkim_context (const gchar *sig, + rspamd_mempool_t *pool, + guint time_jitter, + GError **err); /** * Make DNS request for specified context and obtain and parse key @@ -186,8 +190,11 @@ rspamd_dkim_context_t* rspamd_create_dkim_context (const gchar *sig, rspamd_memp * @param s async session to make request * @return */ -gboolean rspamd_get_dkim_key (rspamd_dkim_context_t *ctx, struct rspamd_dns_resolver *resolver, - struct rspamd_async_session *s, dkim_key_handler_f handler, gpointer ud); +gboolean rspamd_get_dkim_key (rspamd_dkim_context_t *ctx, + struct rspamd_dns_resolver *resolver, + struct rspamd_async_session *s, + dkim_key_handler_f handler, + gpointer ud); /** * Check task for dkim context using dkim key @@ -196,7 +203,9 @@ gboolean rspamd_get_dkim_key (rspamd_dkim_context_t *ctx, struct rspamd_dns_reso * @param task task to check * @return */ -gint rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct rspamd_task *task); +gint rspamd_dkim_check (rspamd_dkim_context_t *ctx, + rspamd_dkim_key_t *key, + struct rspamd_task *task); /** * Free DKIM key diff --git a/src/libserver/dns.c b/src/libserver/dns.c index c1303e3ea..41426f741 100644 --- a/src/libserver/dns.c +++ b/src/libserver/dns.c @@ -48,7 +48,7 @@ static void rspamd_dns_fin_cb (gpointer arg) { struct rdns_request *req = arg; - + rdns_request_release (req); } @@ -67,25 +67,33 @@ rspamd_dns_callback (struct rdns_reply *reply, gpointer ud) remove_normal_event (reqdata->session, rspamd_dns_fin_cb, reqdata->req); } -gboolean +gboolean make_dns_request (struct rspamd_dns_resolver *resolver, - struct rspamd_async_session *session, rspamd_mempool_t *pool, dns_callback_type cb, - gpointer ud, enum rdns_request_type type, const char *name) + struct rspamd_async_session *session, + rspamd_mempool_t *pool, + dns_callback_type cb, + gpointer ud, + enum rdns_request_type type, + const char *name) { struct rdns_request *req; struct rspamd_dns_request_ud *reqdata; - - reqdata = rspamd_mempool_alloc (pool, sizeof (struct rspamd_dns_request_ud)); + + reqdata = + rspamd_mempool_alloc (pool, sizeof (struct rspamd_dns_request_ud)); reqdata->session = session; reqdata->cb = cb; reqdata->ud = ud; req = rdns_make_request_full (resolver->r, rspamd_dns_callback, reqdata, - resolver->request_timeout, resolver->max_retransmits, 1, name, type); + resolver->request_timeout, resolver->max_retransmits, 1, name, + type); if (req != NULL) { - register_async_event (session, (event_finalizer_t)rspamd_dns_fin_cb, req, - g_quark_from_static_string ("dns resolver")); + register_async_event (session, + (event_finalizer_t)rspamd_dns_fin_cb, + req, + g_quark_from_static_string ("dns resolver")); reqdata->req = req; } else { @@ -97,13 +105,15 @@ make_dns_request (struct rspamd_dns_resolver *resolver, struct rspamd_dns_resolver * -dns_resolver_init (rspamd_logger_t *logger, struct event_base *ev_base, struct rspamd_config *cfg) +dns_resolver_init (rspamd_logger_t *logger, + struct event_base *ev_base, + struct rspamd_config *cfg) { - GList *cur; - struct rspamd_dns_resolver *new; - gchar *begin, *p, *err; - gint priority; - + GList *cur; + struct rspamd_dns_resolver *new; + gchar *begin, *p, *err; + gint priority; + new = g_slice_alloc0 (sizeof (struct rspamd_dns_resolver)); new->ev_base = ev_base; new->request_timeout = cfg->dns_timeout; @@ -112,12 +122,15 @@ dns_resolver_init (rspamd_logger_t *logger, struct event_base *ev_base, struct r new->r = rdns_resolver_new (); rdns_bind_libevent (new->r, new->ev_base); rdns_resolver_set_log_level (new->r, cfg->log_level); - rdns_resolver_set_logger (new->r, (rdns_log_function)rspamd_common_logv, logger); + rdns_resolver_set_logger (new->r, + (rdns_log_function)rspamd_common_logv, + logger); if (cfg->nameservers == NULL) { /* Parse resolv.conf */ if (!rdns_resolver_parse_resolv_conf (new->r, "/etc/resolv.conf")) { - msg_err ("cannot parse resolv.conf and no nameservers defined, so no ways to resolve addresses"); + msg_err ( + "cannot parse resolv.conf and no nameservers defined, so no ways to resolve addresses"); return new; } } @@ -128,16 +141,19 @@ dns_resolver_init (rspamd_logger_t *logger, struct event_base *ev_base, struct r p = strchr (begin, ':'); if (p != NULL) { *p = '\0'; - p ++; + p++; priority = strtoul (p, &err, 10); if (err != NULL && *err != '\0') { - msg_info ("bad character '%x', must be 'm' or 's' or a numeric priority", *err); + msg_info ( + "bad character '%x', must be 'm' or 's' or a numeric priority", + *err); } } else { priority = 0; } - if (!rdns_resolver_add_server (new->r, begin, 53, priority, cfg->dns_io_per_server)) { + if (!rdns_resolver_add_server (new->r, begin, 53, priority, + cfg->dns_io_per_server)) { msg_warn ("cannot parse ip address of nameserver: %s", begin); cur = g_list_next (cur); continue; diff --git a/src/libserver/dns.h b/src/libserver/dns.h index 7b3bbd208..4882f539d 100644 --- a/src/libserver/dns.h +++ b/src/libserver/dns.h @@ -39,8 +39,8 @@ struct rspamd_dns_resolver; /** * Init DNS resolver, params are obtained from a config file or system file /etc/resolv.conf */ -struct rspamd_dns_resolver *dns_resolver_init (rspamd_logger_t *logger, - struct event_base *ev_base, struct rspamd_config *cfg); +struct rspamd_dns_resolver * dns_resolver_init (rspamd_logger_t *logger, + struct event_base *ev_base, struct rspamd_config *cfg); /** * Make a DNS request @@ -53,8 +53,12 @@ struct rspamd_dns_resolver *dns_resolver_init (rspamd_logger_t *logger, * @param ... string or ip address based on a request type * @return TRUE if request was sent. */ -gboolean make_dns_request (struct rspamd_dns_resolver *resolver, - struct rspamd_async_session *session, rspamd_mempool_t *pool, - dns_callback_type cb, gpointer ud, enum rdns_request_type type, const char *name); +gboolean make_dns_request (struct rspamd_dns_resolver *resolver, + struct rspamd_async_session *session, + rspamd_mempool_t *pool, + dns_callback_type cb, + gpointer ud, + enum rdns_request_type type, + const char *name); #endif diff --git a/src/libserver/dynamic_cfg.c b/src/libserver/dynamic_cfg.c index d0dabef67..0e513ddd8 100644 --- a/src/libserver/dynamic_cfg.c +++ b/src/libserver/dynamic_cfg.c @@ -29,27 +29,27 @@ #include "json/jansson.h" struct dynamic_cfg_symbol { - gchar *name; - gdouble value; + gchar *name; + gdouble value; }; struct dynamic_cfg_action { - enum rspamd_metric_action action; - gdouble value; + enum rspamd_metric_action action; + gdouble value; }; struct dynamic_cfg_metric { - GList *symbols; - struct dynamic_cfg_action actions[METRIC_ACTION_MAX]; - gchar *name; + GList *symbols; + struct dynamic_cfg_action actions[METRIC_ACTION_MAX]; + gchar *name; }; struct config_json_buf { - gchar *buf; - gchar *pos; - size_t buflen; - struct rspamd_config *cfg; - GList *config_metrics; + gchar *buf; + gchar *pos; + size_t buflen; + struct rspamd_config *cfg; + GList *config_metrics; }; /** @@ -59,9 +59,9 @@ struct config_json_buf { static void dynamic_cfg_free (GList *conf_metrics) { - GList *cur, *cur_elt; - struct dynamic_cfg_metric *metric; - struct dynamic_cfg_symbol *sym; + GList *cur, *cur_elt; + struct dynamic_cfg_metric *metric; + struct dynamic_cfg_symbol *sym; if (conf_metrics) { cur = conf_metrics; @@ -91,44 +91,50 @@ dynamic_cfg_free (GList *conf_metrics) static void apply_dynamic_conf (GList *conf_metrics, struct rspamd_config *cfg) { - GList *cur, *cur_elt; - struct dynamic_cfg_metric *metric; - struct dynamic_cfg_symbol *sym; - struct dynamic_cfg_action *act; - struct metric *real_metric; - struct metric_action *real_act; - gdouble *w; - gint i, j; + GList *cur, *cur_elt; + struct dynamic_cfg_metric *metric; + struct dynamic_cfg_symbol *sym; + struct dynamic_cfg_action *act; + struct metric *real_metric; + struct metric_action *real_act; + gdouble *w; + gint i, j; cur = conf_metrics; while (cur) { metric = cur->data; - if ((real_metric = g_hash_table_lookup (cfg->metrics, metric->name)) != NULL) { + if ((real_metric = + g_hash_table_lookup (cfg->metrics, metric->name)) != NULL) { cur_elt = metric->symbols; while (cur_elt) { sym = cur_elt->data; - if ((w = g_hash_table_lookup (real_metric->symbols, sym->name)) != NULL) { + if ((w = + g_hash_table_lookup (real_metric->symbols, + sym->name)) != NULL) { *w = sym->value; } else { - msg_info ("symbol %s is not found in the main configuration", sym->name); + msg_info ( + "symbol %s is not found in the main configuration", + sym->name); } cur_elt = g_list_next (cur_elt); } - for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { + for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) { act = &metric->actions[i]; if (act->value < 0) { continue; } - for (j = METRIC_ACTION_REJECT; j < METRIC_ACTION_MAX; j ++) { + for (j = METRIC_ACTION_REJECT; j < METRIC_ACTION_MAX; j++) { real_act = &real_metric->actions[j]; if (real_act->action == act->action) { real_act->score = act->value; } /* Update required score accordingly to metric's action */ if (act->action == METRIC_ACTION_REJECT) { - real_metric->actions[METRIC_ACTION_REJECT].score = act->value; + real_metric->actions[METRIC_ACTION_REJECT].score = + act->value; } } } @@ -138,11 +144,14 @@ apply_dynamic_conf (GList *conf_metrics, struct rspamd_config *cfg) } /* Callbacks for reading json dynamic rules */ -gchar * -json_config_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +gchar * +json_config_read_cb (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { - struct config_json_buf *jb; - gint free, off; + struct config_json_buf *jb; + gint free, off; if (data->cur_data == NULL) { jb = g_malloc (sizeof (struct config_json_buf)); @@ -182,14 +191,14 @@ json_config_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct ma void json_config_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) { - struct config_json_buf *jb; - guint nelts, i, j, selts; - gint test_act; - json_t *js, *cur_elt, *cur_nm, *it_val; - json_error_t je; - struct dynamic_cfg_metric *cur_metric; - struct dynamic_cfg_symbol *cur_symbol; - struct dynamic_cfg_action *cur_action; + struct config_json_buf *jb; + guint nelts, i, j, selts; + gint test_act; + json_t *js, *cur_elt, *cur_nm, *it_val; + json_error_t je; + struct dynamic_cfg_metric *cur_metric; + struct dynamic_cfg_symbol *cur_symbol; + struct dynamic_cfg_action *cur_action; if (data->prev_data) { jb = data->prev_data; @@ -217,7 +226,9 @@ json_config_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) js = json_loads (jb->buf, &je); if (!js) { - msg_err ("cannot load json data: parse error %s, on line %d", je.text, je.line); + msg_err ("cannot load json data: parse error %s, on line %d", + je.text, + je.line); return; } @@ -242,11 +253,12 @@ json_config_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) cur_nm = json_object_get (cur_elt, "metric"); if (!cur_nm || !json_is_string (cur_nm)) { - msg_err ("loaded json metric object element has no 'metric' attribute"); + msg_err ( + "loaded json metric object element has no 'metric' attribute"); continue; } cur_metric = g_slice_alloc0 (sizeof (struct dynamic_cfg_metric)); - for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { + for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) { cur_metric->actions[i].value = -1.0; } cur_metric->name = g_strdup (json_string_value (cur_nm)); @@ -254,18 +266,27 @@ json_config_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) /* Parse symbols */ if (cur_nm && json_is_array (cur_nm)) { selts = json_array_size (cur_nm); - for (j = 0; j < selts; j ++) { + for (j = 0; j < selts; j++) { it_val = json_array_get (cur_nm, j); if (it_val && json_is_object (it_val)) { - if (json_object_get (it_val, "name") && json_object_get (it_val, "value")) { - cur_symbol = g_slice_alloc0 (sizeof (struct dynamic_cfg_symbol)); - cur_symbol->name = g_strdup (json_string_value (json_object_get (it_val, "name"))); - cur_symbol->value = json_number_value (json_object_get (it_val, "value")); + if (json_object_get (it_val, + "name") && json_object_get (it_val, "value")) { + cur_symbol = + g_slice_alloc0 (sizeof (struct dynamic_cfg_symbol)); + cur_symbol->name = + g_strdup (json_string_value (json_object_get (it_val, + "name"))); + cur_symbol->value = + json_number_value (json_object_get (it_val, + "value")); /* Insert symbol */ - cur_metric->symbols = g_list_prepend (cur_metric->symbols, cur_symbol); + cur_metric->symbols = g_list_prepend ( + cur_metric->symbols, + cur_symbol); } else { - msg_info ("json symbol object has no mandatory 'name' and 'value' attributes"); + msg_info ( + "json symbol object has no mandatory 'name' and 'value' attributes"); } } } @@ -274,21 +295,29 @@ json_config_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) /* Parse actions */ if (cur_nm && json_is_array (cur_nm)) { selts = json_array_size (cur_nm); - for (j = 0; j < selts; j ++) { + for (j = 0; j < selts; j++) { it_val = json_array_get (cur_nm, j); if (it_val && json_is_object (it_val)) { - if (json_object_get (it_val, "name") && json_object_get (it_val, "value")) { - if (!check_action_str (json_string_value (json_object_get (it_val, "name")), &test_act)) { - msg_err ("unknown action: %s", json_string_value (json_object_get (it_val, "name"))); - g_slice_free1 (sizeof (struct dynamic_cfg_action), cur_action); + if (json_object_get (it_val, + "name") && json_object_get (it_val, "value")) { + if (!check_action_str (json_string_value ( + json_object_get (it_val, "name")), &test_act)) { + msg_err ("unknown action: %s", + json_string_value (json_object_get (it_val, + "name"))); + g_slice_free1 (sizeof (struct dynamic_cfg_action), + cur_action); continue; } cur_action = &cur_metric->actions[test_act]; cur_action->action = test_act; - cur_action->value = json_number_value (json_object_get (it_val, "value")); + cur_action->value = + json_number_value (json_object_get (it_val, + "value")); } else { - msg_info ("json symbol object has no mandatory 'name' and 'value' attributes"); + msg_info ( + "json symbol object has no mandatory 'name' and 'value' attributes"); } } } @@ -314,7 +343,7 @@ json_config_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) void init_dynamic_config (struct rspamd_config *cfg) { - struct config_json_buf *jb, **pjb; + struct config_json_buf *jb, **pjb; if (cfg->dynamic_conf == NULL) { /* No dynamic conf has been specified, so do not try to load it */ @@ -327,7 +356,8 @@ init_dynamic_config (struct rspamd_config *cfg) jb->buf = NULL; jb->cfg = cfg; *pjb = jb; - if (!add_map (cfg, cfg->dynamic_conf, "Dynamic configuration map", json_config_read_cb, json_config_fin_cb, (void **)pjb)) { + if (!add_map (cfg, cfg->dynamic_conf, "Dynamic configuration map", + json_config_read_cb, json_config_fin_cb, (void **)pjb)) { msg_err ("cannot add map for configuration %s", cfg->dynamic_conf); } } @@ -335,13 +365,13 @@ init_dynamic_config (struct rspamd_config *cfg) static gboolean dump_dynamic_list (gint fd, GList *rules) { - GList *cur, *cur_elt; - struct dynamic_cfg_metric *metric; - struct dynamic_cfg_symbol *sym; - struct dynamic_cfg_action *act; - FILE *f; - gint i; - gboolean start = TRUE; + GList *cur, *cur_elt; + struct dynamic_cfg_metric *metric; + struct dynamic_cfg_symbol *sym; + struct dynamic_cfg_action *act; + FILE *f; + gint i; + gboolean start = TRUE; /* Open buffered stream for the descriptor */ if ((f = fdopen (fd, "a+")) == NULL) { @@ -363,10 +393,16 @@ dump_dynamic_list (gint fd, GList *rules) sym = cur_elt->data; cur_elt = g_list_next (cur_elt); if (cur_elt) { - fprintf (f, " {\"name\": \"%s\",\"value\": %.2f},\n", sym->name, sym->value); + fprintf (f, + " {\"name\": \"%s\",\"value\": %.2f},\n", + sym->name, + sym->value); } else { - fprintf (f, " {\"name\": \"%s\",\"value\": %.2f}\n", sym->name, sym->value); + fprintf (f, + " {\"name\": \"%s\",\"value\": %.2f}\n", + sym->name, + sym->value); } } if (metric->actions) { @@ -379,13 +415,14 @@ dump_dynamic_list (gint fd, GList *rules) if (metric->actions) { fprintf (f, " \"actions\": [\n"); - for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { + for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) { act = &metric->actions[i]; if (act->value < 0) { continue; } fprintf (f, " %s{\"name\": \"%s\",\"value\": %.2f}\n", - (start ? "" : ","), str_action_metric (act->action), act->value); + (start ? "" : ","), str_action_metric ( + act->action), act->value); if (start) { start = FALSE; } @@ -414,9 +451,9 @@ dump_dynamic_list (gint fd, GList *rules) gboolean dump_dynamic_config (struct rspamd_config *cfg) { - struct stat st; - gchar *dir, pathbuf[PATH_MAX]; - gint fd; + struct stat st; + gchar *dir, pathbuf[PATH_MAX]; + gint fd; if (cfg->dynamic_conf == NULL || cfg->current_dynamic_conf == NULL) { /* No dynamic conf has been specified, so do not try to dump it */ @@ -434,15 +471,20 @@ dump_dynamic_config (struct rspamd_config *cfg) } if (stat (cfg->dynamic_conf, &st) == -1) { - msg_debug ("%s is unavailable: %s", cfg->dynamic_conf, strerror (errno)); - st.st_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; + msg_debug ("%s is unavailable: %s", cfg->dynamic_conf, + strerror (errno)); + st.st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; } if (access (dir, W_OK | R_OK) == -1) { msg_warn ("%s is inaccessible: %s", dir, strerror (errno)); g_free (dir); return FALSE; } - rspamd_snprintf (pathbuf, sizeof (pathbuf), "%s%crconf-XXXXXX", dir, G_DIR_SEPARATOR); + rspamd_snprintf (pathbuf, + sizeof (pathbuf), + "%s%crconf-XXXXXX", + dir, + G_DIR_SEPARATOR); g_free (dir); #ifdef HAVE_MKSTEMP /* Umask is set before */ @@ -490,11 +532,14 @@ dump_dynamic_config (struct rspamd_config *cfg) * @return */ gboolean -add_dynamic_symbol (struct rspamd_config *cfg, const gchar *metric_name, const gchar *symbol, gdouble value) +add_dynamic_symbol (struct rspamd_config *cfg, + const gchar *metric_name, + const gchar *symbol, + gdouble value) { - GList *cur; - struct dynamic_cfg_metric *metric = NULL; - struct dynamic_cfg_symbol *sym = NULL; + GList *cur; + struct dynamic_cfg_metric *metric = NULL; + struct dynamic_cfg_symbol *sym = NULL; if (cfg->dynamic_conf == NULL) { msg_info ("dynamic conf is disabled"); @@ -541,7 +586,8 @@ add_dynamic_symbol (struct rspamd_config *cfg, const gchar *metric_name, const g sym->value = value; metric->symbols = g_list_prepend (metric->symbols, sym); metric->name = g_strdup (metric_name); - cfg->current_dynamic_conf = g_list_prepend (cfg->current_dynamic_conf, metric); + cfg->current_dynamic_conf = g_list_prepend (cfg->current_dynamic_conf, + metric); msg_debug ("create metric %s for symbol %s", metric_name, symbol); } @@ -560,10 +606,13 @@ add_dynamic_symbol (struct rspamd_config *cfg, const gchar *metric_name, const g * @return */ gboolean -add_dynamic_action (struct rspamd_config *cfg, const gchar *metric_name, guint action, gdouble value) +add_dynamic_action (struct rspamd_config *cfg, + const gchar *metric_name, + guint action, + gdouble value) { - GList *cur; - struct dynamic_cfg_metric *metric = NULL; + GList *cur; + struct dynamic_cfg_metric *metric = NULL; if (cfg->dynamic_conf == NULL) { msg_info ("dynamic conf is disabled"); @@ -589,7 +638,8 @@ add_dynamic_action (struct rspamd_config *cfg, const gchar *metric_name, guint a metric = g_slice_alloc0 (sizeof (struct dynamic_cfg_metric)); metric->actions[action].value = value; metric->name = g_strdup (metric_name); - cfg->current_dynamic_conf = g_list_prepend (cfg->current_dynamic_conf, metric); + cfg->current_dynamic_conf = g_list_prepend (cfg->current_dynamic_conf, + metric); msg_debug ("create metric %s for action %d", metric_name, action); } diff --git a/src/libserver/dynamic_cfg.h b/src/libserver/dynamic_cfg.h index a8cb02ae5..33c9ba458 100644 --- a/src/libserver/dynamic_cfg.h +++ b/src/libserver/dynamic_cfg.h @@ -49,7 +49,10 @@ gboolean dump_dynamic_config (struct rspamd_config *cfg); * @param value value of symbol * @return */ -gboolean add_dynamic_symbol (struct rspamd_config *cfg, const gchar *metric, const gchar *symbol, gdouble value); +gboolean add_dynamic_symbol (struct rspamd_config *cfg, + const gchar *metric, + const gchar *symbol, + gdouble value); /** @@ -60,7 +63,10 @@ gboolean add_dynamic_symbol (struct rspamd_config *cfg, const gchar *metric, con * @param value value of symbol * @return */ -gboolean add_dynamic_action (struct rspamd_config *cfg, const gchar *metric, guint action, gdouble value); +gboolean add_dynamic_action (struct rspamd_config *cfg, + const gchar *metric, + guint action, + gdouble value); #endif /* DYNAMIC_CFG_H_ */ diff --git a/src/libserver/events.c b/src/libserver/events.c index 48dcb3444..9b8ad078d 100644 --- a/src/libserver/events.c +++ b/src/libserver/events.c @@ -29,7 +29,7 @@ static gboolean rspamd_event_equal (gconstpointer a, gconstpointer b) { - const struct rspamd_async_event *ev1 = a, *ev2 = b; + const struct rspamd_async_event *ev1 = a, *ev2 = b; if (ev1->fin == ev2->fin) { return ev1->user_data == ev2->user_data; @@ -41,7 +41,7 @@ rspamd_event_equal (gconstpointer a, gconstpointer b) static guint rspamd_event_hash (gconstpointer a) { - const struct rspamd_async_event *ev = a; + const struct rspamd_async_event *ev = a; return GPOINTER_TO_UINT (ev->user_data); } @@ -50,7 +50,7 @@ rspamd_event_hash (gconstpointer a) static void event_mutex_free (gpointer data) { - GMutex *mtx = data; + GMutex *mtx = data; g_mutex_free (mtx); } @@ -58,17 +58,17 @@ event_mutex_free (gpointer data) static void event_cond_free (gpointer data) { - GCond *cond = data; + GCond *cond = data; g_cond_free (cond); } #endif -struct rspamd_async_session * +struct rspamd_async_session * new_async_session (rspamd_mempool_t * pool, session_finalizer_t fin, - event_finalizer_t restore, event_finalizer_t cleanup, void *user_data) + event_finalizer_t restore, event_finalizer_t cleanup, void *user_data) { - struct rspamd_async_session *new; + struct rspamd_async_session *new; new = rspamd_mempool_alloc (pool, sizeof (struct rspamd_async_session)); new->pool = pool; @@ -81,27 +81,40 @@ new_async_session (rspamd_mempool_t * pool, session_finalizer_t fin, #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) new->mtx = g_mutex_new (); new->cond = g_cond_new (); - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) event_mutex_free, new->mtx); - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) event_cond_free, new->cond); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) event_mutex_free, + new->mtx); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) event_cond_free, + new->cond); #else new->mtx = rspamd_mempool_alloc (pool, sizeof (GMutex)); g_mutex_init (new->mtx); new->cond = rspamd_mempool_alloc (pool, sizeof (GCond)); g_cond_init (new->cond); - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_mutex_clear, new->mtx); - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_cond_clear, new->cond); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_mutex_clear, + new->mtx); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_cond_clear, + new->cond); #endif new->threads = 0; - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, new->events); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, + new->events); return new; } void -register_async_event (struct rspamd_async_session *session, event_finalizer_t fin, void *user_data, GQuark subsystem) +register_async_event (struct rspamd_async_session *session, + event_finalizer_t fin, + void *user_data, + GQuark subsystem) { - struct rspamd_async_event *new; + struct rspamd_async_event *new; if (session == NULL) { msg_info ("session is NULL"); @@ -109,23 +122,28 @@ register_async_event (struct rspamd_async_session *session, event_finalizer_t fi } g_mutex_lock (session->mtx); - new = rspamd_mempool_alloc (session->pool, sizeof (struct rspamd_async_event)); + new = rspamd_mempool_alloc (session->pool, + sizeof (struct rspamd_async_event)); new->fin = fin; new->user_data = user_data; new->subsystem = subsystem; g_hash_table_insert (session->events, new, new); - msg_debug ("added event: %p, pending %d events, subsystem: %s", user_data, g_hash_table_size (session->events), - g_quark_to_string (subsystem)); + msg_debug ("added event: %p, pending %d events, subsystem: %s", + user_data, + g_hash_table_size (session->events), + g_quark_to_string (subsystem)); g_mutex_unlock (session->mtx); } void -remove_normal_event (struct rspamd_async_session *session, event_finalizer_t fin, void *ud) +remove_normal_event (struct rspamd_async_session *session, + event_finalizer_t fin, + void *ud) { - struct rspamd_async_event search_ev, *found_ev; + struct rspamd_async_event search_ev, *found_ev; if (session == NULL) { msg_info ("session is NULL"); @@ -136,10 +154,12 @@ remove_normal_event (struct rspamd_async_session *session, event_finalizer_t fin /* Search for event */ search_ev.fin = fin; search_ev.user_data = ud; - if ((found_ev = g_hash_table_lookup (session->events, &search_ev)) != NULL) { + if ((found_ev = + g_hash_table_lookup (session->events, &search_ev)) != NULL) { g_hash_table_remove (session->events, found_ev); msg_debug ("removed event: %p, subsystem: %s, pending %d events", ud, - g_quark_to_string (found_ev->subsystem), g_hash_table_size (session->events)); + g_quark_to_string (found_ev->subsystem), + g_hash_table_size (session->events)); /* Remove event */ fin (ud); } @@ -151,11 +171,11 @@ remove_normal_event (struct rspamd_async_session *session, event_finalizer_t fin static gboolean rspamd_session_destroy (gpointer k, gpointer v, gpointer unused) { - struct rspamd_async_event *ev = v; + struct rspamd_async_event *ev = v; /* Call event's finalizer */ msg_debug ("removed event on destroy: %p, subsystem: %s", ev->user_data, - g_quark_to_string (ev->subsystem)); + g_quark_to_string (ev->subsystem)); if (ev->fin != NULL) { ev->fin (ev->user_data); @@ -174,14 +194,16 @@ destroy_session (struct rspamd_async_session *session) g_mutex_lock (session->mtx); if (session->threads > 0) { - /* Wait for conditional variable to finish processing */ + /* Wait for conditional variable to finish processing */ g_mutex_unlock (session->mtx); g_cond_wait (session->cond, session->mtx); } session->wanna_die = TRUE; - g_hash_table_foreach_remove (session->events, rspamd_session_destroy, session); + g_hash_table_foreach_remove (session->events, + rspamd_session_destroy, + session); /* Mutex can be destroyed here */ g_mutex_unlock (session->mtx); @@ -204,7 +226,7 @@ check_session_pending (struct rspamd_async_session *session) } if (session->fin != NULL) { g_mutex_unlock (session->mtx); - if (! session->fin (session->user_data)) { + if (!session->fin (session->user_data)) { /* Session finished incompletely, perform restoration */ if (session->restore != NULL) { session->restore (session->user_data); diff --git a/src/libserver/events.h b/src/libserver/events.h index 6728288eb..166cd7138 100644 --- a/src/libserver/events.h +++ b/src/libserver/events.h @@ -38,9 +38,9 @@ struct rspamd_async_session { * @param user_data abstract user data * @return */ -struct rspamd_async_session *new_async_session (rspamd_mempool_t *pool, - session_finalizer_t fin, event_finalizer_t restore, - event_finalizer_t cleanup, void *user_data); +struct rspamd_async_session * new_async_session (rspamd_mempool_t *pool, + session_finalizer_t fin, event_finalizer_t restore, + event_finalizer_t cleanup, void *user_data); /** * Insert new event to the session @@ -50,7 +50,7 @@ struct rspamd_async_session *new_async_session (rspamd_mempool_t *pool, * @param forced unused */ void register_async_event (struct rspamd_async_session *session, - event_finalizer_t fin, void *user_data, GQuark subsystem); + event_finalizer_t fin, void *user_data, GQuark subsystem); /** * Remove normal event @@ -58,11 +58,13 @@ void register_async_event (struct rspamd_async_session *session, * @param fin final callback * @param ud user data object */ -void remove_normal_event (struct rspamd_async_session *session, event_finalizer_t fin, void *ud); +void remove_normal_event (struct rspamd_async_session *session, + event_finalizer_t fin, + void *ud); /** * Must be called at the end of session, it calls fin functions for all non-forced callbacks - * @return true if the whole session was destroyed and false if there are forced events + * @return true if the whole session was destroyed and false if there are forced events */ gboolean destroy_session (struct rspamd_async_session *session); diff --git a/src/libserver/html.c b/src/libserver/html.c index 028c54f6c..539ff555d 100644 --- a/src/libserver/html.c +++ b/src/libserver/html.c @@ -29,9 +29,9 @@ #include "html.h" #include "url.h" -static sig_atomic_t tags_sorted = 0; +static sig_atomic_t tags_sorted = 0; -static struct html_tag tag_defs[] = { +static struct html_tag tag_defs[] = { /* W3C defined elements */ {Tag_A, "a", (CM_INLINE)}, {Tag_ABBR, "abbr", (CM_INLINE)}, @@ -93,7 +93,8 @@ static struct html_tag tag_defs[] = { {Tag_META, "meta", (CM_HEAD | CM_EMPTY)}, {Tag_NOFRAMES, "noframes", (CM_BLOCK | CM_FRAMES)}, {Tag_NOSCRIPT, "noscript", (CM_BLOCK | CM_INLINE | CM_MIXED)}, - {Tag_OBJECT, "object", (CM_OBJECT | CM_HEAD | CM_IMG | CM_INLINE | CM_PARAM)}, + {Tag_OBJECT, "object", + (CM_OBJECT | CM_HEAD | CM_IMG | CM_INLINE | CM_PARAM)}, {Tag_OL, "ol", (CM_BLOCK)}, {Tag_OPTGROUP, "optgroup", (CM_FIELD | CM_OPT)}, {Tag_OPTION, "option", (CM_FIELD | CM_OPT)}, @@ -156,21 +157,21 @@ static struct html_tag tag_defs[] = { {Tag_WBR, "wbr", (CM_INLINE | CM_EMPTY)}, }; -static sig_atomic_t entities_sorted = 0; +static sig_atomic_t entities_sorted = 0; struct _entity; -typedef struct _entity entity; +typedef struct _entity entity; struct _entity { - gchar *name; - uint code; - gchar *replacement; + gchar *name; + uint code; + gchar *replacement; }; -static entity entities_defs[] = { +static entity entities_defs[] = { /* - ** Markup pre-defined character entities - */ + ** Markup pre-defined character entities + */ {"quot", 34, "\""}, {"amp", 38, "&"}, {"apos", 39, "'"}, @@ -178,8 +179,8 @@ static entity entities_defs[] = { {"gt", 62, ">"}, /* - ** Latin-1 character entities - */ + ** Latin-1 character entities + */ {"nbsp", 160, " "}, {"iexcl", 161, "!"}, {"cent", 162, "cent"}, @@ -278,8 +279,8 @@ static entity entities_defs[] = { {"yuml", 255, "y"}, /* - ** Extended Entities defined in HTML 4: Symbols - */ + ** Extended Entities defined in HTML 4: Symbols + */ {"fnof", 402, "f"}, {"Alpha", 913, "alpha"}, {"Beta", 914, "beta"}, @@ -406,8 +407,8 @@ static entity entities_defs[] = { {"diams", 9830, NULL}, /* - ** Extended Entities defined in HTML 4: Special (less Markup at top) - */ + ** Extended Entities defined in HTML 4: Special (less Markup at top) + */ {"OElig", 338, NULL}, {"oelig", 339, NULL}, {"Scaron", 352, NULL}, @@ -443,8 +444,8 @@ static entity entities_defs_num[ (G_N_ELEMENTS (entities_defs)) ]; static gint tag_cmp (const void *m1, const void *m2) { - const struct html_tag *p1 = m1; - const struct html_tag *p2 = m2; + const struct html_tag *p1 = m1; + const struct html_tag *p2 = m2; return g_ascii_strcasecmp (p1->name, p2->name); } @@ -452,8 +453,8 @@ tag_cmp (const void *m1, const void *m2) static gint entity_cmp (const void *m1, const void *m2) { - const entity *p1 = m1; - const entity *p2 = m2; + const entity *p1 = m1; + const entity *p2 = m2; return g_ascii_strcasecmp (p1->name, p2->name); } @@ -461,19 +462,19 @@ entity_cmp (const void *m1, const void *m2) static gint entity_cmp_num (const void *m1, const void *m2) { - const entity *p1 = m1; - const entity *p2 = m2; + const entity *p1 = m1; + const entity *p2 = m2; return p1->code - p2->code; } -static GNode * +static GNode * construct_html_node (rspamd_mempool_t * pool, gchar *text, gsize tag_len) { - struct html_node *html; - GNode *n = NULL; - struct html_tag key, *found; - gchar t; + struct html_node *html; + GNode *n = NULL; + struct html_tag key, *found; + gchar t; if (text == NULL || *text == '\0') { return NULL; @@ -487,7 +488,8 @@ construct_html_node (rspamd_mempool_t * pool, gchar *text, gsize tag_len) } /* Check xml tag */ - if (*text == '?' && g_ascii_strncasecmp (text + 1, "xml", sizeof ("xml") - 1) == 0) { + if (*text == '?' && + g_ascii_strncasecmp (text + 1, "xml", sizeof ("xml") - 1) == 0) { html->flags |= FL_XML; html->tag = NULL; } @@ -499,13 +501,15 @@ construct_html_node (rspamd_mempool_t * pool, gchar *text, gsize tag_len) /* Find end of tag name */ key.name = text; - while (*text && g_ascii_isalnum (*(++text))); + while (*text && g_ascii_isalnum (*(++text))) ; t = *text; *text = '\0'; /* Match tag id by tag name */ - if ((found = bsearch (&key, tag_defs, G_N_ELEMENTS (tag_defs), sizeof (struct html_tag), tag_cmp)) != NULL) { + if ((found = + bsearch (&key, tag_defs, G_N_ELEMENTS (tag_defs), + sizeof (struct html_tag), tag_cmp)) != NULL) { *text = t; html->tag = found; } @@ -520,18 +524,20 @@ construct_html_node (rspamd_mempool_t * pool, gchar *text, gsize tag_len) return n; } -static gboolean +static gboolean check_balance (GNode * node, GNode ** cur_level) { - struct html_node *arg = node->data, *tmp; - GNode *cur; + struct html_node *arg = node->data, *tmp; + GNode *cur; if (arg->flags & FL_CLOSING) { /* First of all check whether this tag is closing tag for parent node */ cur = node->parent; while (cur && cur->data) { tmp = cur->data; - if ((tmp->tag && arg->tag) && tmp->tag->id == arg->tag->id && (tmp->flags & FL_CLOSED) == 0) { + if ((tmp->tag && + arg->tag) && tmp->tag->id == arg->tag->id && + (tmp->flags & FL_CLOSED) == 0) { tmp->flags |= FL_CLOSED; /* Destroy current node as we find corresponding parent node */ g_node_destroy (node); @@ -549,27 +555,28 @@ check_balance (GNode * node, GNode ** cur_level) return FALSE; } -struct html_tag * +struct html_tag * get_tag_by_name (const gchar *name) { - struct html_tag key; + struct html_tag key; key.name = name; - return bsearch (&key, tag_defs, G_N_ELEMENTS (tag_defs), sizeof (struct html_tag), tag_cmp); + return bsearch (&key, tag_defs, G_N_ELEMENTS (tag_defs), + sizeof (struct html_tag), tag_cmp); } /* Decode HTML entitles in text */ void decode_entitles (gchar *s, guint * len) { - guint l, rep_len; - gchar *t = s; /* t - tortoise */ - gchar *h = s; /* h - hare */ - gchar *e = s; - gchar *end_ptr; - gint state = 0, val, base; - entity *found, key; + guint l, rep_len; + gchar *t = s; /* t - tortoise */ + gchar *h = s; /* h - hare */ + gchar *e = s; + gchar *end_ptr; + gint state = 0, val, base; + entity *found, key; if (len == NULL || *len == 0) { l = strlen (s); @@ -580,7 +587,7 @@ decode_entitles (gchar *s, guint * len) while (h - s < (gint)l) { switch (state) { - /* Out of entitle */ + /* Out of entitle */ case 0: if (*h == '&') { state = 1; @@ -601,7 +608,10 @@ decode_entitles (gchar *s, guint * len) key.name = e + 1; *h = '\0'; - if (*(e + 1) != '#' && (found = bsearch (&key, entities_defs, G_N_ELEMENTS (entities_defs), sizeof (entity), entity_cmp)) != NULL) { + if (*(e + 1) != '#' && + (found = + bsearch (&key, entities_defs, G_N_ELEMENTS (entities_defs), + sizeof (entity), entity_cmp)) != NULL) { if (found->replacement) { rep_len = strlen (found->replacement); memcpy (t, found->replacement, rep_len); @@ -631,7 +641,10 @@ decode_entitles (gchar *s, guint * len) else { /* Search for a replacement */ key.code = val; - found = bsearch (&key, entities_defs_num, G_N_ELEMENTS (entities_defs), sizeof (entity), entity_cmp_num); + found = + bsearch (&key, entities_defs_num, G_N_ELEMENTS ( + entities_defs), sizeof (entity), + entity_cmp_num); if (found) { if (found->replacement) { rep_len = strlen (found->replacement); @@ -656,15 +669,19 @@ decode_entitles (gchar *s, guint * len) } static void -check_phishing (struct rspamd_task *task, struct uri *href_url, const gchar *url_text, gsize remain, tag_id_t id) +check_phishing (struct rspamd_task *task, + struct uri *href_url, + const gchar *url_text, + gsize remain, + tag_id_t id) { - struct uri *new; - gchar *url_str; - const gchar *p, *c; - gchar tagbuf[128]; - struct html_tag *tag; - gsize len = 0; - gint rc; + struct uri *new; + gchar *url_str; + const gchar *p, *c; + gchar tagbuf[128]; + struct html_tag *tag; + gsize len = 0; + gint rc; p = url_text; while (len < remain) { @@ -678,8 +695,8 @@ check_phishing (struct rspamd_task *task, struct uri *href_url, const gchar *url } while (len < remain) { if (!g_ascii_isspace (*p) && *p != '>') { - p ++; - len ++; + p++; + len++; } else { break; @@ -693,11 +710,11 @@ check_phishing (struct rspamd_task *task, struct uri *href_url, const gchar *url else if (tag->id == Tag_IMG) { /* We should ignore IMG tag here */ while (len < remain && *p != '>' && *p != '<') { - p ++; - len ++; + p++; + len++; } if (*p == '>' && len < remain) { - p ++; + p++; } remain -= p - url_text; @@ -707,19 +724,21 @@ check_phishing (struct rspamd_task *task, struct uri *href_url, const gchar *url } } } - len ++; - p ++; + len++; + p++; } - if (url_try_text (task->task_pool, url_text, len, NULL, NULL, &url_str, TRUE) && url_str != NULL) { + if (url_try_text (task->task_pool, url_text, len, NULL, NULL, &url_str, + TRUE) && url_str != NULL) { new = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct uri)); if (new != NULL) { g_strstrip (url_str); rc = parse_uri (new, url_str, task->task_pool); - if (rc == URI_ERRNO_OK || rc == URI_ERRNO_NO_SLASHES || rc == URI_ERRNO_NO_HOST_SLASH) { + if (rc == URI_ERRNO_OK || rc == URI_ERRNO_NO_SLASHES || rc == + URI_ERRNO_NO_HOST_SLASH) { if (g_ascii_strncasecmp (href_url->host, new->host, - MAX (href_url->hostlen, new->hostlen)) != 0) { + MAX (href_url->hostlen, new->hostlen)) != 0) { /* Special check for urls beginning with 'www' */ if (new->hostlen > 4 && href_url->hostlen > 4) { p = new->host; @@ -762,7 +781,9 @@ check_phishing (struct rspamd_task *task, struct uri *href_url, const gchar *url } } else { - msg_info ("extract of url '%s' failed: %s", url_str, url_strerror (rc)); + msg_info ("extract of url '%s' failed: %s", + url_str, + url_strerror (rc)); } } } @@ -770,13 +791,17 @@ check_phishing (struct rspamd_task *task, struct uri *href_url, const gchar *url } static void -parse_tag_url (struct rspamd_task *task, struct mime_text_part *part, tag_id_t id, - gchar *tag_text, gsize tag_len, gsize remain) +parse_tag_url (struct rspamd_task *task, + struct mime_text_part *part, + tag_id_t id, + gchar *tag_text, + gsize tag_len, + gsize remain) { - gchar *c = NULL, *p, *url_text; - gint len, rc; - struct uri *url; - gboolean got_single_quote = FALSE, got_double_quote = FALSE; + gchar *c = NULL, *p, *url_text; + gint len, rc; + struct uri *url; + gboolean got_single_quote = FALSE, got_double_quote = FALSE; /* For A tags search for href= and for IMG tags search for src= */ if (id == Tag_A) { @@ -814,7 +839,8 @@ parse_tag_url (struct rspamd_task *task, struct mime_text_part *part, tag_id_t i len++; } } - else if (g_ascii_isspace (*p) || *p == '>' || (*p == '/' && *(p + 1) == '>') || *p == '\r' || *p == '\n') { + else if (g_ascii_isspace (*p) || *p == '>' || + (*p == '/' && *(p + 1) == '>') || *p == '\r' || *p == '\n') { break; } else { @@ -843,22 +869,27 @@ parse_tag_url (struct rspamd_task *task, struct mime_text_part *part, tag_id_t i rspamd_strlcpy (url_text, c, len + 1); decode_entitles (url_text, NULL); - if (g_ascii_strncasecmp (url_text, "http://", sizeof ("http://") - 1) != 0 && - g_ascii_strncasecmp (url_text, "www", sizeof ("www") - 1) != 0 && - g_ascii_strncasecmp (url_text, "ftp://", sizeof ("ftp://") - 1) != 0 && - g_ascii_strncasecmp (url_text, "mailto:", sizeof ("mailto:") - 1) != 0) { + if (g_ascii_strncasecmp (url_text, "http://", + sizeof ("http://") - 1) != 0 && + g_ascii_strncasecmp (url_text, "www", + sizeof ("www") - 1) != 0 && + g_ascii_strncasecmp (url_text, "ftp://", + sizeof ("ftp://") - 1) != 0 && + g_ascii_strncasecmp (url_text, "mailto:", + sizeof ("mailto:") - 1) != 0) { return; } url = rspamd_mempool_alloc (task->task_pool, sizeof (struct uri)); rc = parse_uri (url, url_text, task->task_pool); - if (rc != URI_ERRNO_EMPTY && rc != URI_ERRNO_NO_HOST && url->hostlen != 0) { + if (rc != URI_ERRNO_EMPTY && rc != URI_ERRNO_NO_HOST && url->hostlen != + 0) { /* * Check for phishing */ if ((p = strchr (c, '>')) != NULL && id == Tag_A) { - p ++; + p++; check_phishing (task, url, p, remain - (p - tag_text), id); } if (g_tree_lookup (task->urls, url) == NULL) { @@ -869,20 +900,28 @@ parse_tag_url (struct rspamd_task *task, struct mime_text_part *part, tag_id_t i } gboolean -add_html_node (struct rspamd_task *task, rspamd_mempool_t * pool, struct mime_text_part *part, - gchar *tag_text, gsize tag_len, gsize remain, GNode ** cur_level) +add_html_node (struct rspamd_task *task, + rspamd_mempool_t * pool, + struct mime_text_part *part, + gchar *tag_text, + gsize tag_len, + gsize remain, + GNode ** cur_level) { - GNode *new; - struct html_node *data; + GNode *new; + struct html_node *data; if (!tags_sorted) { - qsort (tag_defs, G_N_ELEMENTS (tag_defs), sizeof (struct html_tag), tag_cmp); + qsort (tag_defs, G_N_ELEMENTS ( + tag_defs), sizeof (struct html_tag), tag_cmp); tags_sorted = 1; } if (!entities_sorted) { - qsort (entities_defs, G_N_ELEMENTS (entities_defs), sizeof (entity), entity_cmp); + qsort (entities_defs, G_N_ELEMENTS ( + entities_defs), sizeof (entity), entity_cmp); memcpy (entities_defs_num, entities_defs, sizeof (entities_defs)); - qsort (entities_defs_num, G_N_ELEMENTS (entities_defs), sizeof (entity), entity_cmp_num); + qsort (entities_defs_num, G_N_ELEMENTS ( + entities_defs), sizeof (entity), entity_cmp_num); entities_sorted = 1; } @@ -892,19 +931,32 @@ add_html_node (struct rspamd_task *task, rspamd_mempool_t * pool, struct mime_te new = g_node_new (NULL); *cur_level = new; part->html_nodes = new; - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_node_destroy, part->html_nodes); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_node_destroy, + part->html_nodes); /* Call once again with root node */ - return add_html_node (task, pool, part, tag_text, tag_len, remain, cur_level); + return add_html_node (task, + pool, + part, + tag_text, + tag_len, + remain, + cur_level); } else { new = construct_html_node (pool, tag_text, tag_len); if (new == NULL) { - debug_task ("cannot construct HTML node for text '%*s'", tag_len, tag_text); + debug_task ("cannot construct HTML node for text '%*s'", + tag_len, + tag_text); return FALSE; } data = new->data; - if (data->tag && (data->tag->id == Tag_A || data->tag->id == Tag_IMG) && ((data->flags & FL_CLOSING) == 0)) { - parse_tag_url (task, part, data->tag->id, tag_text, tag_len, remain); + if (data->tag && + (data->tag->id == Tag_A || + data->tag->id == Tag_IMG) && ((data->flags & FL_CLOSING) == 0)) { + parse_tag_url (task, part, data->tag->id, tag_text, tag_len, + remain); } if (data->flags & FL_CLOSING) { @@ -914,7 +966,8 @@ add_html_node (struct rspamd_task *task, rspamd_mempool_t * pool, struct mime_te } g_node_append (*cur_level, new); if (!check_balance (new, cur_level)) { - debug_task ("mark part as unbalanced as it has not pairable closing tags"); + debug_task ( + "mark part as unbalanced as it has not pairable closing tags"); part->is_balanced = FALSE; } } @@ -926,9 +979,9 @@ add_html_node (struct rspamd_task *task, rspamd_mempool_t * pool, struct mime_te } /* Skip some tags */ if (data->tag && (data->tag->id == Tag_STYLE || - data->tag->id == Tag_SCRIPT || - data->tag->id == Tag_OBJECT || - data->tag->id == Tag_TITLE)) { + data->tag->id == Tag_SCRIPT || + data->tag->id == Tag_OBJECT || + data->tag->id == Tag_TITLE)) { return FALSE; } } diff --git a/src/libserver/html.h b/src/libserver/html.h index 3ea758e60..6709ed151 100644 --- a/src/libserver/html.h +++ b/src/libserver/html.h @@ -11,129 +11,129 @@ /* Known HTML tags */ typedef enum { - Tag_UNKNOWN, /**< Unknown tag! */ - Tag_A, /**< A */ - Tag_ABBR, /**< ABBR */ - Tag_ACRONYM, /**< ACRONYM */ - Tag_ADDRESS, /**< ADDRESS */ - Tag_ALIGN, /**< ALIGN */ - Tag_APPLET, /**< APPLET */ - Tag_AREA, /**< AREA */ - Tag_B, /**< B */ - Tag_BASE, /**< BASE */ - Tag_BASEFONT, /**< BASEFONT */ - Tag_BDO, /**< BDO */ - Tag_BGSOUND, /**< BGSOUND */ - Tag_BIG, /**< BIG */ - Tag_BLINK, /**< BLINK */ - Tag_BLOCKQUOTE, /**< BLOCKQUOTE */ - Tag_BODY, /**< BODY */ - Tag_BR, /**< BR */ - Tag_BUTTON, /**< BUTTON */ - Tag_CAPTION, /**< CAPTION */ - Tag_CENTER, /**< CENTER */ - Tag_CITE, /**< CITE */ - Tag_CODE, /**< CODE */ - Tag_COL, /**< COL */ - Tag_COLGROUP, /**< COLGROUP */ - Tag_COMMENT, /**< COMMENT */ - Tag_DD, /**< DD */ - Tag_DEL, /**< DEL */ - Tag_DFN, /**< DFN */ - Tag_DIR, /**< DIR */ - Tag_DIV, /**< DIF */ - Tag_DL, /**< DL */ - Tag_DT, /**< DT */ - Tag_EM, /**< EM */ - Tag_EMBED, /**< EMBED */ - Tag_FIELDSET, /**< FIELDSET */ - Tag_FONT, /**< FONT */ - Tag_FORM, /**< FORM */ - Tag_FRAME, /**< FRAME */ - Tag_FRAMESET, /**< FRAMESET */ - Tag_H1, /**< H1 */ - Tag_H2, /**< H2 */ - Tag_H3, /**< H3 */ - Tag_H4, /**< H4 */ - Tag_H5, /**< H5 */ - Tag_H6, /**< H6 */ - Tag_HEAD, /**< HEAD */ - Tag_HR, /**< HR */ - Tag_HTML, /**< HTML */ - Tag_I, /**< I */ - Tag_IFRAME, /**< IFRAME */ - Tag_ILAYER, /**< ILAYER */ - Tag_IMG, /**< IMG */ - Tag_INPUT, /**< INPUT */ - Tag_INS, /**< INS */ - Tag_ISINDEX, /**< ISINDEX */ - Tag_KBD, /**< KBD */ - Tag_KEYGEN, /**< KEYGEN */ - Tag_LABEL, /**< LABEL */ - Tag_LAYER, /**< LAYER */ - Tag_LEGEND, /**< LEGEND */ - Tag_LI, /**< LI */ - Tag_LINK, /**< LINK */ - Tag_LISTING, /**< LISTING */ - Tag_MAP, /**< MAP */ - Tag_MARQUEE, /**< MARQUEE */ - Tag_MENU, /**< MENU */ - Tag_META, /**< META */ - Tag_MULTICOL, /**< MULTICOL */ - Tag_NOBR, /**< NOBR */ - Tag_NOEMBED, /**< NOEMBED */ - Tag_NOFRAMES, /**< NOFRAMES */ - Tag_NOLAYER, /**< NOLAYER */ - Tag_NOSAVE, /**< NOSAVE */ - Tag_NOSCRIPT, /**< NOSCRIPT */ - Tag_OBJECT, /**< OBJECT */ - Tag_OL, /**< OL */ - Tag_OPTGROUP, /**< OPTGROUP */ - Tag_OPTION, /**< OPTION */ - Tag_P, /**< P */ - Tag_PARAM, /**< PARAM */ - Tag_PLAINTEXT,/**< PLAINTEXT */ - Tag_PRE, /**< PRE */ - Tag_Q, /**< Q */ - Tag_RB, /**< RB */ - Tag_RBC, /**< RBC */ - Tag_RP, /**< RP */ - Tag_RT, /**< RT */ - Tag_RTC, /**< RTC */ - Tag_RUBY, /**< RUBY */ - Tag_S, /**< S */ - Tag_SAMP, /**< SAMP */ - Tag_SCRIPT, /**< SCRIPT */ - Tag_SELECT, /**< SELECT */ - Tag_SERVER, /**< SERVER */ - Tag_SERVLET, /**< SERVLET */ - Tag_SMALL, /**< SMALL */ - Tag_SPACER, /**< SPACER */ - Tag_SPAN, /**< SPAN */ - Tag_STRIKE, /**< STRIKE */ - Tag_STRONG, /**< STRONG */ - Tag_STYLE, /**< STYLE */ - Tag_SUB, /**< SUB */ - Tag_SUP, /**< SUP */ - Tag_TABLE, /**< TABLE */ - Tag_TBODY, /**< TBODY */ - Tag_TD, /**< TD */ - Tag_TEXTAREA, /**< TEXTAREA */ - Tag_TFOOT, /**< TFOOT */ - Tag_TH, /**< TH */ - Tag_THEAD, /**< THEAD */ - Tag_TITLE, /**< TITLE */ - Tag_TR, /**< TR */ - Tag_TT, /**< TT */ - Tag_U, /**< U */ - Tag_UL, /**< UL */ - Tag_VAR, /**< VAR */ - Tag_WBR, /**< WBR */ - Tag_XMP, /**< XMP */ - Tag_XML, /**< XML */ - Tag_NEXTID, /**< NEXTID */ + Tag_UNKNOWN, /**< Unknown tag! */ + Tag_A, /**< A */ + Tag_ABBR, /**< ABBR */ + Tag_ACRONYM, /**< ACRONYM */ + Tag_ADDRESS, /**< ADDRESS */ + Tag_ALIGN, /**< ALIGN */ + Tag_APPLET, /**< APPLET */ + Tag_AREA, /**< AREA */ + Tag_B, /**< B */ + Tag_BASE, /**< BASE */ + Tag_BASEFONT, /**< BASEFONT */ + Tag_BDO, /**< BDO */ + Tag_BGSOUND, /**< BGSOUND */ + Tag_BIG, /**< BIG */ + Tag_BLINK, /**< BLINK */ + Tag_BLOCKQUOTE, /**< BLOCKQUOTE */ + Tag_BODY, /**< BODY */ + Tag_BR, /**< BR */ + Tag_BUTTON, /**< BUTTON */ + Tag_CAPTION, /**< CAPTION */ + Tag_CENTER, /**< CENTER */ + Tag_CITE, /**< CITE */ + Tag_CODE, /**< CODE */ + Tag_COL, /**< COL */ + Tag_COLGROUP, /**< COLGROUP */ + Tag_COMMENT, /**< COMMENT */ + Tag_DD, /**< DD */ + Tag_DEL, /**< DEL */ + Tag_DFN, /**< DFN */ + Tag_DIR, /**< DIR */ + Tag_DIV, /**< DIF */ + Tag_DL, /**< DL */ + Tag_DT, /**< DT */ + Tag_EM, /**< EM */ + Tag_EMBED, /**< EMBED */ + Tag_FIELDSET, /**< FIELDSET */ + Tag_FONT, /**< FONT */ + Tag_FORM, /**< FORM */ + Tag_FRAME, /**< FRAME */ + Tag_FRAMESET, /**< FRAMESET */ + Tag_H1, /**< H1 */ + Tag_H2, /**< H2 */ + Tag_H3, /**< H3 */ + Tag_H4, /**< H4 */ + Tag_H5, /**< H5 */ + Tag_H6, /**< H6 */ + Tag_HEAD, /**< HEAD */ + Tag_HR, /**< HR */ + Tag_HTML, /**< HTML */ + Tag_I, /**< I */ + Tag_IFRAME, /**< IFRAME */ + Tag_ILAYER, /**< ILAYER */ + Tag_IMG, /**< IMG */ + Tag_INPUT, /**< INPUT */ + Tag_INS, /**< INS */ + Tag_ISINDEX, /**< ISINDEX */ + Tag_KBD, /**< KBD */ + Tag_KEYGEN, /**< KEYGEN */ + Tag_LABEL, /**< LABEL */ + Tag_LAYER, /**< LAYER */ + Tag_LEGEND, /**< LEGEND */ + Tag_LI, /**< LI */ + Tag_LINK, /**< LINK */ + Tag_LISTING, /**< LISTING */ + Tag_MAP, /**< MAP */ + Tag_MARQUEE, /**< MARQUEE */ + Tag_MENU, /**< MENU */ + Tag_META, /**< META */ + Tag_MULTICOL, /**< MULTICOL */ + Tag_NOBR, /**< NOBR */ + Tag_NOEMBED, /**< NOEMBED */ + Tag_NOFRAMES, /**< NOFRAMES */ + Tag_NOLAYER, /**< NOLAYER */ + Tag_NOSAVE, /**< NOSAVE */ + Tag_NOSCRIPT, /**< NOSCRIPT */ + Tag_OBJECT, /**< OBJECT */ + Tag_OL, /**< OL */ + Tag_OPTGROUP, /**< OPTGROUP */ + Tag_OPTION, /**< OPTION */ + Tag_P, /**< P */ + Tag_PARAM, /**< PARAM */ + Tag_PLAINTEXT, /**< PLAINTEXT */ + Tag_PRE, /**< PRE */ + Tag_Q, /**< Q */ + Tag_RB, /**< RB */ + Tag_RBC, /**< RBC */ + Tag_RP, /**< RP */ + Tag_RT, /**< RT */ + Tag_RTC, /**< RTC */ + Tag_RUBY, /**< RUBY */ + Tag_S, /**< S */ + Tag_SAMP, /**< SAMP */ + Tag_SCRIPT, /**< SCRIPT */ + Tag_SELECT, /**< SELECT */ + Tag_SERVER, /**< SERVER */ + Tag_SERVLET, /**< SERVLET */ + Tag_SMALL, /**< SMALL */ + Tag_SPACER, /**< SPACER */ + Tag_SPAN, /**< SPAN */ + Tag_STRIKE, /**< STRIKE */ + Tag_STRONG, /**< STRONG */ + Tag_STYLE, /**< STYLE */ + Tag_SUB, /**< SUB */ + Tag_SUP, /**< SUP */ + Tag_TABLE, /**< TABLE */ + Tag_TBODY, /**< TBODY */ + Tag_TD, /**< TD */ + Tag_TEXTAREA, /**< TEXTAREA */ + Tag_TFOOT, /**< TFOOT */ + Tag_TH, /**< TH */ + Tag_THEAD, /**< THEAD */ + Tag_TITLE, /**< TITLE */ + Tag_TR, /**< TR */ + Tag_TT, /**< TT */ + Tag_U, /**< U */ + Tag_UL, /**< UL */ + Tag_VAR, /**< VAR */ + Tag_WBR, /**< WBR */ + Tag_XMP, /**< XMP */ + Tag_XML, /**< XML */ + Tag_NEXTID, /**< NEXTID */ - N_TAGS /**< Must be last */ + N_TAGS /**< Must be last */ } tag_id_t; #define CM_UNKNOWN 0 @@ -175,7 +175,7 @@ typedef enum #define CM_IMG (1 << 16) /* Elements with inline and block model. Used to avoid calling InlineDup. */ #define CM_MIXED (1 << 17) -/* Elements whose content needs to be indented only if containing one +/* Elements whose content needs to be indented only if containing one CM_BLOCK element. */ #define CM_NO_INDENT (1 << 18) /* Elements that are obsolete (such as "dir", "menu"). */ @@ -187,11 +187,11 @@ typedef enum #define CM_OMITST (1 << 21) /* XML tag */ -#define FL_XML (1 << 0) +#define FL_XML (1 << 0) /* Closing tag */ -#define FL_CLOSING (1 << 1) +#define FL_CLOSING (1 << 1) /* Fully closed tag (e.g. <a attrs />) */ -#define FL_CLOSED (1 << 2) +#define FL_CLOSED (1 << 2) struct html_tag { tag_id_t id; @@ -210,8 +210,13 @@ struct rspamd_task; /* * Add a single node to the tags tree */ -gboolean add_html_node (struct rspamd_task *task, rspamd_mempool_t *pool, - struct mime_text_part *part, gchar *tag_text, gsize tag_len, gsize remain, GNode **cur_level); +gboolean add_html_node (struct rspamd_task *task, + rspamd_mempool_t *pool, + struct mime_text_part *part, + gchar *tag_text, + gsize tag_len, + gsize remain, + GNode **cur_level); /* * Get tag structure by its name (binary search is used) diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c index fc4096f8c..9d3e842cb 100644 --- a/src/libserver/protocol.c +++ b/src/libserver/protocol.c @@ -35,7 +35,7 @@ * described below */ #define MSG_CMD_CHECK "check" -/* +/* * Check if message is spam or not, and return score plus list * of symbols hit */ @@ -95,7 +95,7 @@ #define DELIVER_TO_HEADER "Deliver-To" #define NO_LOG_HEADER "Log" -static GList *custom_commands = NULL; +static GList *custom_commands = NULL; /* @@ -104,20 +104,22 @@ static GList *custom_commands = NULL; static gchar * rspamd_protocol_escape_braces (GString *in) { - gint len = 0; - gchar *orig, *p; + gint len = 0; + gchar *orig, *p; orig = in->str; - while ((g_ascii_isspace (*orig) || *orig == '<') && orig - in->str < (gint)in->len) { - orig ++; + while ((g_ascii_isspace (*orig) || *orig == + '<') && orig - in->str < (gint)in->len) { + orig++; } g_string_erase (in, 0, orig - in->str); p = in->str; - while ((!g_ascii_isspace (*p) && *p != '>') && p - in->str < (gint)in->len) { - p ++; - len ++; + while ((!g_ascii_isspace (*p) && *p != + '>') && p - in->str < (gint)in->len) { + p++; + len++; } g_string_truncate (in, len); @@ -126,10 +128,11 @@ rspamd_protocol_escape_braces (GString *in) } static gboolean -rspamd_protocol_handle_url (struct rspamd_task *task, struct rspamd_http_message *msg) +rspamd_protocol_handle_url (struct rspamd_task *task, + struct rspamd_http_message *msg) { - GList *cur; - struct custom_command *cmd; + GList *cur; + struct custom_command *cmd; const gchar *p; if (msg->url == NULL || msg->url->len == 0) { @@ -224,13 +227,14 @@ err: gboolean rspamd_protocol_handle_headers (struct rspamd_task *task, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - gchar *headern, *err, *tmp; - gboolean res = TRUE; - struct rspamd_http_header *h; + gchar *headern, *err, *tmp; + gboolean res = TRUE; + struct rspamd_http_header *h; - LL_FOREACH (msg->headers, h) { + LL_FOREACH (msg->headers, h) + { headern = h->name->str; switch (headern[0]) { @@ -238,7 +242,8 @@ rspamd_protocol_handle_headers (struct rspamd_task *task, case 'D': if (g_ascii_strcasecmp (headern, DELIVER_TO_HEADER) == 0) { task->deliver_to = rspamd_protocol_escape_braces (h->value); - debug_task ("read deliver-to header, value: %s", task->deliver_to); + debug_task ("read deliver-to header, value: %s", + task->deliver_to); } else { debug_task ("wrong header: %s", headern); @@ -327,7 +332,7 @@ rspamd_protocol_handle_headers (struct rspamd_task *task, case 'P': if (g_ascii_strcasecmp (headern, PASS_HEADER) == 0) { if (h->value->len == sizeof ("all") - 1 && - g_ascii_strcasecmp (h->value->str, "all") == 0) { + g_ascii_strcasecmp (h->value->str, "all") == 0) { task->pass_all_filters = TRUE; debug_task ("pass all filters"); } @@ -373,7 +378,8 @@ rspamd_protocol_handle_headers (struct rspamd_task *task, } if (!res && task->cfg->strict_protocol_headers) { - msg_err ("deny processing of a request with incorrect or unknown headers"); + msg_err ( + "deny processing of a request with incorrect or unknown headers"); task->last_error = "invalid header"; task->error_code = 400; return FALSE; @@ -384,7 +390,7 @@ rspamd_protocol_handle_headers (struct rspamd_task *task, gboolean rspamd_protocol_handle_request (struct rspamd_task *task, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { gboolean ret = TRUE; @@ -407,19 +413,22 @@ rspamd_protocol_handle_request (struct rspamd_task *task, static void write_hashes_to_log (struct rspamd_task *task, GString *logbuf) { - GList *cur; - struct mime_text_part *text_part; - + GList *cur; + struct mime_text_part *text_part; + cur = task->text_parts; while (cur) { text_part = cur->data; if (text_part->fuzzy) { if (cur->next != NULL) { - rspamd_printf_gstring (logbuf, " part: %Xd,", text_part->fuzzy->h); + rspamd_printf_gstring (logbuf, + " part: %Xd,", + text_part->fuzzy->h); } else { - rspamd_printf_gstring (logbuf, " part: %Xd", text_part->fuzzy->h); + rspamd_printf_gstring (logbuf, " part: %Xd", + text_part->fuzzy->h); } } cur = g_list_next (cur); @@ -439,18 +448,20 @@ struct tree_cb_data { static gboolean urls_protocol_cb (gpointer key, gpointer value, gpointer ud) { - struct tree_cb_data *cb = ud; - struct uri *url = value; - ucl_object_t *obj; + struct tree_cb_data *cb = ud; + struct uri *url = value; + ucl_object_t *obj; obj = ucl_object_fromlstring (url->host, url->hostlen); DL_APPEND (cb->top->value.av, obj); if (cb->task->cfg->log_urls) { - msg_info ("<%s> URL: %s - %s: %s", cb->task->message_id, cb->task->user ? - cb->task->user : (cb->task->from ? cb->task->from : "unknown"), - rspamd_inet_address_to_string (&cb->task->from_addr), - struri (url)); + msg_info ("<%s> URL: %s - %s: %s", + cb->task->message_id, + cb->task->user ? + cb->task->user : (cb->task->from ? cb->task->from : "unknown"), + rspamd_inet_address_to_string (&cb->task->from_addr), + struri (url)); } return FALSE; @@ -459,8 +470,8 @@ urls_protocol_cb (gpointer key, gpointer value, gpointer ud) static ucl_object_t * rspamd_urls_tree_ucl (GTree *input, struct rspamd_task *task) { - struct tree_cb_data cb; - ucl_object_t *obj; + struct tree_cb_data cb; + ucl_object_t *obj; obj = ucl_object_typed_new (UCL_ARRAY); cb.top = obj; @@ -474,9 +485,9 @@ rspamd_urls_tree_ucl (GTree *input, struct rspamd_task *task) static gboolean emails_protocol_cb (gpointer key, gpointer value, gpointer ud) { - struct tree_cb_data *cb = ud; - struct uri *url = value; - ucl_object_t *obj; + struct tree_cb_data *cb = ud; + struct uri *url = value; + ucl_object_t *obj; obj = ucl_object_fromlstring (url->user, url->userlen + url->hostlen + 1); DL_APPEND (cb->top->value.av, obj); @@ -487,8 +498,8 @@ emails_protocol_cb (gpointer key, gpointer value, gpointer ud) static ucl_object_t * rspamd_emails_tree_ucl (GTree *input, struct rspamd_task *task) { - struct tree_cb_data cb; - ucl_object_t *obj; + struct tree_cb_data cb; + ucl_object_t *obj; obj = ucl_object_typed_new (UCL_ARRAY); cb.top = obj; @@ -504,9 +515,9 @@ rspamd_emails_tree_ucl (GTree *input, struct rspamd_task *task) static const gchar * make_rewritten_subject (struct metric *metric, struct rspamd_task *task) { - static gchar subj_buf[1024]; - gchar *p = subj_buf, *end, *c, *res; - const gchar *s; + static gchar subj_buf[1024]; + gchar *p = subj_buf, *end, *c, *res; + const gchar *s; end = p + sizeof(subj_buf); c = metric->subject; @@ -522,13 +533,15 @@ make_rewritten_subject (struct metric *metric, struct rspamd_task *task) c += 2; } else { - *p = *c ++; + *p = *c++; } - p ++; + p++; } res = g_mime_utils_header_encode_text (subj_buf); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_free, res); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_free, + res); return res; } @@ -536,8 +549,8 @@ make_rewritten_subject (struct metric *metric, struct rspamd_task *task) static ucl_object_t * rspamd_str_list_ucl (GList *str_list) { - ucl_object_t *top = NULL, *obj; - GList *cur; + ucl_object_t *top = NULL, *obj; + GList *cur; top = ucl_object_typed_new (UCL_ARRAY); cur = str_list; @@ -552,40 +565,46 @@ rspamd_str_list_ucl (GList *str_list) static ucl_object_t * rspamd_metric_symbol_ucl (struct rspamd_task *task, struct metric *m, - struct symbol *sym, GString *logbuf) + struct symbol *sym, GString *logbuf) { - ucl_object_t *obj = NULL; - const gchar *description = NULL; + ucl_object_t *obj = NULL; + const gchar *description = NULL; rspamd_printf_gstring (logbuf, "%s,", sym->name); description = g_hash_table_lookup (m->descriptions, sym->name); obj = ucl_object_typed_new (UCL_OBJECT); - ucl_object_insert_key (obj, ucl_object_fromstring (sym->name), "name", 0, false); - ucl_object_insert_key (obj, ucl_object_fromdouble (sym->score), "score", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + sym->name), "name", 0, false); + ucl_object_insert_key (obj, ucl_object_fromdouble ( + sym->score), "score", 0, false); if (description) { - ucl_object_insert_key (obj, ucl_object_fromstring (description), "description", 0, false); + ucl_object_insert_key (obj, ucl_object_fromstring ( + description), "description", 0, false); } if (sym->options != NULL) { - ucl_object_insert_key (obj, rspamd_str_list_ucl (sym->options), "options", 0, false); + ucl_object_insert_key (obj, rspamd_str_list_ucl ( + sym->options), "options", 0, false); } return obj; } static ucl_object_t * -rspamd_metric_result_ucl (struct rspamd_task *task, struct metric_result *mres, GString *logbuf) +rspamd_metric_result_ucl (struct rspamd_task *task, + struct metric_result *mres, + GString *logbuf) { - GHashTableIter hiter; - struct symbol *sym; - struct metric *m; - gboolean is_spam; - enum rspamd_metric_action action = METRIC_ACTION_NOACTION; - ucl_object_t *obj = NULL, *sobj; - gdouble required_score; - gpointer h, v; - const gchar *subject; - gchar action_char; + GHashTableIter hiter; + struct symbol *sym; + struct metric *m; + gboolean is_spam; + enum rspamd_metric_action action = METRIC_ACTION_NOACTION; + ucl_object_t *obj = NULL, *sobj; + gdouble required_score; + gpointer h, v; + const gchar *subject; + gchar action_char; m = mres->metric; @@ -603,26 +622,27 @@ rspamd_metric_result_ucl (struct rspamd_task *task, struct metric_result *mres, action_char = 'F'; } rspamd_printf_gstring (logbuf, "(%s: %c (%s): [%.2f/%.2f] [", - m->name, action_char, - str_action_metric (action), - mres->score, required_score); + m->name, action_char, + str_action_metric (action), + mres->score, required_score); obj = ucl_object_typed_new (UCL_OBJECT); - ucl_object_insert_key (obj, ucl_object_frombool (is_spam), - "is_spam", 0, false); - ucl_object_insert_key (obj, ucl_object_frombool (task->is_skipped), - "is_skipped", 0, false); + ucl_object_insert_key (obj, ucl_object_frombool (is_spam), + "is_spam", 0, false); + ucl_object_insert_key (obj, ucl_object_frombool (task->is_skipped), + "is_skipped", 0, false); ucl_object_insert_key (obj, ucl_object_fromdouble (mres->score), - "score", 0, false); + "score", 0, false); ucl_object_insert_key (obj, ucl_object_fromdouble (required_score), - "required_score", 0, false); - ucl_object_insert_key (obj, ucl_object_fromstring (str_action_metric (action)), - "action", 0, false); + "required_score", 0, false); + ucl_object_insert_key (obj, + ucl_object_fromstring (str_action_metric (action)), + "action", 0, false); if (action == METRIC_ACTION_REWRITE_SUBJECT) { subject = make_rewritten_subject (m, task); ucl_object_insert_key (obj, ucl_object_fromstring (subject), - "subject", 0, false); + "subject", 0, false); } /* Now handle symbols */ g_hash_table_iter_init (&hiter, mres->symbols); @@ -634,28 +654,31 @@ rspamd_metric_result_ucl (struct rspamd_task *task, struct metric_result *mres, /* Cut the trailing comma if needed */ if (logbuf->str[logbuf->len - 1] == ',') { - logbuf->len --; + logbuf->len--; } #ifdef HAVE_CLOCK_GETTIME rspamd_printf_gstring (logbuf, "]), len: %z, time: %s, dns req: %d,", - task->msg->len, calculate_check_time (&task->tv, &task->ts, - task->cfg->clock_res, &task->scan_milliseconds), task->dns_requests); + task->msg->len, calculate_check_time (&task->tv, &task->ts, + task->cfg->clock_res, &task->scan_milliseconds), task->dns_requests); #else rspamd_printf_gstring (logbuf, "]), len: %z, time: %s, dns req: %d,", - task->msg->len, - calculate_check_time (&task->tv, task->cfg->clock_res, &task->scan_milliseconds), - task->dns_requests); + task->msg->len, + calculate_check_time (&task->tv, task->cfg->clock_res, + &task->scan_milliseconds), + task->dns_requests); #endif return obj; } static void -rspamd_ucl_tolegacy_output (struct rspamd_task *task, ucl_object_t *top, GString *out) +rspamd_ucl_tolegacy_output (struct rspamd_task *task, + ucl_object_t *top, + GString *out) { const ucl_object_t *metric, *score, - *required_score, *is_spam, *elt; + *required_score, *is_spam, *elt; ucl_object_iter_t iter = NULL; metric = ucl_object_find_key (top, DEFAULT_METRIC); @@ -663,10 +686,11 @@ rspamd_ucl_tolegacy_output (struct rspamd_task *task, ucl_object_t *top, GString score = ucl_object_find_key (metric, "score"); required_score = ucl_object_find_key (metric, "required_score"); is_spam = ucl_object_find_key (metric, "is_spam"); - g_string_append_printf (out, "Metric: default; %s; %.2f / %.2f / 0.0\r\n", - ucl_object_toboolean (is_spam) ? "True" : "False", - ucl_object_todouble (score), - ucl_object_todouble (required_score)); + g_string_append_printf (out, + "Metric: default; %s; %.2f / %.2f / 0.0\r\n", + ucl_object_toboolean (is_spam) ? "True" : "False", + ucl_object_todouble (score), + ucl_object_todouble (required_score)); elt = ucl_object_find_key (metric, "action"); if (elt != NULL) { g_string_append_printf (out, "Action: %s\r\n", @@ -679,34 +703,38 @@ rspamd_ucl_tolegacy_output (struct rspamd_task *task, ucl_object_t *top, GString const ucl_object_t *sym_score; sym_score = ucl_object_find_key (elt, "score"); g_string_append_printf (out, "Symbol: %s(%.2f)\r\n", - ucl_object_key (elt), - ucl_object_todouble (sym_score)); + ucl_object_key (elt), + ucl_object_todouble (sym_score)); } } elt = ucl_object_find_key (metric, "subject"); if (elt != NULL) { g_string_append_printf (out, "Subject: %s\r\n", - ucl_object_tostring (elt)); + ucl_object_tostring (elt)); } } g_string_append_printf (out, "Message-ID: %s\r\n", task->message_id); } void -rspamd_protocol_http_reply (struct rspamd_http_message *msg, struct rspamd_task *task) +rspamd_protocol_http_reply (struct rspamd_http_message *msg, + struct rspamd_task *task) { - GString *logbuf; - struct metric_result *metric_res; - GHashTableIter hiter; - gpointer h, v; - ucl_object_t *top = NULL, *obj; - gdouble required_score; - gint action; + GString *logbuf; + struct metric_result *metric_res; + GHashTableIter hiter; + gpointer h, v; + ucl_object_t *top = NULL, *obj; + gdouble required_score; + gint action; /* Output the first line - check status */ logbuf = g_string_sized_new (BUFSIZ); - rspamd_printf_gstring (logbuf, "id: <%s>, qid: <%s>, ", task->message_id, task->queue_id); + rspamd_printf_gstring (logbuf, + "id: <%s>, qid: <%s>, ", + task->message_id, + task->queue_id); if (task->user) { rspamd_printf_gstring (logbuf, "user: %s, ", task->user); @@ -726,18 +754,20 @@ rspamd_protocol_http_reply (struct rspamd_http_message *msg, struct rspamd_task } if (task->messages != NULL) { - ucl_object_insert_key (top, rspamd_str_list_ucl (task->messages), "messages", 0, false); + ucl_object_insert_key (top, rspamd_str_list_ucl ( + task->messages), "messages", 0, false); } if (g_tree_nnodes (task->urls) > 0) { - ucl_object_insert_key (top, rspamd_urls_tree_ucl (task->urls, task), "urls", 0, false); + ucl_object_insert_key (top, rspamd_urls_tree_ucl (task->urls, + task), "urls", 0, false); } if (g_tree_nnodes (task->emails) > 0) { ucl_object_insert_key (top, rspamd_emails_tree_ucl (task->emails, task), - "emails", 0, false); + "emails", 0, false); } - + ucl_object_insert_key (top, ucl_object_fromstring (task->message_id), - "message-id", 0, false); + "message-id", 0, false); write_hashes_to_log (task, logbuf); if (!task->no_log) { @@ -758,11 +788,12 @@ rspamd_protocol_http_reply (struct rspamd_http_message *msg, struct rspamd_task /* Update stat for default metric */ metric_res = g_hash_table_lookup (task->results, DEFAULT_METRIC); if (metric_res != NULL) { - required_score = metric_res->metric->actions[METRIC_ACTION_REJECT].score; + required_score = + metric_res->metric->actions[METRIC_ACTION_REJECT].score; action = check_metric_action (metric_res->score, required_score, metric_res->metric); if (action <= METRIC_ACTION_NOACTION) { - task->worker->srv->stat->actions_stat[action] ++; + task->worker->srv->stat->actions_stat[action]++; } } @@ -773,9 +804,9 @@ rspamd_protocol_http_reply (struct rspamd_http_message *msg, struct rspamd_task void rspamd_protocol_write_reply (struct rspamd_task *task) { - struct rspamd_http_message *msg; - const gchar *ctype = "application/json"; - ucl_object_t *top = NULL; + struct rspamd_http_message *msg; + const gchar *ctype = "application/json"; + ucl_object_t *top = NULL; msg = rspamd_http_new_message (HTTP_RESPONSE); if (!task->is_json) { @@ -792,7 +823,7 @@ rspamd_protocol_write_reply (struct rspamd_task *task) msg->code = 500 + task->error_code % 100; msg->status = g_string_new (task->last_error); ucl_object_insert_key (top, ucl_object_fromstring (task->last_error), - "error", 0, false); + "error", 0, false); msg->body = g_string_sized_new (256); rspamd_ucl_emit_gstring (top, UCL_EMIT_JSON_COMPACT, msg->body); ucl_object_unref (top); @@ -818,13 +849,13 @@ rspamd_protocol_write_reply (struct rspamd_task *task) rspamd_http_connection_reset (task->http_conn); rspamd_http_connection_write_message (task->http_conn, msg, NULL, - ctype, task, task->sock, &task->tv, task->ev_base); + ctype, task, task->sock, &task->tv, task->ev_base); } void register_protocol_command (const gchar *name, protocol_reply_func func) { - struct custom_command *cmd; + struct custom_command *cmd; cmd = g_malloc (sizeof (struct custom_command)); cmd->name = name; diff --git a/src/libserver/protocol.h b/src/libserver/protocol.h index aed45752c..8fdd7e56f 100644 --- a/src/libserver/protocol.h +++ b/src/libserver/protocol.h @@ -27,7 +27,7 @@ struct metric; * @return */ gboolean rspamd_protocol_handle_headers (struct rspamd_task *task, - struct rspamd_http_message *msg); + struct rspamd_http_message *msg); /** * Process HTTP request to the task structure @@ -36,7 +36,7 @@ gboolean rspamd_protocol_handle_headers (struct rspamd_task *task, * @return */ gboolean rspamd_protocol_handle_request (struct rspamd_task *task, - struct rspamd_http_message *msg); + struct rspamd_http_message *msg); /** * Write task results to http message @@ -44,7 +44,7 @@ gboolean rspamd_protocol_handle_request (struct rspamd_task *task, * @param task */ void rspamd_protocol_http_reply (struct rspamd_http_message *msg, - struct rspamd_task *task); + struct rspamd_task *task); /** * Write reply for specified task command diff --git a/src/libserver/proxy.c b/src/libserver/proxy.c index 67c7665b8..a4076954b 100644 --- a/src/libserver/proxy.c +++ b/src/libserver/proxy.c @@ -28,7 +28,7 @@ static void rspamd_proxy_backend_handler (gint fd, gshort what, gpointer data); static void rspamd_proxy_client_handler (gint fd, gshort what, gpointer data); -static inline GQuark +static inline GQuark proxy_error_quark (void) { return g_quark_from_static_string ("proxy-error"); @@ -50,9 +50,9 @@ rspamd_proxy_close (rspamd_proxy_t *proxy) static void rspamd_proxy_client_handler (gint fd, gshort what, gpointer data) { - rspamd_proxy_t *proxy = data; - gint r; - GError *err = NULL; + rspamd_proxy_t *proxy = data; + gint r; + GError *err = NULL; if (what == EV_READ) { /* Got data from client */ @@ -63,14 +63,20 @@ rspamd_proxy_client_handler (gint fd, gshort what, gpointer data) proxy->read_len = r; proxy->buf_offset = 0; event_del (&proxy->backend_ev); - event_set (&proxy->backend_ev, proxy->bfd, EV_WRITE, rspamd_proxy_backend_handler, proxy); + event_set (&proxy->backend_ev, + proxy->bfd, + EV_WRITE, + rspamd_proxy_backend_handler, + proxy); event_add (&proxy->backend_ev, proxy->tv); } else { /* Error case or zero reply */ if (r < 0) { /* Error case */ - g_set_error (&err, proxy_error_quark(), r, "Client read error: %s", strerror (errno)); + g_set_error (&err, + proxy_error_quark (), r, "Client read error: %s", + strerror (errno)); rspamd_proxy_close (proxy); proxy->err_cb (err, proxy->user_data); } @@ -83,17 +89,27 @@ rspamd_proxy_client_handler (gint fd, gshort what, gpointer data) } else if (what == EV_WRITE) { /* Can write to client */ - r = write (proxy->cfd, proxy->buf + proxy->buf_offset, proxy->read_len - proxy->buf_offset); + r = write (proxy->cfd, + proxy->buf + proxy->buf_offset, + proxy->read_len - proxy->buf_offset); if (r > 0) { /* We wrote something */ - proxy->buf_offset +=r; + proxy->buf_offset += r; if (proxy->buf_offset == proxy->read_len) { /* We wrote everything */ event_del (&proxy->client_ev); - event_set (&proxy->client_ev, proxy->cfd, EV_READ, rspamd_proxy_client_handler, proxy); + event_set (&proxy->client_ev, + proxy->cfd, + EV_READ, + rspamd_proxy_client_handler, + proxy); event_add (&proxy->client_ev, proxy->tv); event_del (&proxy->backend_ev); - event_set (&proxy->backend_ev, proxy->bfd, EV_READ, rspamd_proxy_backend_handler, proxy); + event_set (&proxy->backend_ev, + proxy->bfd, + EV_READ, + rspamd_proxy_backend_handler, + proxy); event_add (&proxy->backend_ev, proxy->tv); } else { @@ -105,7 +121,9 @@ rspamd_proxy_client_handler (gint fd, gshort what, gpointer data) /* Error case or zero reply */ if (r < 0) { /* Error case */ - g_set_error (&err, proxy_error_quark(), r, "Client write error: %s", strerror (errno)); + g_set_error (&err, + proxy_error_quark (), r, "Client write error: %s", + strerror (errno)); rspamd_proxy_close (proxy); proxy->err_cb (err, proxy->user_data); } @@ -118,7 +136,7 @@ rspamd_proxy_client_handler (gint fd, gshort what, gpointer data) } else { /* Got timeout */ - g_set_error (&err, proxy_error_quark(), ETIMEDOUT, "Client timeout"); + g_set_error (&err, proxy_error_quark (), ETIMEDOUT, "Client timeout"); rspamd_proxy_close (proxy); proxy->err_cb (err, proxy->user_data); } @@ -127,9 +145,9 @@ rspamd_proxy_client_handler (gint fd, gshort what, gpointer data) static void rspamd_proxy_backend_handler (gint fd, gshort what, gpointer data) { - rspamd_proxy_t *proxy = data; - gint r; - GError *err = NULL; + rspamd_proxy_t *proxy = data; + gint r; + GError *err = NULL; if (what == EV_READ) { /* Got data from backend */ @@ -140,14 +158,20 @@ rspamd_proxy_backend_handler (gint fd, gshort what, gpointer data) proxy->read_len = r; proxy->buf_offset = 0; event_del (&proxy->client_ev); - event_set (&proxy->client_ev, proxy->bfd, EV_WRITE, rspamd_proxy_client_handler, proxy); + event_set (&proxy->client_ev, + proxy->bfd, + EV_WRITE, + rspamd_proxy_client_handler, + proxy); event_add (&proxy->client_ev, proxy->tv); } else { /* Error case or zero reply */ if (r < 0) { /* Error case */ - g_set_error (&err, proxy_error_quark(), r, "Backend read error: %s", strerror (errno)); + g_set_error (&err, + proxy_error_quark (), r, "Backend read error: %s", + strerror (errno)); rspamd_proxy_close (proxy); proxy->err_cb (err, proxy->user_data); } @@ -160,17 +184,27 @@ rspamd_proxy_backend_handler (gint fd, gshort what, gpointer data) } else if (what == EV_WRITE) { /* Can write to backend */ - r = write (proxy->bfd, proxy->buf + proxy->buf_offset, proxy->read_len - proxy->buf_offset); + r = write (proxy->bfd, + proxy->buf + proxy->buf_offset, + proxy->read_len - proxy->buf_offset); if (r > 0) { /* We wrote something */ - proxy->buf_offset +=r; + proxy->buf_offset += r; if (proxy->buf_offset == proxy->read_len) { /* We wrote everything */ event_del (&proxy->backend_ev); - event_set (&proxy->backend_ev, proxy->bfd, EV_READ, rspamd_proxy_backend_handler, proxy); + event_set (&proxy->backend_ev, + proxy->bfd, + EV_READ, + rspamd_proxy_backend_handler, + proxy); event_add (&proxy->backend_ev, proxy->tv); event_del (&proxy->client_ev); - event_set (&proxy->client_ev, proxy->cfd, EV_READ, rspamd_proxy_client_handler, proxy); + event_set (&proxy->client_ev, + proxy->cfd, + EV_READ, + rspamd_proxy_client_handler, + proxy); event_add (&proxy->client_ev, proxy->tv); } else { @@ -182,7 +216,9 @@ rspamd_proxy_backend_handler (gint fd, gshort what, gpointer data) /* Error case or zero reply */ if (r < 0) { /* Error case */ - g_set_error (&err, proxy_error_quark(), r, "Backend write error: %s", strerror (errno)); + g_set_error (&err, + proxy_error_quark (), r, "Backend write error: %s", + strerror (errno)); rspamd_proxy_close (proxy); proxy->err_cb (err, proxy->user_data); } @@ -195,7 +231,7 @@ rspamd_proxy_backend_handler (gint fd, gshort what, gpointer data) } else { /* Got timeout */ - g_set_error (&err, proxy_error_quark(), ETIMEDOUT, "Client timeout"); + g_set_error (&err, proxy_error_quark (), ETIMEDOUT, "Client timeout"); rspamd_proxy_close (proxy); proxy->err_cb (err, proxy->user_data); } @@ -210,11 +246,17 @@ rspamd_proxy_backend_handler (gint fd, gshort what, gpointer data) * @param ud user data for callback * @return new proxy object */ -rspamd_proxy_t* -rspamd_create_proxy (gint cfd, gint bfd, rspamd_mempool_t *pool, struct event_base *base, - gsize bufsize, struct timeval *tv, dispatcher_err_callback_t err_cb, gpointer ud) +rspamd_proxy_t * +rspamd_create_proxy (gint cfd, + gint bfd, + rspamd_mempool_t *pool, + struct event_base *base, + gsize bufsize, + struct timeval *tv, + dispatcher_err_callback_t err_cb, + gpointer ud) { - rspamd_proxy_t *new; + rspamd_proxy_t *new; new = rspamd_mempool_alloc0 (pool, sizeof (rspamd_proxy_t)); @@ -229,11 +271,19 @@ rspamd_create_proxy (gint cfd, gint bfd, rspamd_mempool_t *pool, struct event_ba new->tv = tv; /* Set client's and backend's interfaces to read events */ - event_set (&new->client_ev, new->cfd, EV_READ, rspamd_proxy_client_handler, new); + event_set (&new->client_ev, + new->cfd, + EV_READ, + rspamd_proxy_client_handler, + new); event_base_set (new->base, &new->client_ev); event_add (&new->client_ev, new->tv); - event_set (&new->backend_ev, new->bfd, EV_READ, rspamd_proxy_backend_handler, new); + event_set (&new->backend_ev, + new->bfd, + EV_READ, + rspamd_proxy_backend_handler, + new); event_base_set (new->base, &new->backend_ev); event_add (&new->backend_ev, new->tv); diff --git a/src/libserver/proxy.h b/src/libserver/proxy.h index c505fe83d..784a78dbc 100644 --- a/src/libserver/proxy.h +++ b/src/libserver/proxy.h @@ -34,21 +34,21 @@ */ typedef struct rspamd_proxy_s { - struct event client_ev; /**< event for client's communication */ - struct event backend_ev; /**< event for backend communication */ - struct event_base *base; /**< base for event operations */ - rspamd_mempool_t *pool; /**< memory pool */ - dispatcher_err_callback_t err_cb; /**< error callback */ - struct event_base *ev_base; /**< event base */ - gint cfd; /**< client's socket */ - gint bfd; /**< backend's socket */ - guint8 *buf; /**< exchange buffer */ - gsize bufsize; /**< buffer size */ - gint read_len; /**< read length */ - gint buf_offset; /**< offset to write */ - gpointer user_data; /**< user's data for callbacks */ - struct timeval *tv; /**< timeout for communications */ - gboolean closed; /**< whether descriptors are closed */ + struct event client_ev; /**< event for client's communication */ + struct event backend_ev; /**< event for backend communication */ + struct event_base *base; /**< base for event operations */ + rspamd_mempool_t *pool; /**< memory pool */ + dispatcher_err_callback_t err_cb; /**< error callback */ + struct event_base *ev_base; /**< event base */ + gint cfd; /**< client's socket */ + gint bfd; /**< backend's socket */ + guint8 *buf; /**< exchange buffer */ + gsize bufsize; /**< buffer size */ + gint read_len; /**< read length */ + gint buf_offset; /**< offset to write */ + gpointer user_data; /**< user's data for callbacks */ + struct timeval *tv; /**< timeout for communications */ + gboolean closed; /**< whether descriptors are closed */ } rspamd_proxy_t; /** @@ -60,9 +60,14 @@ typedef struct rspamd_proxy_s { * @param ud user data for callback * @return new proxy object */ -rspamd_proxy_t* rspamd_create_proxy (gint cfd, gint bfd, rspamd_mempool_t *pool, - struct event_base *base, gsize bufsize, struct timeval *tv, - dispatcher_err_callback_t err_cb, gpointer ud); +rspamd_proxy_t * rspamd_create_proxy (gint cfd, + gint bfd, + rspamd_mempool_t *pool, + struct event_base *base, + gsize bufsize, + struct timeval *tv, + dispatcher_err_callback_t err_cb, + gpointer ud); void rspamd_proxy_close (rspamd_proxy_t *proxy); diff --git a/src/libserver/roll_history.c b/src/libserver/roll_history.c index 504f8ae3b..d9553fa93 100644 --- a/src/libserver/roll_history.c +++ b/src/libserver/roll_history.c @@ -33,10 +33,10 @@ * @param pool pool for shared memory * @return new structure */ -struct roll_history* +struct roll_history * rspamd_roll_history_new (rspamd_mempool_t *pool) { - struct roll_history *new; + struct roll_history *new; if (pool == NULL) { return NULL; @@ -57,9 +57,9 @@ struct history_metric_callback_data { static void roll_history_symbols_callback (gpointer key, gpointer value, void *user_data) { - struct history_metric_callback_data *cb = user_data; - struct symbol *s = value; - guint wr; + struct history_metric_callback_data *cb = user_data; + struct symbol *s = value; + guint wr; if (cb->remain > 0) { wr = rspamd_snprintf (cb->pos, cb->remain, "%s, ", s->name); @@ -74,12 +74,13 @@ roll_history_symbols_callback (gpointer key, gpointer value, void *user_data) * @param task task object */ void -rspamd_roll_history_update (struct roll_history *history, struct rspamd_task *task) +rspamd_roll_history_update (struct roll_history *history, + struct rspamd_task *task) { - gint row_num; - struct roll_history_row *row; - struct metric_result *metric_res; - struct history_metric_callback_data cbdata; + gint row_num; + struct roll_history_row *row; + struct metric_result *metric_res; + struct history_metric_callback_data cbdata; if (history->need_lock) { /* Some process is getting history, so wait on a mutex */ @@ -108,10 +109,11 @@ rspamd_roll_history_update (struct roll_history *history, struct rspamd_task *ta /* Add information from task to roll history */ memcpy (&row->from_addr, &task->from_addr, sizeof (row->from_addr)); - memcpy (&row->tv, &task->tv, sizeof (row->tv)); + memcpy (&row->tv, &task->tv, sizeof (row->tv)); /* Strings */ - rspamd_strlcpy (row->message_id, task->message_id, sizeof (row->message_id)); + rspamd_strlcpy (row->message_id, task->message_id, + sizeof (row->message_id)); if (task->user) { rspamd_strlcpy (row->user, task->user, sizeof (row->message_id)); } @@ -120,19 +122,23 @@ rspamd_roll_history_update (struct roll_history *history, struct rspamd_task *ta } /* Get default metric */ - metric_res = g_hash_table_lookup (task->results, DEFAULT_METRIC); + metric_res = g_hash_table_lookup (task->results, DEFAULT_METRIC); if (metric_res == NULL) { row->symbols[0] = '\0'; row->action = METRIC_ACTION_NOACTION; } else { row->score = metric_res->score; - row->required_score = metric_res->metric->actions[METRIC_ACTION_REJECT].score; + row->required_score = + metric_res->metric->actions[METRIC_ACTION_REJECT].score; row->action = check_metric_action (metric_res->score, - metric_res->metric->actions[METRIC_ACTION_REJECT].score, metric_res->metric); + metric_res->metric->actions[METRIC_ACTION_REJECT].score, + metric_res->metric); cbdata.pos = row->symbols; cbdata.remain = sizeof (row->symbols); - g_hash_table_foreach (metric_res->symbols, roll_history_symbols_callback, &cbdata); + g_hash_table_foreach (metric_res->symbols, + roll_history_symbols_callback, + &cbdata); if (cbdata.remain > 0) { /* Remove last whitespace and comma */ *cbdata.pos-- = '\0'; @@ -155,11 +161,12 @@ rspamd_roll_history_update (struct roll_history *history, struct rspamd_task *ta gboolean rspamd_roll_history_load (struct roll_history *history, const gchar *filename) { - gint fd; - struct stat st; + gint fd; + struct stat st; if (stat (filename, &st) == -1) { - msg_info ("cannot load history from %s: %s", filename, strerror (errno)); + msg_info ("cannot load history from %s: %s", filename, + strerror (errno)); return FALSE; } @@ -169,13 +176,15 @@ rspamd_roll_history_load (struct roll_history *history, const gchar *filename) } if ((fd = open (filename, O_RDONLY)) == -1) { - msg_info ("cannot load history from %s: %s", filename, strerror (errno)); + msg_info ("cannot load history from %s: %s", filename, + strerror (errno)); return FALSE; } if (read (fd, history->rows, sizeof (history->rows)) == -1) { close (fd); - msg_info ("cannot read history from %s: %s", filename, strerror (errno)); + msg_info ("cannot read history from %s: %s", filename, + strerror (errno)); return FALSE; } @@ -193,7 +202,7 @@ rspamd_roll_history_load (struct roll_history *history, const gchar *filename) gboolean rspamd_roll_history_save (struct roll_history *history, const gchar *filename) { - gint fd; + gint fd; if ((fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 00600)) == -1) { msg_info ("cannot save history to %s: %s", filename, strerror (errno)); diff --git a/src/libserver/roll_history.h b/src/libserver/roll_history.h index 1dff93a4f..85a8f2ddc 100644 --- a/src/libserver/roll_history.h +++ b/src/libserver/roll_history.h @@ -78,14 +78,15 @@ struct roll_history { * @param pool pool for shared memory * @return new structure */ -struct roll_history* rspamd_roll_history_new (rspamd_mempool_t *pool); +struct roll_history * rspamd_roll_history_new (rspamd_mempool_t *pool); /** * Update roll history with data from task * @param history roll history object * @param task task object */ -void rspamd_roll_history_update (struct roll_history *history, struct rspamd_task *task); +void rspamd_roll_history_update (struct roll_history *history, + struct rspamd_task *task); /** * Load previously saved history from file @@ -93,7 +94,8 @@ void rspamd_roll_history_update (struct roll_history *history, struct rspamd_tas * @param filename filename to load from * @return TRUE if history has been loaded */ -gboolean rspamd_roll_history_load (struct roll_history *history, const gchar *filename); +gboolean rspamd_roll_history_load (struct roll_history *history, + const gchar *filename); /** * Save history to file @@ -101,6 +103,7 @@ gboolean rspamd_roll_history_load (struct roll_history *history, const gchar *fi * @param filename filename to load from * @return TRUE if history has been saved */ -gboolean rspamd_roll_history_save (struct roll_history *history, const gchar *filename); +gboolean rspamd_roll_history_save (struct roll_history *history, + const gchar *filename); #endif /* ROLL_HISTORY_H_ */ diff --git a/src/libserver/spf.c b/src/libserver/spf.c index d7811b4b6..56640cead 100644 --- a/src/libserver/spf.c +++ b/src/libserver/spf.c @@ -79,40 +79,42 @@ struct spf_dns_cb { gboolean in_include; }; -#define CHECK_REC(rec) \ -do { \ - if ((rec)->nested > SPF_MAX_NESTING || \ - (rec)->dns_requests > SPF_MAX_DNS_REQUESTS) { \ - msg_info ("<%s> spf recursion limit %d is reached, domain: %s", \ - (rec)->task->message_id, (rec)->dns_requests, \ - (rec)->sender_domain); \ - return FALSE; \ - } \ -} while (0) \ - -static gboolean parse_spf_record (struct rspamd_task *task, struct spf_record *rec); -static gboolean start_spf_parse (struct spf_record *rec, gchar *begin, guint ttl); +#define CHECK_REC(rec) \ + do { \ + if ((rec)->nested > SPF_MAX_NESTING || \ + (rec)->dns_requests > SPF_MAX_DNS_REQUESTS) { \ + msg_info ("<%s> spf recursion limit %d is reached, domain: %s", \ + (rec)->task->message_id, (rec)->dns_requests, \ + (rec)->sender_domain); \ + return FALSE; \ + } \ + } while (0) \ + +static gboolean parse_spf_record (struct rspamd_task *task, + struct spf_record *rec); +static gboolean start_spf_parse (struct spf_record *rec, gchar *begin, + guint ttl); /* Determine spf mech */ static spf_mech_t check_spf_mech (const gchar *elt, gboolean *need_shift) { g_assert (elt != NULL); - + *need_shift = TRUE; switch (*elt) { - case '-': - return SPF_FAIL; - case '~': - return SPF_SOFT_FAIL; - case '+': - return SPF_PASS; - case '?': - return SPF_NEUTRAL; - default: - *need_shift = FALSE; - return SPF_PASS; + case '-': + return SPF_FAIL; + case '~': + return SPF_SOFT_FAIL; + case '+': + return SPF_PASS; + case '?': + return SPF_NEUTRAL; + default: + *need_shift = FALSE; + return SPF_PASS; } } @@ -120,14 +122,14 @@ check_spf_mech (const gchar *elt, gboolean *need_shift) static void dump_spf_record (GList *addrs) { - struct spf_addr *addr; - GList *cur; - gint r = 0; - gchar logbuf[BUFSIZ], c; + struct spf_addr *addr; + GList *cur; + gint r = 0; + gchar logbuf[BUFSIZ], c; #ifdef HAVE_INET_PTON - gchar ipbuf[INET6_ADDRSTRLEN]; + gchar ipbuf[INET6_ADDRSTRLEN]; #else - struct in_addr ina; + struct in_addr ina; #endif cur = addrs; @@ -149,20 +151,35 @@ dump_spf_record (GList *addrs) } #ifdef HAVE_INET_PTON if (addr->data.normal.ipv6) { - inet_ntop (AF_INET6, &addr->data.normal.d.in6, ipbuf, sizeof (ipbuf)); + inet_ntop (AF_INET6, &addr->data.normal.d.in6, ipbuf, + sizeof (ipbuf)); } else { - inet_ntop (AF_INET, &addr->data.normal.d.in4, ipbuf, sizeof (ipbuf)); + inet_ntop (AF_INET, &addr->data.normal.d.in4, ipbuf, + sizeof (ipbuf)); } - r += snprintf (logbuf + r, sizeof (logbuf) - r, "%c%s/%d; ", c, ipbuf, addr->data.normal.mask); + r += snprintf (logbuf + r, + sizeof (logbuf) - r, + "%c%s/%d; ", + c, + ipbuf, + addr->data.normal.mask); #else ina.s_addr = addr->data.normal.d.in4.s_addr; - r += snprintf (logbuf + r, sizeof (logbuf) - r, "%c%s/%d; ", c, inet_ntoa (ina), addr->data.normal.mask); + r += snprintf (logbuf + r, + sizeof (logbuf) - r, + "%c%s/%d; ", + c, + inet_ntoa (ina), + addr->data.normal.mask); #endif } else { - r += snprintf (logbuf + r, sizeof (logbuf) - r, "%s; ", addr->spf_string); + r += snprintf (logbuf + r, + sizeof (logbuf) - r, + "%s; ", + addr->spf_string); dump_spf_record (addr->data.list); } cur = g_list_next (cur); @@ -174,8 +191,8 @@ dump_spf_record (GList *addrs) static GList * spf_addr_find (GList *addrs, gpointer to_find) { - struct spf_addr *addr; - GList *cur, *res = NULL; + struct spf_addr *addr; + GList *cur, *res = NULL; cur = addrs; while (cur) { @@ -202,9 +219,9 @@ spf_addr_find (GList *addrs, gpointer to_find) static void spf_record_destructor (gpointer r) { - struct spf_record *rec = r; - GList *cur; - struct spf_addr *addr; + struct spf_record *rec = r; + GList *cur; + struct spf_addr *addr; if (rec->addrs) { cur = rec->addrs; @@ -220,87 +237,89 @@ spf_record_destructor (gpointer r) } static gboolean -parse_spf_ipmask (const gchar *begin, struct spf_addr *addr, struct spf_record *rec) +parse_spf_ipmask (const gchar *begin, + struct spf_addr *addr, + struct spf_record *rec) { - const gchar *pos; - gchar mask_buf[5] = {'\0'}, *p; - gint state = 0, dots = 0; + const gchar *pos; + gchar mask_buf[5] = {'\0'}, *p; + gint state = 0, dots = 0; #ifdef HAVE_INET_PTON - gchar ip_buf[INET6_ADDRSTRLEN]; + gchar ip_buf[INET6_ADDRSTRLEN]; #else - gchar ip_buf[INET_ADDRSTRLEN]; + gchar ip_buf[INET_ADDRSTRLEN]; #endif - - bzero (ip_buf, sizeof (ip_buf)); + + bzero (ip_buf, sizeof (ip_buf)); bzero (mask_buf, sizeof (mask_buf)); pos = begin; p = ip_buf; while (*pos) { switch (state) { - case 0: - /* Require ':' */ - if (*pos != ':') { - msg_info ("<%s>: spf error for domain %s: semicolon missing", - rec->task->message_id, rec->sender_domain); - return FALSE; - } - state = 1; - pos ++; - p = ip_buf; - dots = 0; - break; - case 1: + case 0: + /* Require ':' */ + if (*pos != ':') { + msg_info ("<%s>: spf error for domain %s: semicolon missing", + rec->task->message_id, rec->sender_domain); + return FALSE; + } + state = 1; + pos++; + p = ip_buf; + dots = 0; + break; + case 1: #ifdef HAVE_INET_PTON - if (p - ip_buf >= (gint)sizeof (ip_buf)) { - return FALSE; - } - if (g_ascii_isxdigit (*pos)) { - *p ++ = *pos ++; - } - else if (*pos == '.' || *pos == ':') { - *p ++ = *pos ++; - dots ++; - } + if (p - ip_buf >= (gint)sizeof (ip_buf)) { + return FALSE; + } + if (g_ascii_isxdigit (*pos)) { + *p++ = *pos++; + } + else if (*pos == '.' || *pos == ':') { + *p++ = *pos++; + dots++; + } #else - /* Begin parse ip */ - if (p - ip_buf >= (gint)sizeof (ip_buf) || dots > 3) { - return FALSE; - } - if (g_ascii_isdigit (*pos)) { - *p ++ = *pos ++; - } - else if (*pos == '.') { - *p ++ = *pos ++; - dots ++; - } + /* Begin parse ip */ + if (p - ip_buf >= (gint)sizeof (ip_buf) || dots > 3) { + return FALSE; + } + if (g_ascii_isdigit (*pos)) { + *p++ = *pos++; + } + else if (*pos == '.') { + *p++ = *pos++; + dots++; + } #endif - else if (*pos == '/') { - pos ++; - p = mask_buf; - state = 2; - } - else { - /* Invalid character */ - msg_info ("<%s>: spf error for domain %s: invalid ip address", - rec->task->message_id, rec->sender_domain); - return FALSE; - } - break; - case 2: - /* Parse mask */ - if (p - mask_buf >= (gint)sizeof (mask_buf)) { - msg_info ("<%s>: spf error for domain %s: too long mask", - rec->task->message_id, rec->sender_domain); - return FALSE; - } - if (g_ascii_isdigit (*pos)) { - *p ++ = *pos ++; - } - else { - return FALSE; - } - break; + else if (*pos == '/') { + pos++; + p = mask_buf; + state = 2; + } + else { + /* Invalid character */ + msg_info ("<%s>: spf error for domain %s: invalid ip address", + rec->task->message_id, rec->sender_domain); + return FALSE; + } + break; + case 2: + /* Parse mask */ + if (p - mask_buf >= (gint)sizeof (mask_buf)) { + msg_info ("<%s>: spf error for domain %s: too long mask", + rec->task->message_id, rec->sender_domain); + return FALSE; + } + if (g_ascii_isdigit (*pos)) { + *p++ = *pos++; + } + else { + return FALSE; + } + break; } } @@ -311,7 +330,7 @@ parse_spf_ipmask (const gchar *begin, struct spf_addr *addr, struct spf_record * } else { msg_info ("<%s>: spf error for domain %s: invalid ip address", - rec->task->message_id, rec->sender_domain); + rec->task->message_id, rec->sender_domain); return FALSE; } } @@ -328,16 +347,22 @@ parse_spf_ipmask (const gchar *begin, struct spf_addr *addr, struct spf_record * if (!addr->data.normal.ipv6) { addr->data.normal.mask = strtoul (mask_buf, NULL, 10); if (addr->data.normal.mask > 32) { - msg_info ("<%s>: spf error for domain %s: bad ipmask value: '%s'", - rec->task->message_id, rec->sender_domain, begin); + msg_info ( + "<%s>: spf error for domain %s: bad ipmask value: '%s'", + rec->task->message_id, + rec->sender_domain, + begin); return FALSE; } } else { addr->data.normal.mask = strtoul (mask_buf, NULL, 10); if (addr->data.normal.mask > 128) { - msg_info ("<%s>: spf error for domain %s: bad ipmask value: '%s'", - rec->task->message_id, rec->sender_domain, begin); + msg_info ( + "<%s>: spf error for domain %s: bad ipmask value: '%s'", + rec->task->message_id, + rec->sender_domain, + begin); return FALSE; } } @@ -351,10 +376,13 @@ parse_spf_ipmask (const gchar *begin, struct spf_addr *addr, struct spf_record * } static gchar * -parse_spf_hostmask (struct rspamd_task *task, const gchar *begin, struct spf_addr *addr, struct spf_record *rec) +parse_spf_hostmask (struct rspamd_task *task, + const gchar *begin, + struct spf_addr *addr, + struct spf_record *rec) { - gchar *host = NULL, *p, mask_buf[3]; - gint hostlen; + gchar *host = NULL, *p, mask_buf[3]; + gint hostlen; bzero (mask_buf, sizeof (mask_buf)); if (*begin == '\0' || *begin == '/') { @@ -368,7 +396,7 @@ parse_spf_hostmask (struct rspamd_task *task, const gchar *begin, struct spf_add addr->data.normal.mask = strtoul (mask_buf, NULL, 10); if (addr->data.normal.mask > 32) { msg_info ("<%s>: spf error for domain %s: too long mask", - rec->task->message_id, rec->sender_domain); + rec->task->message_id, rec->sender_domain); return FALSE; } if (host == NULL) { @@ -389,7 +417,7 @@ parse_spf_hostmask (struct rspamd_task *task, const gchar *begin, struct spf_add static void spf_record_process_addr (struct rdns_reply_entry *elt, - struct spf_dns_cb *cb, struct rspamd_task *task) + struct spf_dns_cb *cb, struct rspamd_task *task) { struct spf_addr *addr = cb->addr, *new_addr; GList *tmp = NULL; @@ -408,11 +436,13 @@ spf_record_process_addr (struct rdns_reply_entry *elt, memcpy (new_addr, addr, sizeof (struct spf_addr)); new_addr->data.normal.d.in4.s_addr = elt->content.a.addr.s_addr; new_addr->data.normal.parsed = TRUE; - cb->rec->addrs = g_list_insert_before (cb->rec->addrs, tmp, new_addr); + cb->rec->addrs = g_list_insert_before (cb->rec->addrs, + tmp, + new_addr); } else { msg_info ("<%s>: spf error for domain %s: addresses mismatch", - task->message_id, cb->rec->sender_domain); + task->message_id, cb->rec->sender_domain); } } @@ -420,7 +450,7 @@ spf_record_process_addr (struct rdns_reply_entry *elt, else if (elt->type == RDNS_REQUEST_AAAA) { if (!addr->data.normal.parsed) { memcpy (&addr->data.normal.d.in6, - &elt->content.aaa.addr, sizeof (struct in6_addr)); + &elt->content.aaa.addr, sizeof (struct in6_addr)); addr->data.normal.mask = 32; addr->data.normal.parsed = TRUE; addr->data.normal.ipv6 = TRUE; @@ -429,17 +459,21 @@ spf_record_process_addr (struct rdns_reply_entry *elt, /* Insert one more address */ tmp = spf_addr_find (cb->rec->addrs, addr); if (tmp) { - new_addr = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_addr)); + new_addr = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct spf_addr)); memcpy (new_addr, addr, sizeof (struct spf_addr)); memcpy (&new_addr->data.normal.d.in6, - &elt->content.aaa.addr, sizeof (struct in6_addr)); + &elt->content.aaa.addr, sizeof (struct in6_addr)); new_addr->data.normal.parsed = TRUE; new_addr->data.normal.ipv6 = TRUE; - cb->rec->addrs = g_list_insert_before (cb->rec->addrs, tmp, new_addr); + cb->rec->addrs = g_list_insert_before (cb->rec->addrs, + tmp, + new_addr); } else { msg_info ("<%s>: spf error for domain %s: addresses mismatch", - task->message_id, cb->rec->sender_domain); + task->message_id, cb->rec->sender_domain); } } } @@ -448,34 +482,37 @@ spf_record_process_addr (struct rdns_reply_entry *elt, static void spf_record_dns_callback (struct rdns_reply *reply, gpointer arg) { - struct spf_dns_cb *cb = arg; - gchar *begin; - struct rdns_reply_entry *elt_data; - GList *tmp = NULL; - struct rspamd_task *task; + struct spf_dns_cb *cb = arg; + gchar *begin; + struct rdns_reply_entry *elt_data; + GList *tmp = NULL; + struct rspamd_task *task; task = cb->rec->task; - cb->rec->requests_inflight --; + cb->rec->requests_inflight--; if (reply->code == RDNS_RC_NOERROR) { /* Add all logic for all DNS states here */ - LL_FOREACH (reply->entries, elt_data) { + LL_FOREACH (reply->entries, elt_data) + { switch (cb->cur_action) { case SPF_RESOLVE_MX: if (elt_data->type == RDNS_REQUEST_MX) { /* Now resolve A record for this MX */ - if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_A, - elt_data->content.mx.name)) { - task->dns_requests ++; - cb->rec->requests_inflight ++; + if (make_dns_request (task->resolver, task->s, + task->task_pool, + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_A, + elt_data->content.mx.name)) { + task->dns_requests++; + cb->rec->requests_inflight++; } - if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_AAAA, - elt_data->content.mx.name)) { - task->dns_requests ++; - cb->rec->requests_inflight ++; + if (make_dns_request (task->resolver, task->s, + task->task_pool, + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_AAAA, + elt_data->content.mx.name)) { + task->dns_requests++; + cb->rec->requests_inflight++; } } else { @@ -488,17 +525,19 @@ spf_record_dns_callback (struct rdns_reply *reply, gpointer arg) break; case SPF_RESOLVE_PTR: if (elt_data->type == RDNS_REQUEST_PTR) { - if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_A, - elt_data->content.ptr.name)) { - task->dns_requests ++; - cb->rec->requests_inflight ++; + if (make_dns_request (task->resolver, task->s, + task->task_pool, + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_A, + elt_data->content.ptr.name)) { + task->dns_requests++; + cb->rec->requests_inflight++; } - if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_AAAA, - elt_data->content.ptr.name)) { - task->dns_requests ++; - cb->rec->requests_inflight ++; + if (make_dns_request (task->resolver, task->s, + task->task_pool, + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_AAAA, + elt_data->content.ptr.name)) { + task->dns_requests++; + cb->rec->requests_inflight++; } } else { @@ -543,7 +582,8 @@ spf_record_dns_callback (struct rdns_reply *reply, gpointer arg) case SPF_RESOLVE_EXP: break; case SPF_RESOLVE_EXISTS: - if (elt_data->type == RDNS_REQUEST_A || elt_data->type == RDNS_REQUEST_AAAA) { + if (elt_data->type == RDNS_REQUEST_A || elt_data->type == + RDNS_REQUEST_AAAA) { /* If specified address resolves, we can accept connection from every IP */ cb->addr->data.normal.d.in4.s_addr = INADDR_NONE; cb->addr->data.normal.mask = 0; @@ -554,50 +594,63 @@ spf_record_dns_callback (struct rdns_reply *reply, gpointer arg) } else if (reply->code == RDNS_RC_NXDOMAIN) { switch (cb->cur_action) { - case SPF_RESOLVE_MX: - if (rdns_request_has_type (reply->request, RDNS_REQUEST_MX)) { - msg_info ("<%s>: spf error for domain %s: cannot find MX record for %s", - task->message_id, cb->rec->sender_domain, cb->rec->cur_domain); - cb->addr->data.normal.d.in4.s_addr = INADDR_NONE; - cb->addr->data.normal.mask = 32; - } - else { - msg_info ("<%s>: spf error for domain %s: cannot resolve MX record for %s", - task->message_id, cb->rec->sender_domain, cb->rec->cur_domain); - cb->addr->data.normal.d.in4.s_addr = INADDR_NONE; - cb->addr->data.normal.mask = 32; - } - break; - case SPF_RESOLVE_A: - if (rdns_request_has_type (reply->request, RDNS_REQUEST_A)) { - cb->addr->data.normal.d.in4.s_addr = INADDR_NONE; - cb->addr->data.normal.mask = 32; - } - break; + case SPF_RESOLVE_MX: + if (rdns_request_has_type (reply->request, RDNS_REQUEST_MX)) { + msg_info ( + "<%s>: spf error for domain %s: cannot find MX record for %s", + task->message_id, + cb->rec->sender_domain, + cb->rec->cur_domain); + cb->addr->data.normal.d.in4.s_addr = INADDR_NONE; + cb->addr->data.normal.mask = 32; + } + else { + msg_info ( + "<%s>: spf error for domain %s: cannot resolve MX record for %s", + task->message_id, + cb->rec->sender_domain, + cb->rec->cur_domain); + cb->addr->data.normal.d.in4.s_addr = INADDR_NONE; + cb->addr->data.normal.mask = 32; + } + break; + case SPF_RESOLVE_A: + if (rdns_request_has_type (reply->request, RDNS_REQUEST_A)) { + cb->addr->data.normal.d.in4.s_addr = INADDR_NONE; + cb->addr->data.normal.mask = 32; + } + break; #ifdef HAVE_INET_PTON - case SPF_RESOLVE_AAA: - if (rdns_request_has_type (reply->request, RDNS_REQUEST_AAAA)) { - memset (&cb->addr->data.normal.d.in6, 0xff, sizeof (struct in6_addr)); - cb->addr->data.normal.mask = 32; - } - break; + case SPF_RESOLVE_AAA: + if (rdns_request_has_type (reply->request, RDNS_REQUEST_AAAA)) { + memset (&cb->addr->data.normal.d.in6, 0xff, + sizeof (struct in6_addr)); + cb->addr->data.normal.mask = 32; + } + break; #endif - case SPF_RESOLVE_PTR: - break; - case SPF_RESOLVE_REDIRECT: - msg_info ("<%s>: spf error for domain %s: cannot resolve TXT record for %s", - task->message_id, cb->rec->sender_domain, cb->rec->cur_domain); - break; - case SPF_RESOLVE_INCLUDE: - msg_info ("<%s>: spf error for domain %s: cannot resolve TXT record for %s", - task->message_id, cb->rec->sender_domain, cb->rec->cur_domain); - break; - case SPF_RESOLVE_EXP: - break; - case SPF_RESOLVE_EXISTS: - cb->addr->data.normal.d.in4.s_addr = INADDR_NONE; - cb->addr->data.normal.mask = 32; - break; + case SPF_RESOLVE_PTR: + break; + case SPF_RESOLVE_REDIRECT: + msg_info ( + "<%s>: spf error for domain %s: cannot resolve TXT record for %s", + task->message_id, + cb->rec->sender_domain, + cb->rec->cur_domain); + break; + case SPF_RESOLVE_INCLUDE: + msg_info ( + "<%s>: spf error for domain %s: cannot resolve TXT record for %s", + task->message_id, + cb->rec->sender_domain, + cb->rec->cur_domain); + break; + case SPF_RESOLVE_EXP: + break; + case SPF_RESOLVE_EXISTS: + cb->addr->data.normal.d.in4.s_addr = INADDR_NONE; + cb->addr->data.normal.mask = 32; + break; } } @@ -607,13 +660,16 @@ spf_record_dns_callback (struct rdns_reply *reply, gpointer arg) } static gboolean -parse_spf_a (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_a (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { struct spf_dns_cb *cb; - gchar *host = NULL; - + gchar *host = NULL; + CHECK_REC (rec); - + /* * a * a/<prefix-length> @@ -629,31 +685,31 @@ parse_spf_a (struct rspamd_task *task, const gchar *begin, struct spf_record *re addr->data.normal.mask = 32; } else if (*begin == ':') { - begin ++; + begin++; } else if (*begin != '/') { /* Invalid A record */ return FALSE; } - + if (host == NULL) { host = parse_spf_hostmask (task, begin, addr, rec); } - + if (host == NULL) { return FALSE; } - rec->dns_requests ++; + rec->dns_requests++; cb = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_dns_cb)); cb->rec = rec; cb->addr = addr; cb->cur_action = SPF_RESOLVE_A; cb->in_include = rec->in_include; if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_A, host)) { - task->dns_requests ++; - rec->requests_inflight ++; + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_A, host)) { + task->dns_requests++; + rec->requests_inflight++; return TRUE; } @@ -662,10 +718,13 @@ parse_spf_a (struct rspamd_task *task, const gchar *begin, struct spf_record *re } static gboolean -parse_spf_ptr (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_ptr (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { struct spf_dns_cb *cb; - gchar *host, *ptr; + gchar *host, *ptr; CHECK_REC (rec); @@ -673,7 +732,7 @@ parse_spf_ptr (struct rspamd_task *task, const gchar *begin, struct spf_record * return FALSE; } if (*begin == ':') { - begin ++; + begin++; host = rspamd_mempool_strdup (task->task_pool, begin); } else if (*begin == '\0') { @@ -683,7 +742,7 @@ parse_spf_ptr (struct rspamd_task *task, const gchar *begin, struct spf_record * return FALSE; } - rec->dns_requests ++; + rec->dns_requests++; cb = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_dns_cb)); cb->rec = rec; cb->addr = addr; @@ -691,15 +750,17 @@ parse_spf_ptr (struct rspamd_task *task, const gchar *begin, struct spf_record * cb->cur_action = SPF_RESOLVE_PTR; cb->in_include = rec->in_include; cb->ptr_host = host; - ptr = rdns_generate_ptr_from_str (rspamd_inet_address_to_string (&task->from_addr)); + ptr = + rdns_generate_ptr_from_str (rspamd_inet_address_to_string ( + &task->from_addr)); if (ptr == NULL) { return FALSE; } rspamd_mempool_add_destructor (task->task_pool, free, ptr); if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_PTR, ptr)) { - task->dns_requests ++; - rec->requests_inflight ++; + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_PTR, ptr)) { + task->dns_requests++; + rec->requests_inflight++; return TRUE; } @@ -709,26 +770,29 @@ parse_spf_ptr (struct rspamd_task *task, const gchar *begin, struct spf_record * } static gboolean -parse_spf_mx (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_mx (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { struct spf_dns_cb *cb; - gchar *host; - + gchar *host; + CHECK_REC (rec); - + if (begin == NULL) { return FALSE; } if (*begin == ':') { - begin ++; + begin++; } - + host = parse_spf_hostmask (task, begin, addr, rec); - + if (host == NULL) { return FALSE; } - rec->dns_requests ++; + rec->dns_requests++; cb = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_dns_cb)); cb->rec = rec; cb->addr = addr; @@ -736,10 +800,10 @@ parse_spf_mx (struct rspamd_task *task, const gchar *begin, struct spf_record *r cb->cur_action = SPF_RESOLVE_MX; cb->in_include = rec->in_include; if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_MX, host)) { - task->dns_requests ++; - rec->requests_inflight ++; - + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_MX, host)) { + task->dns_requests++; + rec->requests_inflight++; + return TRUE; } @@ -747,7 +811,10 @@ parse_spf_mx (struct rspamd_task *task, const gchar *begin, struct spf_record *r } static gboolean -parse_spf_all (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_all (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { /* All is 0/0 */ memset (&addr->data.normal.d, 0, sizeof (addr->data.normal.d)); @@ -764,7 +831,10 @@ parse_spf_all (struct rspamd_task *task, const gchar *begin, struct spf_record * } static gboolean -parse_spf_ip4 (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_ip4 (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { /* ip4:addr[/mask] */ @@ -774,7 +844,10 @@ parse_spf_ip4 (struct rspamd_task *task, const gchar *begin, struct spf_record * #ifdef HAVE_INET_PTON static gboolean -parse_spf_ip6 (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_ip6 (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { /* ip6:addr[/mask] */ @@ -784,18 +857,21 @@ parse_spf_ip6 (struct rspamd_task *task, const gchar *begin, struct spf_record * #endif static gboolean -parse_spf_include (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_include (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { struct spf_dns_cb *cb; - gchar *domain; + gchar *domain; CHECK_REC (rec); if (begin == NULL || *begin != ':') { return FALSE; } - begin ++; - rec->dns_requests ++; + begin++; + rec->dns_requests++; cb = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_dns_cb)); cb->rec = rec; @@ -806,9 +882,9 @@ parse_spf_include (struct rspamd_task *task, const gchar *begin, struct spf_reco addr->data.list = NULL; domain = rspamd_mempool_strdup (task->task_pool, begin); if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_TXT, domain)) { - task->dns_requests ++; - rec->requests_inflight ++; + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_TXT, domain)) { + task->dns_requests++; + rec->requests_inflight++; return TRUE; } @@ -818,7 +894,10 @@ parse_spf_include (struct rspamd_task *task, const gchar *begin, struct spf_reco } static gboolean -parse_spf_exp (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_exp (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { CHECK_REC (rec); @@ -827,18 +906,21 @@ parse_spf_exp (struct rspamd_task *task, const gchar *begin, struct spf_record * } static gboolean -parse_spf_redirect (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_redirect (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { struct spf_dns_cb *cb; - gchar *domain; + gchar *domain; CHECK_REC (rec); if (begin == NULL || *begin != '=') { return FALSE; } - begin ++; - rec->dns_requests ++; + begin++; + rec->dns_requests++; cb = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_dns_cb)); cb->rec = rec; @@ -847,10 +929,10 @@ parse_spf_redirect (struct rspamd_task *task, const gchar *begin, struct spf_rec cb->in_include = rec->in_include; domain = rspamd_mempool_strdup (task->task_pool, begin); if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_TXT, domain)) { - task->dns_requests ++; - rec->requests_inflight ++; - + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_TXT, domain)) { + task->dns_requests++; + rec->requests_inflight++; + return TRUE; } @@ -858,18 +940,21 @@ parse_spf_redirect (struct rspamd_task *task, const gchar *begin, struct spf_rec } static gboolean -parse_spf_exists (struct rspamd_task *task, const gchar *begin, struct spf_record *rec, struct spf_addr *addr) +parse_spf_exists (struct rspamd_task *task, + const gchar *begin, + struct spf_record *rec, + struct spf_addr *addr) { struct spf_dns_cb *cb; - gchar *host; + gchar *host; CHECK_REC (rec); - + if (begin == NULL || *begin != ':') { return FALSE; } - begin ++; - rec->dns_requests ++; + begin++; + rec->dns_requests++; addr->data.normal.mask = 32; cb = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_dns_cb)); @@ -880,10 +965,10 @@ parse_spf_exists (struct rspamd_task *task, const gchar *begin, struct spf_recor host = rspamd_mempool_strdup (task->task_pool, begin); if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_record_dns_callback, (void *)cb, RDNS_REQUEST_A, host)) { - task->dns_requests ++; - rec->requests_inflight ++; - + spf_record_dns_callback, (void *)cb, RDNS_REQUEST_A, host)) { + task->dns_requests++; + rec->requests_inflight++; + return TRUE; } @@ -893,8 +978,8 @@ parse_spf_exists (struct rspamd_task *task, const gchar *begin, struct spf_recor static void reverse_spf_ip (gchar *ip, gint len) { - gchar ipbuf[sizeof("255.255.255.255") - 1], *p, *c; - gint t = 0, l = len; + gchar ipbuf[sizeof("255.255.255.255") - 1], *p, *c; + gint t = 0, l = len; if (len > (gint)sizeof (ipbuf)) { msg_info ("cannot reverse string of length %d", len); @@ -902,127 +987,136 @@ reverse_spf_ip (gchar *ip, gint len) } p = ipbuf + len; - c = ip; - while (-- l) { + c = ip; + while (--l) { if (*c == '.') { memcpy (p, c - t, t); *--p = '.'; - c ++; + c++; t = 0; continue; } - t ++; - c ++; - p --; + t++; + c++; + p--; } memcpy (p - 1, c - t, t + 1); - memcpy (ip, ipbuf, len); + memcpy (ip, ipbuf, len); } static gchar * -expand_spf_macro (struct rspamd_task *task, struct spf_record *rec, gchar *begin) +expand_spf_macro (struct rspamd_task *task, struct spf_record *rec, + gchar *begin) { - gchar *p, *c, *new, *tmp; - gint len = 0, slen = 0, state = 0; + gchar *p, *c, *new, *tmp; + gint len = 0, slen = 0, state = 0; #ifdef HAVE_INET_PTON - gchar ip_buf[INET6_ADDRSTRLEN]; + gchar ip_buf[INET6_ADDRSTRLEN]; #endif - gboolean need_expand = FALSE; + gboolean need_expand = FALSE; p = begin; /* Calculate length */ while (*p) { switch (state) { - case 0: - /* Skip any character and wait for % in input */ - if (*p == '%') { - state = 1; - } - else { - len ++; - } + case 0: + /* Skip any character and wait for % in input */ + if (*p == '%') { + state = 1; + } + else { + len++; + } - slen ++; - p ++; - break; - case 1: - /* We got % sign, so we should whether wait for { or for - or for _ or for % */ - if (*p == '%' || *p == '-') { - /* Just a single % sign or space */ - len ++; - } - else if (*p == '_') { - /* %20 */ - len += sizeof ("%20") - 1; - } - else if (*p == '{') { - state = 2; - } - else { - /* Something unknown */ - msg_info ("<%s>: spf error for domain %s: unknown spf element", - task->message_id, rec->sender_domain); - return begin; - } - p ++; - slen ++; - break; - case 2: - /* Read macro name */ - switch (g_ascii_tolower (*p)) { - case 'i': + slen++; + p++; + break; + case 1: + /* We got % sign, so we should whether wait for { or for - or for _ or for % */ + if (*p == '%' || *p == '-') { + /* Just a single % sign or space */ + len++; + } + else if (*p == '_') { + /* %20 */ + len += sizeof ("%20") - 1; + } + else if (*p == '{') { + state = 2; + } + else { + /* Something unknown */ + msg_info ("<%s>: spf error for domain %s: unknown spf element", + task->message_id, rec->sender_domain); + return begin; + } + p++; + slen++; + break; + case 2: + /* Read macro name */ + switch (g_ascii_tolower (*p)) { + case 'i': #ifdef HAVE_INET_PTON - len += sizeof (INET6_ADDRSTRLEN) - 1; + len += sizeof (INET6_ADDRSTRLEN) - 1; #else - len += sizeof (INET_ADDRSTRLEN) - 1; + len += sizeof (INET_ADDRSTRLEN) - 1; #endif - break; - case 's': - len += strlen (rec->sender); - break; - case 'l': - len += strlen (rec->local_part); - break; - case 'o': - len += strlen (rec->sender_domain); - break; - case 'd': - len += strlen (rec->cur_domain); - break; - case 'v': - len += sizeof ("in-addr") - 1; - break; - case 'h': - if (task->helo) { - len += strlen (task->helo); - } - break; - default: - msg_info ("<%s>: spf error for domain %s: unknown or unsupported spf macro %c in %s", - task->message_id, rec->sender_domain, *p, begin); - return begin; - } - p ++; - slen ++; - state = 3; break; - case 3: - /* Read modifier */ - if (*p == '}') { - state = 0; - need_expand = TRUE; + case 's': + len += strlen (rec->sender); + break; + case 'l': + len += strlen (rec->local_part); + break; + case 'o': + len += strlen (rec->sender_domain); + break; + case 'd': + len += strlen (rec->cur_domain); + break; + case 'v': + len += sizeof ("in-addr") - 1; + break; + case 'h': + if (task->helo) { + len += strlen (task->helo); } - else if (*p != 'r' && !g_ascii_isdigit (*p)) { - msg_info ("<%s>: spf error for domain %s: unknown or unsupported spf modifier %c in %s", - task->message_id, rec->sender_domain, *p, begin); - return begin; - } - p ++; - slen ++; break; + default: + msg_info ( + "<%s>: spf error for domain %s: unknown or unsupported spf macro %c in %s", + task->message_id, + rec->sender_domain, + *p, + begin); + return begin; + } + p++; + slen++; + state = 3; + break; + case 3: + /* Read modifier */ + if (*p == '}') { + state = 0; + need_expand = TRUE; + } + else if (*p != 'r' && !g_ascii_isdigit (*p)) { + msg_info ( + "<%s>: spf error for domain %s: unknown or unsupported spf modifier %c in %s", + task->message_id, + rec->sender_domain, + *p, + begin); + return begin; + } + p++; + slen++; + break; } } @@ -1030,7 +1124,7 @@ expand_spf_macro (struct rspamd_task *task, struct spf_record *rec, gchar *begin /* No expansion needed */ return begin; } - + new = rspamd_mempool_alloc (task->task_pool, len + 1); c = new; @@ -1040,138 +1134,146 @@ expand_spf_macro (struct rspamd_task *task, struct spf_record *rec, gchar *begin while (*p) { switch (state) { - case 0: - /* Skip any character and wait for % in input */ - if (*p == '%') { - state = 1; - } - else { - *c = *p; - c ++; - } + case 0: + /* Skip any character and wait for % in input */ + if (*p == '%') { + state = 1; + } + else { + *c = *p; + c++; + } - p ++; - break; - case 1: - /* We got % sign, so we should whether wait for { or for - or for _ or for % */ - if (*p == '%') { - /* Just a single % sign or space */ - *c++ = '%'; - } - else if (*p == '-') { - *c++ = ' '; - } - else if (*p == '_') { - /* %20 */ - *c++ = '%'; - *c++ = '2'; - *c++ = '0'; - } - else if (*p == '{') { - state = 2; - } - else { - /* Something unknown */ - msg_info ("<%s>: spf error for domain %s: unknown spf element", - task->message_id, rec->sender_domain); - return begin; - } - p ++; - break; - case 2: - /* Read macro name */ - switch (g_ascii_tolower (*p)) { - case 'i': + p++; + break; + case 1: + /* We got % sign, so we should whether wait for { or for - or for _ or for % */ + if (*p == '%') { + /* Just a single % sign or space */ + *c++ = '%'; + } + else if (*p == '-') { + *c++ = ' '; + } + else if (*p == '_') { + /* %20 */ + *c++ = '%'; + *c++ = '2'; + *c++ = '0'; + } + else if (*p == '{') { + state = 2; + } + else { + /* Something unknown */ + msg_info ("<%s>: spf error for domain %s: unknown spf element", + task->message_id, rec->sender_domain); + return begin; + } + p++; + break; + case 2: + /* Read macro name */ + switch (g_ascii_tolower (*p)) { + case 'i': #ifdef HAVE_INET_PTON - len = rspamd_strlcpy (ip_buf, - rspamd_inet_address_to_string (&task->from_addr), - sizeof (ip_buf)); - memcpy (c, ip_buf, len); + len = rspamd_strlcpy (ip_buf, + rspamd_inet_address_to_string (&task->from_addr), + sizeof (ip_buf)); + memcpy (c, ip_buf, len); #else - tmp = inet_ntoa (task->from_addr); - len = strlen (tmp); - memcpy (c, tmp, len); + tmp = inet_ntoa (task->from_addr); + len = strlen (tmp); + memcpy (c, tmp, len); #endif - c += len; - break; - case 's': - len = strlen (rec->sender); - memcpy (c, rec->sender, len); - c += len; - break; - case 'l': - len = strlen (rec->local_part); - memcpy (c, rec->local_part, len); - c += len; - break; - case 'o': - len = strlen (rec->sender_domain); - memcpy (c, rec->sender_domain, len); - c += len; - break; - case 'd': - len = strlen (rec->cur_domain); - memcpy (c, rec->cur_domain, len); - c += len; - break; - case 'v': - len = sizeof ("in-addr") - 1; - memcpy (c, "in-addr", len); - c += len; - break; - case 'h': - if (task->helo) { - tmp = strchr (task->helo, '@'); - if (tmp) { - len = strlen (tmp + 1); - memcpy (c, tmp + 1, len); - c += len; - } - } - break; - default: - msg_info ("<%s>: spf error for domain %s: unknown or unsupported spf macro %c in %s", - task->message_id, rec->sender_domain, *p, begin); - return begin; - } - p ++; - state = 3; + c += len; break; - case 3: - /* Read modifier */ - if (*p == '}') { - state = 0; - } - else if (*p == 'r' && len != 0) { - reverse_spf_ip (c - len, len); - len = 0; - } - else if (g_ascii_isdigit (*p)) { - /*XXX: try to implement domain strimming */ + case 's': + len = strlen (rec->sender); + memcpy (c, rec->sender, len); + c += len; + break; + case 'l': + len = strlen (rec->local_part); + memcpy (c, rec->local_part, len); + c += len; + break; + case 'o': + len = strlen (rec->sender_domain); + memcpy (c, rec->sender_domain, len); + c += len; + break; + case 'd': + len = strlen (rec->cur_domain); + memcpy (c, rec->cur_domain, len); + c += len; + break; + case 'v': + len = sizeof ("in-addr") - 1; + memcpy (c, "in-addr", len); + c += len; + break; + case 'h': + if (task->helo) { + tmp = strchr (task->helo, '@'); + if (tmp) { + len = strlen (tmp + 1); + memcpy (c, tmp + 1, len); + c += len; + } } - else { - msg_info ("<%s>: spf error for domain %s: unknown or unsupported spf macro %c in %s", - task->message_id, rec->sender_domain, *p, begin); - return begin; - } - p ++; break; + default: + msg_info ( + "<%s>: spf error for domain %s: unknown or unsupported spf macro %c in %s", + task->message_id, + rec->sender_domain, + *p, + begin); + return begin; + } + p++; + state = 3; + break; + case 3: + /* Read modifier */ + if (*p == '}') { + state = 0; + } + else if (*p == 'r' && len != 0) { + reverse_spf_ip (c - len, len); + len = 0; + } + else if (g_ascii_isdigit (*p)) { + /*XXX: try to implement domain strimming */ + } + else { + msg_info ( + "<%s>: spf error for domain %s: unknown or unsupported spf macro %c in %s", + task->message_id, + rec->sender_domain, + *p, + begin); + return begin; + } + p++; + break; } } /* Null terminate */ *c = '\0'; return new; - + } -#define NEW_ADDR(x) do { \ - (x) = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_addr)); \ - (x)->mech = check_spf_mech (rec->cur_elt, &need_shift); \ - (x)->spf_string = rspamd_mempool_strdup (task->task_pool, begin); \ - memset (&(x)->data.normal, 0, sizeof ((x)->data.normal)); \ - (x)->data.normal.mask = 32; \ - (x)->is_list = FALSE; \ +#define NEW_ADDR(x) do { \ + (x) = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_addr)); \ + (x)->mech = check_spf_mech (rec->cur_elt, &need_shift); \ + (x)->spf_string = rspamd_mempool_strdup (task->task_pool, begin); \ + memset (&(x)->data.normal, 0, sizeof ((x)->data.normal)); \ + (x)->data.normal.mask = 32; \ + (x)->is_list = FALSE; \ } while (0); /* Read current element and try to parse record */ @@ -1180,141 +1282,153 @@ parse_spf_record (struct rspamd_task *task, struct spf_record *rec) { struct spf_addr *new = NULL; gboolean need_shift, res = FALSE; - gchar *begin; - + gchar *begin; + rec->cur_elt = rec->elts[rec->elt_num]; if (rec->cur_elt == NULL) { return FALSE; } else if (*rec->cur_elt == '\0') { /* Silently skip empty elements */ - rec->elt_num ++; + rec->elt_num++; return TRUE; } else { begin = expand_spf_macro (task, rec, rec->cur_elt); if (*begin == '?' || *begin == '+' || *begin == '-' || *begin == '~') { - begin ++; + begin++; } /* Now check what we have */ switch (g_ascii_tolower (*begin)) { - case 'a': - /* all or a */ - if (g_ascii_strncasecmp (begin, SPF_ALL, sizeof (SPF_ALL) - 1) == 0) { - NEW_ADDR (new); - begin += sizeof (SPF_ALL) - 1; - res = parse_spf_all (task, begin, rec, new); - } - else if (g_ascii_strncasecmp (begin, SPF_A, sizeof (SPF_A) - 1) == 0) { - NEW_ADDR (new); - begin += sizeof (SPF_A) - 1; - res = parse_spf_a (task, begin, rec, new); - } - else { - msg_info ("<%s>: spf error for domain %s: bad spf command %s", - task->message_id, rec->sender_domain, begin); - } - break; - case 'i': - /* include or ip4 */ - if (g_ascii_strncasecmp (begin, SPF_IP4, sizeof (SPF_IP4) - 1) == 0) { - NEW_ADDR (new); - begin += sizeof (SPF_IP4) - 1; - res = parse_spf_ip4 (task, begin, rec, new); - } - else if (g_ascii_strncasecmp (begin, SPF_INCLUDE, sizeof (SPF_INCLUDE) - 1) == 0) { - NEW_ADDR (new); - begin += sizeof (SPF_INCLUDE) - 1; - res = parse_spf_include (task, begin, rec, new); - } - else if (g_ascii_strncasecmp (begin, SPF_IP6, sizeof (SPF_IP6) - 1) == 0) { + case 'a': + /* all or a */ + if (g_ascii_strncasecmp (begin, SPF_ALL, + sizeof (SPF_ALL) - 1) == 0) { + NEW_ADDR (new); + begin += sizeof (SPF_ALL) - 1; + res = parse_spf_all (task, begin, rec, new); + } + else if (g_ascii_strncasecmp (begin, SPF_A, + sizeof (SPF_A) - 1) == 0) { + NEW_ADDR (new); + begin += sizeof (SPF_A) - 1; + res = parse_spf_a (task, begin, rec, new); + } + else { + msg_info ("<%s>: spf error for domain %s: bad spf command %s", + task->message_id, rec->sender_domain, begin); + } + break; + case 'i': + /* include or ip4 */ + if (g_ascii_strncasecmp (begin, SPF_IP4, + sizeof (SPF_IP4) - 1) == 0) { + NEW_ADDR (new); + begin += sizeof (SPF_IP4) - 1; + res = parse_spf_ip4 (task, begin, rec, new); + } + else if (g_ascii_strncasecmp (begin, SPF_INCLUDE, + sizeof (SPF_INCLUDE) - 1) == 0) { + NEW_ADDR (new); + begin += sizeof (SPF_INCLUDE) - 1; + res = parse_spf_include (task, begin, rec, new); + } + else if (g_ascii_strncasecmp (begin, SPF_IP6, sizeof (SPF_IP6) - + 1) == 0) { #ifdef HAVE_INET_PTON - NEW_ADDR (new); - begin += sizeof (SPF_IP6) - 1; - res = parse_spf_ip6 (task, begin, rec, new); + NEW_ADDR (new); + begin += sizeof (SPF_IP6) - 1; + res = parse_spf_ip6 (task, begin, rec, new); #else - msg_info ("ignoring ip6 spf command as IPv6 is not supported: %s", begin); - new = NULL; - res = TRUE; - begin += sizeof (SPF_IP6) - 1; + msg_info ( + "ignoring ip6 spf command as IPv6 is not supported: %s", + begin); + new = NULL; + res = TRUE; + begin += sizeof (SPF_IP6) - 1; #endif - } - else { - msg_info ("<%s>: spf error for domain %s: bad spf command %s", - task->message_id, rec->sender_domain, begin); - } - break; - case 'm': - /* mx */ - if (g_ascii_strncasecmp (begin, SPF_MX, sizeof (SPF_MX) - 1) == 0) { - NEW_ADDR (new); - begin += sizeof (SPF_MX) - 1; - res = parse_spf_mx (task, begin, rec, new); - } - else { - msg_info ("<%s>: spf error for domain %s: bad spf command %s", - task->message_id, rec->sender_domain, begin); - } - break; - case 'p': - /* ptr */ - if (g_ascii_strncasecmp (begin, SPF_PTR, sizeof (SPF_PTR) - 1) == 0) { - NEW_ADDR (new); - begin += sizeof (SPF_PTR) - 1; - res = parse_spf_ptr (task, begin, rec, new); - } - else { - msg_info ("<%s>: spf error for domain %s: bad spf command %s", - task->message_id, rec->sender_domain, begin); - } - break; - case 'e': - /* exp or exists */ - if (g_ascii_strncasecmp (begin, SPF_EXP, sizeof (SPF_EXP) - 1) == 0) { - begin += sizeof (SPF_EXP) - 1; - res = parse_spf_exp (task, begin, rec, NULL); - } - else if (g_ascii_strncasecmp (begin, SPF_EXISTS, sizeof (SPF_EXISTS) - 1) == 0) { - NEW_ADDR (new); - begin += sizeof (SPF_EXISTS) - 1; - res = parse_spf_exists (task, begin, rec, new); - } - else { - msg_info ("<%s>: spf error for domain %s: bad spf command %s", - task->message_id, rec->sender_domain, begin); - } - break; - case 'r': - /* redirect */ - if (g_ascii_strncasecmp (begin, SPF_REDIRECT, sizeof (SPF_REDIRECT) - 1) == 0) { - begin += sizeof (SPF_REDIRECT) - 1; - res = parse_spf_redirect (task, begin, rec, NULL); - } - else { - msg_info ("<%s>: spf error for domain %s: bad spf command %s", - task->message_id, rec->sender_domain, begin); - } - break; - case 'v': - if (g_ascii_strncasecmp (begin, "v=spf", sizeof ("v=spf") - 1) == 0) { - /* Skip this element till the end of record */ - while (*begin && !g_ascii_isspace (*begin)) { - begin ++; - } - } - break; - default: + } + else { msg_info ("<%s>: spf error for domain %s: bad spf command %s", - task->message_id, rec->sender_domain, begin); - break; + task->message_id, rec->sender_domain, begin); + } + break; + case 'm': + /* mx */ + if (g_ascii_strncasecmp (begin, SPF_MX, sizeof (SPF_MX) - 1) == 0) { + NEW_ADDR (new); + begin += sizeof (SPF_MX) - 1; + res = parse_spf_mx (task, begin, rec, new); + } + else { + msg_info ("<%s>: spf error for domain %s: bad spf command %s", + task->message_id, rec->sender_domain, begin); + } + break; + case 'p': + /* ptr */ + if (g_ascii_strncasecmp (begin, SPF_PTR, + sizeof (SPF_PTR) - 1) == 0) { + NEW_ADDR (new); + begin += sizeof (SPF_PTR) - 1; + res = parse_spf_ptr (task, begin, rec, new); + } + else { + msg_info ("<%s>: spf error for domain %s: bad spf command %s", + task->message_id, rec->sender_domain, begin); + } + break; + case 'e': + /* exp or exists */ + if (g_ascii_strncasecmp (begin, SPF_EXP, + sizeof (SPF_EXP) - 1) == 0) { + begin += sizeof (SPF_EXP) - 1; + res = parse_spf_exp (task, begin, rec, NULL); + } + else if (g_ascii_strncasecmp (begin, SPF_EXISTS, + sizeof (SPF_EXISTS) - 1) == 0) { + NEW_ADDR (new); + begin += sizeof (SPF_EXISTS) - 1; + res = parse_spf_exists (task, begin, rec, new); + } + else { + msg_info ("<%s>: spf error for domain %s: bad spf command %s", + task->message_id, rec->sender_domain, begin); + } + break; + case 'r': + /* redirect */ + if (g_ascii_strncasecmp (begin, SPF_REDIRECT, + sizeof (SPF_REDIRECT) - 1) == 0) { + begin += sizeof (SPF_REDIRECT) - 1; + res = parse_spf_redirect (task, begin, rec, NULL); + } + else { + msg_info ("<%s>: spf error for domain %s: bad spf command %s", + task->message_id, rec->sender_domain, begin); + } + break; + case 'v': + if (g_ascii_strncasecmp (begin, "v=spf", + sizeof ("v=spf") - 1) == 0) { + /* Skip this element till the end of record */ + while (*begin && !g_ascii_isspace (*begin)) { + begin++; + } + } + break; + default: + msg_info ("<%s>: spf error for domain %s: bad spf command %s", + task->message_id, rec->sender_domain, begin); + break; } if (res) { if (new != NULL) { rec->addrs = g_list_prepend (rec->addrs, new); } - rec->elt_num ++; + rec->elt_num++; } } @@ -1325,14 +1439,16 @@ parse_spf_record (struct rspamd_task *task, struct spf_record *rec) static void parse_spf_scopes (struct spf_record *rec, gchar **begin) { - for (;;) { - if (g_ascii_strncasecmp (*begin, SPF_SCOPE_PRA, sizeof (SPF_SCOPE_PRA) - 1) == 0) { + for (;; ) { + if (g_ascii_strncasecmp (*begin, SPF_SCOPE_PRA, sizeof (SPF_SCOPE_PRA) - + 1) == 0) { *begin += sizeof (SPF_SCOPE_PRA) - 1; /* XXX: Implement actual PRA check */ /* extract_pra_info (rec); */ continue; } - else if (g_ascii_strncasecmp (*begin, SPF_SCOPE_MFROM, sizeof (SPF_SCOPE_MFROM) - 1) == 0) { + else if (g_ascii_strncasecmp (*begin, SPF_SCOPE_MFROM, + sizeof (SPF_SCOPE_MFROM) - 1) == 0) { /* mfrom is standart spf1 check */ *begin += sizeof (SPF_SCOPE_MFROM) - 1; continue; @@ -1340,7 +1456,7 @@ parse_spf_scopes (struct spf_record *rec, gchar **begin) else if (**begin != ',') { break; } - (*begin) ++; + (*begin)++; } } @@ -1349,47 +1465,51 @@ start_spf_parse (struct spf_record *rec, gchar *begin, guint ttl) { /* Skip spaces */ while (g_ascii_isspace (*begin)) { - begin ++; + begin++; } - if (g_ascii_strncasecmp (begin, SPF_VER1_STR, sizeof (SPF_VER1_STR) - 1) == 0) { + if (g_ascii_strncasecmp (begin, SPF_VER1_STR, + sizeof (SPF_VER1_STR) - 1) == 0) { begin += sizeof (SPF_VER1_STR) - 1; while (g_ascii_isspace (*begin) && *begin) { - begin ++; + begin++; } rec->elts = g_strsplit_set (begin, " ", 0); rec->elt_num = 0; if (rec->elts) { - rspamd_mempool_add_destructor (rec->task->task_pool, (rspamd_mempool_destruct_t)g_strfreev, rec->elts); + rspamd_mempool_add_destructor (rec->task->task_pool, + (rspamd_mempool_destruct_t)g_strfreev, rec->elts); rec->cur_elt = rec->elts[0]; - while (parse_spf_record (rec->task, rec)); + while (parse_spf_record (rec->task, rec)) ; if (ttl != 0) { rec->ttl = ttl; } return TRUE; } } - else if (g_ascii_strncasecmp (begin, SPF_VER2_STR, sizeof (SPF_VER2_STR) - 1) == 0) { + else if (g_ascii_strncasecmp (begin, SPF_VER2_STR, sizeof (SPF_VER2_STR) - + 1) == 0) { /* Skip one number of record, so no we are here spf2.0/ */ begin += sizeof (SPF_VER2_STR); if (*begin != '/') { msg_info ("<%s>: spf error for domain %s: sender id is invalid", - rec->task->message_id, rec->sender_domain); + rec->task->message_id, rec->sender_domain); } else { - begin ++; + begin++; parse_spf_scopes (rec, &begin); } /* Now common spf record */ while (g_ascii_isspace (*begin) && *begin) { - begin ++; + begin++; } rec->elts = g_strsplit_set (begin, " ", 0); rec->elt_num = 0; if (rec->elts) { - rspamd_mempool_add_destructor (rec->task->task_pool, (rspamd_mempool_destruct_t)g_strfreev, rec->elts); + rspamd_mempool_add_destructor (rec->task->task_pool, + (rspamd_mempool_destruct_t)g_strfreev, rec->elts); rec->cur_elt = rec->elts[0]; - while (parse_spf_record (rec->task, rec)); + while (parse_spf_record (rec->task, rec)) ; if (ttl != 0) { rec->ttl = ttl; } @@ -1398,7 +1518,10 @@ start_spf_parse (struct spf_record *rec, gchar *begin, guint ttl) } else { msg_debug ("<%s>: spf error for domain %s: bad spf record version: %*s", - rec->task->message_id, rec->sender_domain, sizeof (SPF_VER1_STR) - 1, begin); + rec->task->message_id, + rec->sender_domain, + sizeof (SPF_VER1_STR) - 1, + begin); } return FALSE; } @@ -1409,9 +1532,10 @@ spf_dns_callback (struct rdns_reply *reply, gpointer arg) struct spf_record *rec = arg; struct rdns_reply_entry *elt; - rec->requests_inflight --; + rec->requests_inflight--; if (reply->code == RDNS_RC_NOERROR) { - LL_FOREACH (reply->entries, elt) { + LL_FOREACH (reply->entries, elt) + { if (start_spf_parse (rec, elt->content.txt.data, elt->ttl)) { break; } @@ -1426,10 +1550,11 @@ spf_dns_callback (struct rdns_reply *reply, gpointer arg) gchar * get_spf_domain (struct rspamd_task *task) { - gchar *domain, *res = NULL; - GList *domains; + gchar *domain, *res = NULL; + GList *domains; - if (task->from && (domain = strchr (task->from, '@')) != NULL && *domain == '@') { + if (task->from && + (domain = strchr (task->from, '@')) != NULL && *domain == '@') { res = rspamd_mempool_strdup (task->task_pool, domain + 1); if ((domain = strchr (res, '>')) != NULL) { *domain = '\0'; @@ -1437,7 +1562,10 @@ get_spf_domain (struct rspamd_task *task) } else { /* Extract from header */ - domains = message_get_header (task->task_pool, task->message, "From", FALSE); + domains = message_get_header (task->task_pool, + task->message, + "From", + FALSE); if (domains != NULL) { res = rspamd_mempool_strdup (task->task_pool, domains->data); @@ -1461,24 +1589,28 @@ get_spf_domain (struct rspamd_task *task) gboolean resolve_spf (struct rspamd_task *task, spf_cb_t callback) { - struct spf_record *rec; - gchar *domain; - GList *domains; + struct spf_record *rec; + gchar *domain; + GList *domains; rec = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct spf_record)); rec->task = task; rec->callback = callback; /* Add destructor */ - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)spf_record_destructor, rec); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)spf_record_destructor, + rec); /* Extract from data */ - if (task->from && (domain = strchr (task->from, '@')) != NULL && *domain == '@') { + if (task->from && + (domain = strchr (task->from, '@')) != NULL && *domain == '@') { rec->sender = task->from; rec->local_part = rspamd_mempool_strdup (task->task_pool, task->from); *(rec->local_part + (domain - task->from)) = '\0'; if (*rec->local_part == '<') { - memmove (rec->local_part, rec->local_part + 1, strlen (rec->local_part)); + memmove (rec->local_part, rec->local_part + 1, + strlen (rec->local_part)); } rec->cur_domain = rspamd_mempool_strdup (task->task_pool, domain + 1); if ((domain = strchr (rec->cur_domain, '>')) != NULL) { @@ -1486,25 +1618,31 @@ resolve_spf (struct rspamd_task *task, spf_cb_t callback) } rec->sender_domain = rec->cur_domain; - if (make_dns_request (task->resolver, task->s, task->task_pool, spf_dns_callback, - (void *)rec, RDNS_REQUEST_TXT, rec->cur_domain)) { - task->dns_requests ++; - rec->requests_inflight ++; + if (make_dns_request (task->resolver, task->s, task->task_pool, + spf_dns_callback, + (void *)rec, RDNS_REQUEST_TXT, rec->cur_domain)) { + task->dns_requests++; + rec->requests_inflight++; return TRUE; } } else { /* Extract from header */ - domains = message_get_header (task->task_pool, task->message, "From", FALSE); + domains = message_get_header (task->task_pool, + task->message, + "From", + FALSE); if (domains != NULL) { - rec->cur_domain = rspamd_mempool_strdup (task->task_pool, domains->data); + rec->cur_domain = rspamd_mempool_strdup (task->task_pool, + domains->data); g_list_free (domains); if ((domain = strrchr (rec->cur_domain, '@')) == NULL) { return FALSE; } - rec->sender = rspamd_mempool_strdup (task->task_pool, rec->cur_domain); + rec->sender = rspamd_mempool_strdup (task->task_pool, + rec->cur_domain); rec->local_part = rec->cur_domain; *domain = '\0'; rec->cur_domain = domain + 1; @@ -1518,9 +1656,10 @@ resolve_spf (struct rspamd_task *task, spf_cb_t callback) } rec->sender_domain = rec->cur_domain; if (make_dns_request (task->resolver, task->s, task->task_pool, - spf_dns_callback, (void *)rec, RDNS_REQUEST_TXT, rec->cur_domain)) { - task->dns_requests ++; - rec->requests_inflight ++; + spf_dns_callback, (void *)rec, RDNS_REQUEST_TXT, + rec->cur_domain)) { + task->dns_requests++; + rec->requests_inflight++; return TRUE; } } @@ -1529,6 +1668,6 @@ resolve_spf (struct rspamd_task *task, spf_cb_t callback) return FALSE; } -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/libserver/spf.h b/src/libserver/spf.h index 94c613e42..18d8229f8 100644 --- a/src/libserver/spf.h +++ b/src/libserver/spf.h @@ -78,7 +78,7 @@ gboolean resolve_spf (struct rspamd_task *task, spf_cb_t callback); /* * Get a domain for spf for specified task */ -gchar *get_spf_domain (struct rspamd_task *task); +gchar * get_spf_domain (struct rspamd_task *task); #endif diff --git a/src/libserver/statfile.c b/src/libserver/statfile.c index a993fd116..031c45cf5 100644 --- a/src/libserver/statfile.c +++ b/src/libserver/statfile.c @@ -33,33 +33,33 @@ /* Maximum number of statistics files */ #define STATFILES_MAX 255 static void statfile_pool_set_block_common ( - statfile_pool_t * pool, stat_file_t * file, - guint32 h1, guint32 h2, - time_t t, double value, - gboolean from_now); + statfile_pool_t * pool, stat_file_t * file, + guint32 h1, guint32 h2, + time_t t, double value, + gboolean from_now); static gint cmpstatfile (const void *a, const void *b) { - const stat_file_t *s1 = a, *s2 = b; + const stat_file_t *s1 = a, *s2 = b; return g_ascii_strcasecmp (s1->filename, s2->filename); } /* Convert statfile version 1.0 to statfile version 1.2, saving backup */ struct stat_file_header_10 { - u_char magic[3]; /**< magic signature ('r' 's' 'd') */ - u_char version[2]; /**< version of statfile */ - u_char padding[3]; /**< padding */ - guint64 create_time; /**< create time (time_t->guint64) */ + u_char magic[3]; /**< magic signature ('r' 's' 'd') */ + u_char version[2]; /**< version of statfile */ + u_char padding[3]; /**< padding */ + guint64 create_time; /**< create time (time_t->guint64) */ }; static gboolean convert_statfile_10 (stat_file_t * file) { - gchar *backup_name; + gchar *backup_name; struct stat st; - struct stat_file_header header = { + struct stat_file_header header = { .magic = {'r', 's', 'd'}, .version = RSPAMD_STATFILE_VERSION, .padding = {0, 0, 0}, @@ -70,9 +70,12 @@ convert_statfile_10 (stat_file_t * file) /* Format backup name */ backup_name = g_strdup_printf ("%s.%s", file->filename, BACKUP_SUFFIX); - - msg_info ("convert old statfile %s to version %c.%c, backup in %s", file->filename, - header.version[0], header.version[1], backup_name); + + msg_info ("convert old statfile %s to version %c.%c, backup in %s", + file->filename, + header.version[0], + header.version[1], + backup_name); if (stat (backup_name, &st) != -1) { msg_info ("replace old %s", backup_name); @@ -85,31 +88,51 @@ convert_statfile_10 (stat_file_t * file) /* XXX: maybe race condition here */ unlock_file (file->fd, FALSE); close (file->fd); - if ((file->fd = open (file->filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) { - msg_info ("cannot create file %s, error %d, %s", file->filename, errno, strerror (errno)); + if ((file->fd = + open (file->filename, O_RDWR | O_TRUNC | O_CREAT, + S_IWUSR | S_IRUSR)) == -1) { + msg_info ("cannot create file %s, error %d, %s", + file->filename, + errno, + strerror (errno)); return FALSE; } lock_file (file->fd, FALSE); /* Now make new header and copy it to new file */ if (write (file->fd, &header, sizeof (header)) == -1) { - msg_info ("cannot write to file %s, error %d, %s", file->filename, errno, strerror (errno)); + msg_info ("cannot write to file %s, error %d, %s", + file->filename, + errno, + strerror (errno)); return FALSE; } /* Now write old map to new file */ - if (write (file->fd, ((u_char *)file->map + sizeof (struct stat_file_header_10)), - file->len - sizeof (struct stat_file_header_10)) == -1) { - msg_info ("cannot write to file %s, error %d, %s", file->filename, errno, strerror (errno)); + if (write (file->fd, + ((u_char *)file->map + sizeof (struct stat_file_header_10)), + file->len - sizeof (struct stat_file_header_10)) == -1) { + msg_info ("cannot write to file %s, error %d, %s", + file->filename, + errno, + strerror (errno)); return FALSE; } /* Unmap old memory and map new */ munmap (file->map, file->len); - file->len = file->len + sizeof (struct stat_file_header) - sizeof (struct stat_file_header_10); + file->len = file->len + sizeof (struct stat_file_header) - + sizeof (struct stat_file_header_10); #ifdef HAVE_MMAP_NOCORE - if ((file->map = mmap (NULL, file->len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOCORE, file->fd, 0)) == MAP_FAILED) { + if ((file->map = + mmap (NULL, file->len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOCORE, + file->fd, 0)) == MAP_FAILED) { #else - if ((file->map = mmap (NULL, file->len, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, 0)) == MAP_FAILED) { + if ((file->map = + mmap (NULL, file->len, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, + 0)) == MAP_FAILED) { #endif - msg_info ("cannot mmap file %s, error %d, %s", file->filename, errno, strerror (errno)); + msg_info ("cannot mmap file %s, error %d, %s", + file->filename, + errno, + strerror (errno)); return FALSE; } @@ -120,9 +143,9 @@ convert_statfile_10 (stat_file_t * file) static gint statfile_pool_check (stat_file_t * file) { - struct stat_file *f; - gchar *c; - static gchar valid_version[] = RSPAMD_STATFILE_VERSION; + struct stat_file *f; + gchar *c; + static gchar valid_version[] = RSPAMD_STATFILE_VERSION; if (!file || !file->map) { @@ -130,7 +153,9 @@ statfile_pool_check (stat_file_t * file) } if (file->len < sizeof (struct stat_file)) { - msg_info ("file %s is too short to be stat file: %z", file->filename, file->len); + msg_info ("file %s is too short to be stat file: %z", + file->filename, + file->len); return -1; } @@ -150,31 +175,40 @@ statfile_pool_check (stat_file_t * file) } else if (memcmp (c, valid_version, sizeof (valid_version)) != 0) { /* Unknown version */ - msg_info ("file %s has invalid version %c.%c", file->filename, '0' + *c, '0' + *(c + 1)); + msg_info ("file %s has invalid version %c.%c", + file->filename, + '0' + *c, + '0' + *(c + 1)); return -1; } /* Check first section and set new offset */ file->cur_section.code = f->section.code; file->cur_section.length = f->section.length; - if (file->cur_section.length * sizeof (struct stat_file_block) > file->len) { - msg_info ("file %s is truncated: %z, must be %z", file->filename, file->len, file->cur_section.length * sizeof (struct stat_file_block)); + if (file->cur_section.length * sizeof (struct stat_file_block) > + file->len) { + msg_info ("file %s is truncated: %z, must be %z", + file->filename, + file->len, + file->cur_section.length * sizeof (struct stat_file_block)); return -1; } - file->seek_pos = sizeof (struct stat_file) - sizeof (struct stat_file_block); + file->seek_pos = sizeof (struct stat_file) - + sizeof (struct stat_file_block); return 0; } -statfile_pool_t * +statfile_pool_t * statfile_pool_new (rspamd_mempool_t *pool, gboolean use_mlock) { - statfile_pool_t *new; + statfile_pool_t *new; new = rspamd_mempool_alloc0 (pool, sizeof (statfile_pool_t)); new->pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); - new->files = rspamd_mempool_alloc0 (new->pool, STATFILES_MAX * sizeof (stat_file_t)); + new->files = + rspamd_mempool_alloc0 (new->pool, STATFILES_MAX * sizeof (stat_file_t)); new->lock = rspamd_mempool_get_mutex (new->pool); new->mlock_ok = use_mlock; @@ -182,18 +216,24 @@ statfile_pool_new (rspamd_mempool_t *pool, gboolean use_mlock) } static stat_file_t * -statfile_pool_reindex (statfile_pool_t * pool, gchar *filename, size_t old_size, size_t size) +statfile_pool_reindex (statfile_pool_t * pool, + gchar *filename, + size_t old_size, + size_t size) { - gchar *backup; - gint fd; - stat_file_t *new; - u_char *map, *pos; - struct stat_file_block *block; - struct stat_file_header *header; + gchar *backup; + gint fd; + stat_file_t *new; + u_char *map, *pos; + struct stat_file_block *block; + struct stat_file_header *header; if (size < - sizeof (struct stat_file_header) + sizeof (struct stat_file_section) + sizeof (block)) { - msg_err ("file %s is too small to carry any statistic: %z", filename, size); + sizeof (struct stat_file_header) + sizeof (struct stat_file_section) + + sizeof (block)) { + msg_err ("file %s is too small to carry any statistic: %z", + filename, + size); return NULL; } @@ -202,7 +242,8 @@ statfile_pool_reindex (statfile_pool_t * pool, gchar *filename, size_t old_size, backup = g_strconcat (filename, ".old", NULL); if (rename (filename, backup) == -1) { - msg_err ("cannot rename %s to %s: %s", filename, backup, strerror (errno)); + msg_err ("cannot rename %s to %s: %s", filename, backup, strerror ( + errno)); g_free (backup); rspamd_mempool_unlock_mutex (pool->lock); return NULL; @@ -227,7 +268,8 @@ statfile_pool_reindex (statfile_pool_t * pool, gchar *filename, size_t old_size, } /* Now start reading blocks from old statfile */ - if ((map = mmap (NULL, old_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if ((map = + mmap (NULL, old_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { msg_err ("cannot mmap file: %s", strerror (errno)); close (fd); g_free (backup); @@ -238,14 +280,20 @@ statfile_pool_reindex (statfile_pool_t * pool, gchar *filename, size_t old_size, while (old_size - (pos - map) >= sizeof (struct stat_file_block)) { block = (struct stat_file_block *)pos; if (block->hash1 != 0 && block->value != 0) { - statfile_pool_set_block_common (pool, new, block->hash1, block->hash2, 0, block->value, FALSE); + statfile_pool_set_block_common (pool, + new, + block->hash1, + block->hash2, + 0, + block->value, + FALSE); } pos += sizeof (block); } header = (struct stat_file_header *)map; statfile_set_revision (new, header->revision, header->rev_time); - + munmap (map, old_size); close (fd); unlink (backup); @@ -261,9 +309,9 @@ statfile_pool_reindex (statfile_pool_t * pool, gchar *filename, size_t old_size, static void statfile_preload (stat_file_t *file) { - guint8 *pos, *end; - volatile guint8 t; - gsize size; + guint8 *pos, *end; + volatile guint8 t; + gsize size; pos = (guint8 *)file->map; end = (guint8 *)file->map + file->len; @@ -286,50 +334,66 @@ statfile_preload (stat_file_t *file) } } -stat_file_t * -statfile_pool_open (statfile_pool_t * pool, gchar *filename, size_t size, gboolean forced) +stat_file_t * +statfile_pool_open (statfile_pool_t * pool, + gchar *filename, + size_t size, + gboolean forced) { - struct stat st; - stat_file_t *new_file; + struct stat st; + stat_file_t *new_file; if ((new_file = statfile_pool_is_open (pool, filename)) != NULL) { return new_file; } if (pool->opened >= STATFILES_MAX - 1) { - msg_err ("reached hard coded limit of statfiles opened: %d", STATFILES_MAX); + msg_err ("reached hard coded limit of statfiles opened: %d", + STATFILES_MAX); return NULL; } if (stat (filename, &st) == -1) { - msg_info ("cannot stat file %s, error %s, %d", filename, strerror (errno), errno); + msg_info ("cannot stat file %s, error %s, %d", filename, strerror ( + errno), errno); return NULL; } rspamd_mempool_lock_mutex (pool->lock); - if (!forced && labs (size - st.st_size) > (long)sizeof (struct stat_file) * 2 - && size > sizeof (struct stat_file)) { + if (!forced && + labs (size - st.st_size) > (long)sizeof (struct stat_file) * 2 + && size > sizeof (struct stat_file)) { rspamd_mempool_unlock_mutex (pool->lock); - msg_warn ("need to reindex statfile old size: %Hz, new size: %Hz", (size_t)st.st_size, size); + msg_warn ("need to reindex statfile old size: %Hz, new size: %Hz", + (size_t)st.st_size, size); return statfile_pool_reindex (pool, filename, st.st_size, size); } else if (size < sizeof (struct stat_file)) { - msg_err ("requested to shrink statfile to %Hz but it is too small", size); + msg_err ("requested to shrink statfile to %Hz but it is too small", + size); } new_file = &pool->files[pool->opened++]; bzero (new_file, sizeof (stat_file_t)); if ((new_file->fd = open (filename, O_RDWR)) == -1) { - msg_info ("cannot open file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("cannot open file %s, error %d, %s", + filename, + errno, + strerror (errno)); rspamd_mempool_unlock_mutex (pool->lock); pool->opened--; return NULL; } - if ((new_file->map = mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, new_file->fd, 0)) == MAP_FAILED) { + if ((new_file->map = + mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, + new_file->fd, 0)) == MAP_FAILED) { close (new_file->fd); rspamd_mempool_unlock_mutex (pool->lock); - msg_info ("cannot mmap file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("cannot mmap file %s, error %d, %s", + filename, + errno, + strerror (errno)); pool->opened--; return NULL; @@ -340,7 +404,9 @@ statfile_pool_open (statfile_pool_t * pool, gchar *filename, size_t size, gboole /* Try to lock pages in RAM */ if (pool->mlock_ok) { if (mlock (new_file->map, new_file->len) == -1) { - msg_warn ("mlock of statfile failed, maybe you need to increase RLIMIT_MEMLOCK limit for a process: %s", strerror (errno)); + msg_warn ( + "mlock of statfile failed, maybe you need to increase RLIMIT_MEMLOCK limit for a process: %s", + strerror (errno)); pool->mlock_ok = FALSE; } } @@ -350,7 +416,7 @@ statfile_pool_open (statfile_pool_t * pool, gchar *filename, size_t size, gboole pool->opened--; rspamd_mempool_unlock_mutex (pool->lock); unlock_file (new_file->fd, FALSE); - munmap (new_file->map, st.st_size); + munmap (new_file->map, st.st_size); return NULL; } unlock_file (new_file->fd, FALSE); @@ -367,9 +433,11 @@ statfile_pool_open (statfile_pool_t * pool, gchar *filename, size_t size, gboole } gint -statfile_pool_close (statfile_pool_t * pool, stat_file_t * file, gboolean keep_sorted) +statfile_pool_close (statfile_pool_t * pool, + stat_file_t * file, + gboolean keep_sorted) { - stat_file_t *pos; + stat_file_t *pos; if ((pos = statfile_pool_is_open (pool, file->filename)) == NULL) { msg_info ("file %s is not opened", file->filename); @@ -388,7 +456,7 @@ statfile_pool_close (statfile_pool_t * pool, stat_file_t * file, gboolean keep_s } /* Move the remain statfiles */ memmove (pos, ((guint8 *)pos) + sizeof (stat_file_t), - (--pool->opened - (pos - pool->files)) * sizeof (stat_file_t)); + (--pool->opened - (pos - pool->files)) * sizeof (stat_file_t)); rspamd_mempool_unlock_mutex (pool->lock); @@ -398,7 +466,7 @@ statfile_pool_close (statfile_pool_t * pool, stat_file_t * file, gboolean keep_s gint statfile_pool_create (statfile_pool_t * pool, gchar *filename, size_t size) { - struct stat_file_header header = { + struct stat_file_header header = { .magic = {'r', 's', 'd'}, .version = RSPAMD_STATFILE_VERSION, .padding = {0, 0, 0}, @@ -406,13 +474,13 @@ statfile_pool_create (statfile_pool_t * pool, gchar *filename, size_t size) .rev_time = 0, .used_blocks = 0 }; - struct stat_file_section section = { + struct stat_file_section section = { .code = STATFILE_SECTION_COMMON, }; - struct stat_file_block block = { 0, 0, 0 }; - gint fd; - guint buflen = 0, nblocks; - gchar *buf = NULL; + struct stat_file_block block = { 0, 0, 0 }; + gint fd; + guint buflen = 0, nblocks; + gchar *buf = NULL; if (statfile_pool_is_open (pool, filename) != NULL) { msg_info ("file %s is already opened", filename); @@ -420,26 +488,40 @@ statfile_pool_create (statfile_pool_t * pool, gchar *filename, size_t size) } if (size < - sizeof (struct stat_file_header) + sizeof (struct stat_file_section) + sizeof (block)) { - msg_err ("file %s is too small to carry any statistic: %z", filename, size); + sizeof (struct stat_file_header) + sizeof (struct stat_file_section) + + sizeof (block)) { + msg_err ("file %s is too small to carry any statistic: %z", + filename, + size); return -1; } rspamd_mempool_lock_mutex (pool->lock); - nblocks = (size - sizeof (struct stat_file_header) - sizeof (struct stat_file_section)) / sizeof (struct stat_file_block); + nblocks = + (size - sizeof (struct stat_file_header) - + sizeof (struct stat_file_section)) / sizeof (struct stat_file_block); header.total_blocks = nblocks; - if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) { - msg_info ("cannot create file %s, error %d, %s", filename, errno, strerror (errno)); + if ((fd = + open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) { + msg_info ("cannot create file %s, error %d, %s", + filename, + errno, + strerror (errno)); rspamd_mempool_unlock_mutex (pool->lock); return -1; } - rspamd_fallocate (fd, 0, sizeof (header) + sizeof (section) + sizeof (block) * nblocks); + rspamd_fallocate (fd, + 0, + sizeof (header) + sizeof (section) + sizeof (block) * nblocks); header.create_time = (guint64) time (NULL); if (write (fd, &header, sizeof (header)) == -1) { - msg_info ("cannot write header to file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("cannot write header to file %s, error %d, %s", + filename, + errno, + strerror (errno)); close (fd); rspamd_mempool_unlock_mutex (pool->lock); return -1; @@ -447,12 +529,15 @@ statfile_pool_create (statfile_pool_t * pool, gchar *filename, size_t size) section.length = (guint64) nblocks; if (write (fd, §ion, sizeof (section)) == -1) { - msg_info ("cannot write section header to file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("cannot write section header to file %s, error %d, %s", + filename, + errno, + strerror (errno)); close (fd); rspamd_mempool_unlock_mutex (pool->lock); return -1; } - + /* Buffer for write 256 blocks at once */ if (nblocks > 256) { buflen = sizeof (block) * 256; @@ -463,7 +548,10 @@ statfile_pool_create (statfile_pool_t * pool, gchar *filename, size_t size) if (nblocks > 256) { /* Just write buffer */ if (write (fd, buf, buflen) == -1) { - msg_info ("cannot write blocks buffer to file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("cannot write blocks buffer to file %s, error %d, %s", + filename, + errno, + strerror (errno)); close (fd); rspamd_mempool_unlock_mutex (pool->lock); g_free (buf); @@ -473,7 +561,10 @@ statfile_pool_create (statfile_pool_t * pool, gchar *filename, size_t size) } else { if (write (fd, &block, sizeof (block)) == -1) { - msg_info ("cannot write block to file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("cannot write block to file %s, error %d, %s", + filename, + errno, + strerror (errno)); close (fd); if (buf) { g_free (buf); @@ -481,7 +572,7 @@ statfile_pool_create (statfile_pool_t * pool, gchar *filename, size_t size) rspamd_mempool_unlock_mutex (pool->lock); return -1; } - nblocks --; + nblocks--; } } @@ -498,7 +589,7 @@ statfile_pool_create (statfile_pool_t * pool, gchar *filename, size_t size) void statfile_pool_delete (statfile_pool_t * pool) { - gint i; + gint i; for (i = 0; i < pool->opened; i++) { statfile_pool_close (pool, &pool->files[i], FALSE); @@ -521,11 +612,15 @@ statfile_pool_unlock_file (statfile_pool_t * pool, stat_file_t * file) } double -statfile_pool_get_block (statfile_pool_t * pool, stat_file_t * file, guint32 h1, guint32 h2, time_t now) +statfile_pool_get_block (statfile_pool_t * pool, + stat_file_t * file, + guint32 h1, + guint32 h2, + time_t now) { - struct stat_file_block *block; - guint i, blocknum; - u_char *c; + struct stat_file_block *block; + guint i, blocknum; + u_char *c; file->access_time = now; @@ -534,7 +629,8 @@ statfile_pool_get_block (statfile_pool_t * pool, stat_file_t * file, guint32 h1, } blocknum = h1 % file->cur_section.length; - c = (u_char *) file->map + file->seek_pos + blocknum * sizeof (struct stat_file_block); + c = (u_char *) file->map + file->seek_pos + blocknum * + sizeof (struct stat_file_block); block = (struct stat_file_block *)c; for (i = 0; i < CHAIN_LENGTH; i++) { @@ -553,13 +649,19 @@ statfile_pool_get_block (statfile_pool_t * pool, stat_file_t * file, guint32 h1, } static void -statfile_pool_set_block_common (statfile_pool_t * pool, stat_file_t * file, guint32 h1, guint32 h2, time_t t, double value, gboolean from_now) +statfile_pool_set_block_common (statfile_pool_t * pool, + stat_file_t * file, + guint32 h1, + guint32 h2, + time_t t, + double value, + gboolean from_now) { - struct stat_file_block *block, *to_expire = NULL; - struct stat_file_header *header; - guint i, blocknum; - u_char *c; - double min = G_MAXDOUBLE; + struct stat_file_block *block, *to_expire = NULL; + struct stat_file_header *header; + guint i, blocknum; + u_char *c; + double min = G_MAXDOUBLE; if (from_now) { file->access_time = t; @@ -570,13 +672,16 @@ statfile_pool_set_block_common (statfile_pool_t * pool, stat_file_t * file, guin blocknum = h1 % file->cur_section.length; header = (struct stat_file_header *)file->map; - c = (u_char *) file->map + file->seek_pos + blocknum * sizeof (struct stat_file_block); + c = (u_char *) file->map + file->seek_pos + blocknum * + sizeof (struct stat_file_block); block = (struct stat_file_block *)c; for (i = 0; i < CHAIN_LENGTH; i++) { if (i + blocknum >= file->cur_section.length) { /* Need to expire some block in chain */ - msg_info ("chain %ud is full in statfile %s, starting expire", blocknum, file->filename); + msg_info ("chain %ud is full in statfile %s, starting expire", + blocknum, + file->filename); break; } /* First try to find block in chain */ @@ -587,15 +692,19 @@ statfile_pool_set_block_common (statfile_pool_t * pool, stat_file_t * file, guin /* Check whether we have a free block in chain */ if (block->hash1 == 0 && block->hash2 == 0) { /* Write new block here */ - msg_debug ("found free block %ud in chain %ud, set h1=%ud, h2=%ud", i, blocknum, h1, h2); + msg_debug ("found free block %ud in chain %ud, set h1=%ud, h2=%ud", + i, + blocknum, + h1, + h2); block->hash1 = h1; block->hash2 = h2; block->value = value; - header->used_blocks ++; + header->used_blocks++; return; } - + /* Expire block with minimum value otherwise */ if (block->value < min) { to_expire = block; @@ -611,7 +720,8 @@ statfile_pool_set_block_common (statfile_pool_t * pool, stat_file_t * file, guin } else { /* Expire first block in chain */ - c = (u_char *) file->map + file->seek_pos + blocknum * sizeof (struct stat_file_block); + c = (u_char *) file->map + file->seek_pos + blocknum * + sizeof (struct stat_file_block); block = (struct stat_file_block *)c; } @@ -621,17 +731,26 @@ statfile_pool_set_block_common (statfile_pool_t * pool, stat_file_t * file, guin } void -statfile_pool_set_block (statfile_pool_t * pool, stat_file_t * file, guint32 h1, guint32 h2, time_t now, double value) +statfile_pool_set_block (statfile_pool_t * pool, + stat_file_t * file, + guint32 h1, + guint32 h2, + time_t now, + double value) { statfile_pool_set_block_common (pool, file, h1, h2, now, value, TRUE); } -stat_file_t * +stat_file_t * statfile_pool_is_open (statfile_pool_t * pool, gchar *filename) { - static stat_file_t f, *ret; + static stat_file_t f, *ret; rspamd_strlcpy (f.filename, filename, sizeof (f.filename)); - ret = lfind (&f, pool->files, (size_t *)&pool->opened, sizeof (stat_file_t), cmpstatfile); + ret = lfind (&f, + pool->files, + (size_t *)&pool->opened, + sizeof (stat_file_t), + cmpstatfile); return ret; } @@ -643,10 +762,13 @@ statfile_pool_get_section (statfile_pool_t * pool, stat_file_t * file) } gboolean -statfile_pool_set_section (statfile_pool_t * pool, stat_file_t * file, guint32 code, gboolean from_begin) +statfile_pool_set_section (statfile_pool_t * pool, + stat_file_t * file, + guint32 code, + gboolean from_begin) { - struct stat_file_section *sec; - off_t cur_offset; + struct stat_file_section *sec; + off_t cur_offset; /* Try to find section */ @@ -671,13 +793,19 @@ statfile_pool_set_section (statfile_pool_t * pool, stat_file_t * file, guint32 c } gboolean -statfile_pool_add_section (statfile_pool_t * pool, stat_file_t * file, guint32 code, guint64 length) +statfile_pool_add_section (statfile_pool_t * pool, + stat_file_t * file, + guint32 code, + guint64 length) { - struct stat_file_section sect; - struct stat_file_block block = { 0, 0, 0 }; + struct stat_file_section sect; + struct stat_file_block block = { 0, 0, 0 }; if (lseek (file->fd, 0, SEEK_END) == -1) { - msg_info ("cannot lseek file %s, error %d, %s", file->filename, errno, strerror (errno)); + msg_info ("cannot lseek file %s, error %d, %s", + file->filename, + errno, + strerror (errno)); return FALSE; } @@ -685,13 +813,19 @@ statfile_pool_add_section (statfile_pool_t * pool, stat_file_t * file, guint32 c sect.length = length; if (write (file->fd, §, sizeof (sect)) == -1) { - msg_info ("cannot write block to file %s, error %d, %s", file->filename, errno, strerror (errno)); + msg_info ("cannot write block to file %s, error %d, %s", + file->filename, + errno, + strerror (errno)); return FALSE; } while (length--) { if (write (file->fd, &block, sizeof (block)) == -1) { - msg_info ("cannot write block to file %s, error %d, %s", file->filename, errno, strerror (errno)); + msg_info ("cannot write block to file %s, error %d, %s", + file->filename, + errno, + strerror (errno)); return FALSE; } } @@ -702,8 +836,13 @@ statfile_pool_add_section (statfile_pool_t * pool, stat_file_t * file, guint32 c fsync (file->fd); file->len += length; - if ((file->map = mmap (NULL, file->len, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, 0)) == NULL) { - msg_info ("cannot mmap file %s, error %d, %s", file->filename, errno, strerror (errno)); + if ((file->map = + mmap (NULL, file->len, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, + 0)) == NULL) { + msg_info ("cannot mmap file %s, error %d, %s", + file->filename, + errno, + strerror (errno)); return FALSE; } statfile_pool_unlock_file (pool, file); @@ -731,15 +870,15 @@ statfile_get_section_by_name (const gchar *name) return 0; } -gboolean +gboolean statfile_set_revision (stat_file_t *file, guint64 rev, time_t time) { - struct stat_file_header *header; + struct stat_file_header *header; if (file == NULL || file->map == NULL) { return FALSE; } - + header = (struct stat_file_header *)file->map; header->revision = rev; @@ -748,10 +887,10 @@ statfile_set_revision (stat_file_t *file, guint64 rev, time_t time) return TRUE; } -gboolean +gboolean statfile_inc_revision (stat_file_t *file) { - struct stat_file_header *header; + struct stat_file_header *header; if (file == NULL || file->map == NULL) { return FALSE; @@ -759,7 +898,7 @@ statfile_inc_revision (stat_file_t *file) header = (struct stat_file_header *)file->map; - header->revision ++; + header->revision++; return TRUE; } @@ -767,12 +906,12 @@ statfile_inc_revision (stat_file_t *file) gboolean statfile_get_revision (stat_file_t *file, guint64 *rev, time_t *time) { - struct stat_file_header *header; + struct stat_file_header *header; if (file == NULL || file->map == NULL) { return FALSE; } - + header = (struct stat_file_header *)file->map; if (rev != NULL) { @@ -785,29 +924,29 @@ statfile_get_revision (stat_file_t *file, guint64 *rev, time_t *time) return TRUE; } -guint64 +guint64 statfile_get_used_blocks (stat_file_t *file) { - struct stat_file_header *header; + struct stat_file_header *header; if (file == NULL || file->map == NULL) { - return (guint64)-1; + return (guint64) - 1; } - + header = (struct stat_file_header *)file->map; return header->used_blocks; } -guint64 +guint64 statfile_get_total_blocks (stat_file_t *file) { - struct stat_file_header *header; + struct stat_file_header *header; if (file == NULL || file->map == NULL) { - return (guint64)-1; + return (guint64) - 1; } - + header = (struct stat_file_header *)file->map; /* If total blocks is 0 we have old version of header, so set total blocks correctly */ @@ -821,13 +960,13 @@ statfile_get_total_blocks (stat_file_t *file) static void statfile_pool_invalidate_callback (gint fd, short what, void *ud) { - statfile_pool_t *pool = ud; - stat_file_t *file; - gint i; + statfile_pool_t *pool = ud; + stat_file_t *file; + gint i; msg_info ("invalidating %d statfiles", pool->opened); - for (i = 0; i < pool->opened; i ++) { + for (i = 0; i < pool->opened; i++) { file = &pool->files[i]; msync (file->map, file->len, MS_ASYNC); } @@ -836,44 +975,54 @@ statfile_pool_invalidate_callback (gint fd, short what, void *ud) void -statfile_pool_plan_invalidate (statfile_pool_t *pool, time_t seconds, time_t jitter) +statfile_pool_plan_invalidate (statfile_pool_t *pool, + time_t seconds, + time_t jitter) { - gboolean pending; + gboolean pending; if (pool->invalidate_event != NULL) { pending = evtimer_pending (pool->invalidate_event, NULL); if (pending) { /* Replan event */ - pool->invalidate_tv.tv_sec = seconds + g_random_int_range (0, jitter); + pool->invalidate_tv.tv_sec = seconds + + g_random_int_range (0, jitter); pool->invalidate_tv.tv_usec = 0; evtimer_add (pool->invalidate_event, &pool->invalidate_tv); } } else { - pool->invalidate_event = rspamd_mempool_alloc (pool->pool, sizeof (struct event)); + pool->invalidate_event = + rspamd_mempool_alloc (pool->pool, sizeof (struct event)); pool->invalidate_tv.tv_sec = seconds + g_random_int_range (0, jitter); pool->invalidate_tv.tv_usec = 0; - evtimer_set (pool->invalidate_event, statfile_pool_invalidate_callback, pool); + evtimer_set (pool->invalidate_event, + statfile_pool_invalidate_callback, + pool); evtimer_add (pool->invalidate_event, &pool->invalidate_tv); - msg_info ("invalidate of statfile pool is planned in %d seconds", (gint)pool->invalidate_tv.tv_sec); + msg_info ("invalidate of statfile pool is planned in %d seconds", + (gint)pool->invalidate_tv.tv_sec); } } stat_file_t * -get_statfile_by_symbol (statfile_pool_t *pool, struct rspamd_classifier_config *ccf, - const gchar *symbol, struct rspamd_statfile_config **st, gboolean try_create) +get_statfile_by_symbol (statfile_pool_t *pool, + struct rspamd_classifier_config *ccf, + const gchar *symbol, + struct rspamd_statfile_config **st, + gboolean try_create) { - stat_file_t *res = NULL; - GList *cur; + stat_file_t *res = NULL; + GList *cur; - if (pool == NULL || ccf == NULL || symbol == NULL) { + if (pool == NULL || ccf == NULL || symbol == NULL) { msg_err ("invalid input arguments"); - return NULL; - } + return NULL; + } - cur = g_list_first (ccf->statfiles); + cur = g_list_first (ccf->statfiles); while (cur) { *st = cur->data; if (strcmp (symbol, (*st)->symbol) == 0) { @@ -882,28 +1031,33 @@ get_statfile_by_symbol (statfile_pool_t *pool, struct rspamd_classifier_config * *st = NULL; cur = g_list_next (cur); } - if (*st == NULL) { + if (*st == NULL) { msg_info ("cannot find statfile with symbol %s", symbol); - return NULL; - } + return NULL; + } - if ((res = statfile_pool_is_open (pool, (*st)->path)) == NULL) { - if ((res = statfile_pool_open (pool, (*st)->path, (*st)->size, FALSE)) == NULL) { + if ((res = statfile_pool_is_open (pool, (*st)->path)) == NULL) { + if ((res = + statfile_pool_open (pool, (*st)->path, (*st)->size, + FALSE)) == NULL) { msg_warn ("cannot open %s", (*st)->path); - if (try_create) { - if (statfile_pool_create (pool, (*st)->path, (*st)->size) == -1) { + if (try_create) { + if (statfile_pool_create (pool, (*st)->path, + (*st)->size) == -1) { msg_err ("cannot create statfile %s", (*st)->path); return NULL; } - res = statfile_pool_open (pool, (*st)->path, (*st)->size, FALSE); + res = + statfile_pool_open (pool, (*st)->path, (*st)->size, FALSE); if (res == NULL) { - msg_err ("cannot open statfile %s after creation", (*st)->path); + msg_err ("cannot open statfile %s after creation", + (*st)->path); } - } + } } } - return res; + return res; } void @@ -913,10 +1067,12 @@ statfile_pool_lockall (statfile_pool_t *pool) gint i; if (pool->mlock_ok) { - for (i = 0; i < pool->opened; i ++) { + for (i = 0; i < pool->opened; i++) { file = &pool->files[i]; if (mlock (file->map, file->len) == -1) { - msg_warn ("mlock of statfile failed, maybe you need to increase RLIMIT_MEMLOCK limit for a process: %s", strerror (errno)); + msg_warn ( + "mlock of statfile failed, maybe you need to increase RLIMIT_MEMLOCK limit for a process: %s", + strerror (errno)); pool->mlock_ok = FALSE; return; } diff --git a/src/libserver/statfile.h b/src/libserver/statfile.h index 3ad5f1321..f7f632703 100644 --- a/src/libserver/statfile.h +++ b/src/libserver/statfile.h @@ -25,41 +25,41 @@ * Common statfile header */ struct stat_file_header { - u_char magic[3]; /**< magic signature ('r' 's' 'd') */ - u_char version[2]; /**< version of statfile */ - u_char padding[3]; /**< padding */ - guint64 create_time; /**< create time (time_t->guint64) */ - guint64 revision; /**< revision number */ - guint64 rev_time; /**< revision time */ - guint64 used_blocks; /**< used blocks number */ - guint64 total_blocks; /**< total number of blocks */ - u_char unused[239]; /**< some bytes that can be used in future */ + u_char magic[3]; /**< magic signature ('r' 's' 'd') */ + u_char version[2]; /**< version of statfile */ + u_char padding[3]; /**< padding */ + guint64 create_time; /**< create time (time_t->guint64) */ + guint64 revision; /**< revision number */ + guint64 rev_time; /**< revision time */ + guint64 used_blocks; /**< used blocks number */ + guint64 total_blocks; /**< total number of blocks */ + u_char unused[239]; /**< some bytes that can be used in future */ }; /** * Section header */ struct stat_file_section { - guint64 code; /**< section's code */ - guint64 length; /**< section's length in blocks */ + guint64 code; /**< section's code */ + guint64 length; /**< section's length in blocks */ }; /** * Block of data in statfile */ struct stat_file_block { - guint32 hash1; /**< hash1 (also acts as index) */ - guint32 hash2; /**< hash2 */ - double value; /**< double value */ + guint32 hash1; /**< hash1 (also acts as index) */ + guint32 hash2; /**< hash2 */ + double value; /**< double value */ }; /** * Statistic file */ struct stat_file { - struct stat_file_header header; /**< header */ - struct stat_file_section section; /**< first section */ - struct stat_file_block blocks[1]; /**< first block of data */ + struct stat_file_header header; /**< header */ + struct stat_file_section section; /**< first section */ + struct stat_file_block blocks[1]; /**< first block of data */ }; /** @@ -67,32 +67,32 @@ struct stat_file { */ typedef struct stat_file_s { #ifdef HAVE_PATH_MAX - gchar filename[PATH_MAX]; /**< name of file */ + gchar filename[PATH_MAX]; /**< name of file */ #else - gchar filename[MAXPATHLEN]; /**< name of file */ + gchar filename[MAXPATHLEN]; /**< name of file */ #endif - gint fd; /**< descriptor */ - void *map; /**< mmaped area */ - off_t seek_pos; /**< current seek position */ - struct stat_file_section cur_section; /**< current section */ - time_t open_time; /**< time when file was opened */ - time_t access_time; /**< last access time */ - size_t len; /**< length of file(in bytes) */ - rspamd_mempool_mutex_t *lock; /**< mutex */ + gint fd; /**< descriptor */ + void *map; /**< mmaped area */ + off_t seek_pos; /**< current seek position */ + struct stat_file_section cur_section; /**< current section */ + time_t open_time; /**< time when file was opened */ + time_t access_time; /**< last access time */ + size_t len; /**< length of file(in bytes) */ + rspamd_mempool_mutex_t *lock; /**< mutex */ } stat_file_t; /** * Statfiles pool */ typedef struct statfile_pool_s { - stat_file_t *files; /**< hash table of opened files indexed by name */ - void **maps; /**< shared hash table of mmaped areas indexed by name */ - gint opened; /**< number of opened files */ - rspamd_mempool_t *pool; /**< memory pool object */ - rspamd_mempool_mutex_t *lock; /**< mutex */ - struct event *invalidate_event; /**< event for pool invalidation */ + stat_file_t *files; /**< hash table of opened files indexed by name */ + void **maps; /**< shared hash table of mmaped areas indexed by name */ + gint opened; /**< number of opened files */ + rspamd_mempool_t *pool; /**< memory pool object */ + rspamd_mempool_mutex_t *lock; /**< mutex */ + struct event *invalidate_event; /**< event for pool invalidation */ struct timeval invalidate_tv; - gboolean mlock_ok; /**< whether it is possible to use mlock (2) to avoid statfiles unloading */ + gboolean mlock_ok; /**< whether it is possible to use mlock (2) to avoid statfiles unloading */ } statfile_pool_t; /* Forwarded declarations */ @@ -104,7 +104,8 @@ struct rspamd_statfile_config; * @param max_size maximum size * @return statfile pool object */ -statfile_pool_t* statfile_pool_new (rspamd_mempool_t *pool, gboolean use_mlock); +statfile_pool_t * statfile_pool_new (rspamd_mempool_t *pool, + gboolean use_mlock); /** * Open statfile and attach it to pool @@ -112,7 +113,10 @@ statfile_pool_t* statfile_pool_new (rspamd_mempool_t *pool, gboolean use_mlock); * @param filename name of statfile to open * @return 0 if specified statfile is attached and -1 in case of error */ -stat_file_t* statfile_pool_open (statfile_pool_t *pool, gchar *filename, size_t len, gboolean forced); +stat_file_t * statfile_pool_open (statfile_pool_t *pool, + gchar *filename, + size_t len, + gboolean forced); /** * Create new statfile but DOES NOT attach it to pool, use @see statfile_pool_open for attaching @@ -130,7 +134,9 @@ gint statfile_pool_create (statfile_pool_t *pool, gchar *filename, size_t len); * @param remove_hash remove filename from opened files hash also * @return 0 if file was closed and -1 if statfile was not opened */ -gint statfile_pool_close (statfile_pool_t *pool, stat_file_t *file, gboolean keep_sorted); +gint statfile_pool_close (statfile_pool_t *pool, + stat_file_t *file, + gboolean keep_sorted); /** * Delete statfile pool and close all attached statfiles @@ -167,7 +173,11 @@ void statfile_pool_unlock_file (statfile_pool_t *pool, stat_file_t *file); * @param now current time * @return block value or 0 if block is not found */ -double statfile_pool_get_block (statfile_pool_t *pool, stat_file_t *file, guint32 h1, guint32 h2, time_t now); +double statfile_pool_get_block (statfile_pool_t *pool, + stat_file_t *file, + guint32 h1, + guint32 h2, + time_t now); /** * Set specified block in statfile @@ -178,7 +188,12 @@ double statfile_pool_get_block (statfile_pool_t *pool, stat_file_t *file, guint3 * @param now current time * @param value value of block */ -void statfile_pool_set_block (statfile_pool_t *pool, stat_file_t *file, guint32 h1, guint32 h2, time_t now, double value); +void statfile_pool_set_block (statfile_pool_t *pool, + stat_file_t *file, + guint32 h1, + guint32 h2, + time_t now, + double value); /** * Check whether statfile is opened @@ -186,7 +201,7 @@ void statfile_pool_set_block (statfile_pool_t *pool, stat_file_t *file, guint32 * @param filename name of statfile * @return TRUE if specified statfile is opened and FALSE otherwise */ -stat_file_t* statfile_pool_is_open (statfile_pool_t *pool, gchar *filename); +stat_file_t * statfile_pool_is_open (statfile_pool_t *pool, gchar *filename); /** * Returns current statfile section @@ -204,7 +219,10 @@ guint32 statfile_pool_get_section (statfile_pool_t *pool, stat_file_t *file); * @param from_begin search for section from begin of file if true * @return TRUE if section was set and FALSE otherwise */ -gboolean statfile_pool_set_section (statfile_pool_t *pool, stat_file_t *file, guint32 code, gboolean from_begin); +gboolean statfile_pool_set_section (statfile_pool_t *pool, + stat_file_t *file, + guint32 code, + gboolean from_begin); /** * Add new section to statfile @@ -214,7 +232,10 @@ gboolean statfile_pool_set_section (statfile_pool_t *pool, stat_file_t *file, gu * @param length length in blocks of new section * @return TRUE if section was successfully added and FALSE in case of error */ -gboolean statfile_pool_add_section (statfile_pool_t *pool, stat_file_t *file, guint32 code, guint64 length); +gboolean statfile_pool_add_section (statfile_pool_t *pool, + stat_file_t *file, + guint32 code, + guint64 length); /** @@ -268,7 +289,9 @@ guint64 statfile_get_total_blocks (stat_file_t *file); /** * Plan statfile pool invalidation */ -void statfile_pool_plan_invalidate (statfile_pool_t *pool, time_t seconds, time_t jitter); +void statfile_pool_plan_invalidate (statfile_pool_t *pool, + time_t seconds, + time_t jitter); /** * Get a statfile by symbol @@ -278,7 +301,10 @@ void statfile_pool_plan_invalidate (statfile_pool_t *pool, time_t seconds, time_ * @param st statfile to get * @param try_create whether we need to create statfile if it is absent */ -stat_file_t* get_statfile_by_symbol (statfile_pool_t *pool, struct rspamd_classifier_config *ccf, - const gchar *symbol, struct rspamd_statfile_config **st, gboolean try_create); +stat_file_t * get_statfile_by_symbol (statfile_pool_t *pool, + struct rspamd_classifier_config *ccf, + const gchar *symbol, + struct rspamd_statfile_config **st, + gboolean try_create); #endif diff --git a/src/libserver/statfile_sync.c b/src/libserver/statfile_sync.c index 1121658fa..262176880 100644 --- a/src/libserver/statfile_sync.c +++ b/src/libserver/statfile_sync.c @@ -56,63 +56,69 @@ struct rspamd_sync_ctx { enum rspamd_sync_state state; gboolean is_busy; - guint64 new_rev; - guint64 new_time; - guint64 new_len; + guint64 new_rev; + guint64 new_time; + guint64 new_len; }; static void log_next_sync (const gchar *symbol, time_t delay) { - gchar outstr[200]; - time_t t; + gchar outstr[200]; + time_t t; struct tm *tmp; - gint r; + gint r; - t = time(NULL); + t = time (NULL); t += delay; - tmp = localtime(&t); + tmp = localtime (&t); if (tmp) { - r = rspamd_snprintf (outstr, sizeof (outstr), "statfile_sync: next sync of %s at ", symbol); - if ((r = strftime(outstr + r, sizeof(outstr) - r, "%T", tmp)) != 0) { + r = rspamd_snprintf (outstr, + sizeof (outstr), + "statfile_sync: next sync of %s at ", + symbol); + if ((r = strftime (outstr + r, sizeof(outstr) - r, "%T", tmp)) != 0) { msg_info (outstr); } } } -static gboolean +static gboolean parse_revision_line (struct rspamd_sync_ctx *ctx, f_str_t *in) { - guint i, state = 0; - gchar *p, *c, numbuf[sizeof("18446744073709551615")]; - guint64 *val; + guint i, state = 0; + gchar *p, *c, numbuf[sizeof("18446744073709551615")]; + guint64 *val; /* First of all try to find END line */ - if (in->len >= sizeof ("END") - 1 && memcmp (in->begin, "END", sizeof ("END") - 1) == 0) { + if (in->len >= sizeof ("END") - 1 && + memcmp (in->begin, "END", sizeof ("END") - 1) == 0) { ctx->state = SYNC_STATE_QUIT; ctx->is_busy = FALSE; return TRUE; } /* Next check for error line */ - if (in->len >= sizeof ("FAIL") - 1 && memcmp (in->begin, "FAIL", sizeof ("FAIL") - 1) == 0) { + if (in->len >= sizeof ("FAIL") - 1 && + memcmp (in->begin, "FAIL", sizeof ("FAIL") - 1) == 0) { ctx->state = SYNC_STATE_QUIT; ctx->is_busy = FALSE; return TRUE; } - + /* Now try to extract 3 numbers from string: revision, time and length */ p = in->begin; val = &ctx->new_rev; - for (i = 0; i < in->len; i ++, p ++) { + for (i = 0; i < in->len; i++, p++) { if (g_ascii_isspace (*p) || i == in->len - 1) { if (state == 1) { if (i == in->len - 1) { /* One more character */ - p ++; + p++; } - rspamd_strlcpy (numbuf, c, MIN (p - c + 1, (gint)sizeof (numbuf))); + rspamd_strlcpy (numbuf, c, MIN (p - c + 1, + (gint)sizeof (numbuf))); errno = 0; *val = strtoull (numbuf, NULL, 10); if (errno != 0) { @@ -144,94 +150,113 @@ parse_revision_line (struct rspamd_sync_ctx *ctx, f_str_t *in) return ((val == &ctx->new_len)); } -static gboolean +static gboolean read_blocks (struct rspamd_sync_ctx *ctx, f_str_t *in) { struct rspamd_binlog_element *elt; - guint i; - + guint i; + statfile_pool_lock_file (ctx->pool, ctx->real_statfile); elt = (struct rspamd_binlog_element *)in->begin; - for (i = 0; i < in->len / sizeof (struct rspamd_binlog_element); i ++, elt ++) { - statfile_pool_set_block (ctx->pool, ctx->real_statfile, elt->h1, elt->h2, ctx->new_time, elt->value); + for (i = 0; i < in->len / sizeof (struct rspamd_binlog_element); i++, + elt++) { + statfile_pool_set_block (ctx->pool, + ctx->real_statfile, + elt->h1, + elt->h2, + ctx->new_time, + elt->value); } statfile_pool_unlock_file (ctx->pool, ctx->real_statfile); return TRUE; } -static gboolean +static gboolean sync_read (f_str_t * in, void *arg) { struct rspamd_sync_ctx *ctx = arg; - gchar buf[256]; - guint64 rev = 0; - time_t ti = 0; + gchar buf[256]; + guint64 rev = 0; + time_t ti = 0; if (in->len == 0) { /* Skip empty lines */ return TRUE; } switch (ctx->state) { - case SYNC_STATE_GREETING: - /* Skip greeting line and write sync command */ - /* Write initial data */ - statfile_get_revision (ctx->real_statfile, &rev, &ti); - rev = rspamd_snprintf (buf, sizeof (buf), "sync %s %uL %T" CRLF, ctx->st->symbol, rev, ti); - ctx->state = SYNC_STATE_READ_LINE; - return rspamd_dispatcher_write (ctx->dispatcher, buf, rev, FALSE, FALSE); - break; - case SYNC_STATE_READ_LINE: - /* Try to parse line from server */ - if (!parse_revision_line (ctx, in)) { - msg_info ("cannot parse line of length %z: '%*s'", in->len, (gint)in->len, in->begin); - close (ctx->sock); - rspamd_remove_dispatcher (ctx->dispatcher); - ctx->is_busy = FALSE; - return FALSE; - } - else if (ctx->state != SYNC_STATE_QUIT) { - if (ctx->new_len > 0) { - ctx->state = SYNC_STATE_READ_REV; - rspamd_set_dispatcher_policy (ctx->dispatcher, BUFFER_CHARACTER, ctx->new_len); - } - } - else { - /* Quit this session */ - msg_info ("sync ended for: %s", ctx->st->symbol); - close (ctx->sock); - rspamd_remove_dispatcher (ctx->dispatcher); - ctx->is_busy = FALSE; - /* Immediately return from callback */ - return FALSE; - } - break; - case SYNC_STATE_READ_REV: - /* In now contains all blocks of specified revision, so we can read them directly */ - if (!read_blocks (ctx, in)) { - msg_info ("cannot read blocks"); - close (ctx->sock); - rspamd_remove_dispatcher (ctx->dispatcher); - ctx->is_busy = FALSE; - return FALSE; + case SYNC_STATE_GREETING: + /* Skip greeting line and write sync command */ + /* Write initial data */ + statfile_get_revision (ctx->real_statfile, &rev, &ti); + rev = rspamd_snprintf (buf, + sizeof (buf), + "sync %s %uL %T" CRLF, + ctx->st->symbol, + rev, + ti); + ctx->state = SYNC_STATE_READ_LINE; + return rspamd_dispatcher_write (ctx->dispatcher, buf, rev, FALSE, + FALSE); + break; + case SYNC_STATE_READ_LINE: + /* Try to parse line from server */ + if (!parse_revision_line (ctx, in)) { + msg_info ("cannot parse line of length %z: '%*s'", + in->len, + (gint)in->len, + in->begin); + close (ctx->sock); + rspamd_remove_dispatcher (ctx->dispatcher); + ctx->is_busy = FALSE; + return FALSE; + } + else if (ctx->state != SYNC_STATE_QUIT) { + if (ctx->new_len > 0) { + ctx->state = SYNC_STATE_READ_REV; + rspamd_set_dispatcher_policy (ctx->dispatcher, + BUFFER_CHARACTER, + ctx->new_len); } - statfile_set_revision (ctx->real_statfile, ctx->new_rev, ctx->new_time); - msg_info ("set new revision: %uL, readed %z bytes", ctx->new_rev, in->len); - /* Now try to read other revision or END line */ - ctx->state = SYNC_STATE_READ_LINE; - rspamd_set_dispatcher_policy (ctx->dispatcher, BUFFER_LINE, 0); - break; - case SYNC_STATE_QUIT: + } + else { + /* Quit this session */ + msg_info ("sync ended for: %s", ctx->st->symbol); close (ctx->sock); rspamd_remove_dispatcher (ctx->dispatcher); ctx->is_busy = FALSE; + /* Immediately return from callback */ return FALSE; + } + break; + case SYNC_STATE_READ_REV: + /* In now contains all blocks of specified revision, so we can read them directly */ + if (!read_blocks (ctx, in)) { + msg_info ("cannot read blocks"); + close (ctx->sock); + rspamd_remove_dispatcher (ctx->dispatcher); + ctx->is_busy = FALSE; + return FALSE; + } + statfile_set_revision (ctx->real_statfile, ctx->new_rev, ctx->new_time); + msg_info ("set new revision: %uL, readed %z bytes", + ctx->new_rev, + in->len); + /* Now try to read other revision or END line */ + ctx->state = SYNC_STATE_READ_LINE; + rspamd_set_dispatcher_policy (ctx->dispatcher, BUFFER_LINE, 0); + break; + case SYNC_STATE_QUIT: + close (ctx->sock); + rspamd_remove_dispatcher (ctx->dispatcher); + ctx->is_busy = FALSE; + return FALSE; } return TRUE; } -static void +static void sync_err (GError *err, void *arg) { struct rspamd_sync_ctx *ctx = arg; @@ -248,30 +273,40 @@ sync_timer_callback (gint fd, short what, void *ud) { struct rspamd_sync_ctx *ctx = ud; guint32 jittered_interval; - + /* Plan new event */ evtimer_del (&ctx->tm_ev); /* Add some jittering for synchronization */ - jittered_interval = g_random_int_range (ctx->sync_interval, ctx->sync_interval * 2); + jittered_interval = g_random_int_range (ctx->sync_interval, + ctx->sync_interval * 2); msec_to_tv (jittered_interval, &ctx->interval); evtimer_add (&ctx->tm_ev, &ctx->interval); log_next_sync (ctx->st->symbol, ctx->interval.tv_sec); - + if (ctx->is_busy) { /* Sync is in progress */ msg_info ("syncronization process is in progress, do not start new one"); return; } - if ((ctx->sock = make_universal_socket (ctx->st->binlog->master_addr, ctx->st->binlog->master_port, - SOCK_STREAM, TRUE, FALSE, TRUE)) == -1) { + if ((ctx->sock = + make_universal_socket (ctx->st->binlog->master_addr, + ctx->st->binlog->master_port, + SOCK_STREAM, TRUE, FALSE, TRUE)) == -1) { msg_info ("cannot connect to %s", ctx->st->binlog->master_addr); return; } /* Now create and activate dispatcher */ msec_to_tv (ctx->timeout, &ctx->io_tv); - ctx->dispatcher = rspamd_create_dispatcher (ctx->ev_base, ctx->sock, BUFFER_LINE, sync_read, NULL, sync_err, &ctx->io_tv, ctx); - + ctx->dispatcher = rspamd_create_dispatcher (ctx->ev_base, + ctx->sock, + BUFFER_LINE, + sync_read, + NULL, + sync_err, + &ctx->io_tv, + ctx); + ctx->state = SYNC_STATE_GREETING; ctx->is_busy = TRUE; @@ -280,29 +315,39 @@ sync_timer_callback (gint fd, short what, void *ud) } static gboolean -add_statfile_watch (statfile_pool_t *pool, struct rspamd_statfile_config *st, struct rspamd_config *cfg, struct event_base *ev_base) +add_statfile_watch (statfile_pool_t *pool, + struct rspamd_statfile_config *st, + struct rspamd_config *cfg, + struct event_base *ev_base) { struct rspamd_sync_ctx *ctx; guint32 jittered_interval; - + if (st->binlog->master_addr != NULL) { - ctx = rspamd_mempool_alloc (pool->pool, sizeof (struct rspamd_sync_ctx)); + ctx = + rspamd_mempool_alloc (pool->pool, sizeof (struct rspamd_sync_ctx)); ctx->st = st; ctx->timeout = cfg->statfile_sync_timeout; ctx->sync_interval = cfg->statfile_sync_interval; ctx->ev_base = ev_base; /* Add some jittering for synchronization */ - jittered_interval = g_random_int_range (ctx->sync_interval, ctx->sync_interval * 2); + jittered_interval = g_random_int_range (ctx->sync_interval, + ctx->sync_interval * 2); msec_to_tv (jittered_interval, &ctx->interval); /* Open statfile and attach it to pool */ - if ((ctx->real_statfile = statfile_pool_is_open (pool, st->path)) == NULL) { - if ((ctx->real_statfile = statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { + if ((ctx->real_statfile = + statfile_pool_is_open (pool, st->path)) == NULL) { + if ((ctx->real_statfile = + statfile_pool_open (pool, st->path, st->size, FALSE)) == NULL) { msg_warn ("cannot open %s", st->path); if (statfile_pool_create (pool, st->path, st->size) == -1) { msg_err ("cannot create statfile %s", st->path); return FALSE; } - ctx->real_statfile = statfile_pool_open (pool, st->path, st->size, FALSE); + ctx->real_statfile = statfile_pool_open (pool, + st->path, + st->size, + FALSE); } } /* Now plan event for it's future executing */ @@ -312,21 +357,24 @@ add_statfile_watch (statfile_pool_t *pool, struct rspamd_statfile_config *st, st log_next_sync (st->symbol, ctx->interval.tv_sec); } else { - msg_err ("cannot add statfile watch for statfile %s: no master defined", st->symbol); + msg_err ("cannot add statfile watch for statfile %s: no master defined", + st->symbol); return FALSE; } return TRUE; } -gboolean -start_statfile_sync (statfile_pool_t *pool, struct rspamd_config *cfg, struct event_base *ev_base) +gboolean +start_statfile_sync (statfile_pool_t *pool, + struct rspamd_config *cfg, + struct event_base *ev_base) { GList *cur, *l; struct rspamd_classifier_config *cl; struct rspamd_statfile_config *st; - /* + /* * First of all walk through all classifiers and find those statfiles * for which we should do sync (slave affinity) */ diff --git a/src/libserver/statfile_sync.h b/src/libserver/statfile_sync.h index bcaeb3bb5..be2550d7b 100644 --- a/src/libserver/statfile_sync.h +++ b/src/libserver/statfile_sync.h @@ -9,6 +9,8 @@ /* * Start synchronization of statfiles. Must be called after event_init as it adds events */ -gboolean start_statfile_sync (statfile_pool_t *pool, struct rspamd_config *cfg, struct event_base *ev_base); +gboolean start_statfile_sync (statfile_pool_t *pool, + struct rspamd_config *cfg, + struct event_base *ev_base); #endif diff --git a/src/libserver/symbols_cache.c b/src/libserver/symbols_cache.c index b0ce7d872..75862b3b7 100644 --- a/src/libserver/symbols_cache.c +++ b/src/libserver/symbols_cache.c @@ -41,13 +41,13 @@ #define MIN_CACHE 17 -static guint64 total_frequency = 0; -static guint32 nsymbols = 0; +static guint64 total_frequency = 0; +static guint32 nsymbols = 0; gint cache_cmp (const void *p1, const void *p2) { - const struct cache_item *i1 = p1, *i2 = p2; + const struct cache_item *i1 = p1, *i2 = p2; return strcmp (i1->s->symbol, i2->s->symbol); } @@ -55,20 +55,24 @@ cache_cmp (const void *p1, const void *p2) gint cache_logic_cmp (const void *p1, const void *p2) { - const struct cache_item *i1 = p1, *i2 = p2; - double w1, w2; - double weight1, weight2; - double f1 = 0, f2 = 0; + const struct cache_item *i1 = p1, *i2 = p2; + double w1, w2; + double weight1, weight2; + double f1 = 0, f2 = 0; if (i1->priority == 0 && i2->priority == 0) { if (total_frequency > 0) { - f1 = ((double)i1->s->frequency * nsymbols) / (double)total_frequency; - f2 = ((double)i2->s->frequency * nsymbols) / (double)total_frequency; + f1 = + ((double)i1->s->frequency * nsymbols) / (double)total_frequency; + f2 = + ((double)i2->s->frequency * nsymbols) / (double)total_frequency; } weight1 = i1->metric_weight == 0 ? i1->s->weight : i1->metric_weight; weight2 = i2->metric_weight == 0 ? i2->s->weight : i2->metric_weight; - w1 = abs (weight1) * WEIGHT_MULT + f1 * FREQUENCY_MULT + i1->s->avg_time * TIME_MULT; - w2 = abs (weight2) * WEIGHT_MULT + f2 * FREQUENCY_MULT + i2->s->avg_time * TIME_MULT; + w1 = abs (weight1) * WEIGHT_MULT + f1 * FREQUENCY_MULT + + i1->s->avg_time * TIME_MULT; + w2 = abs (weight2) * WEIGHT_MULT + f2 * FREQUENCY_MULT + + i2->s->avg_time * TIME_MULT; } else { /* Strict sorting */ @@ -79,12 +83,12 @@ cache_logic_cmp (const void *p1, const void *p2) return (gint)w2 - w1; } -static GChecksum * +static GChecksum * get_mem_cksum (struct symbols_cache *cache) { - GChecksum *result; - GList *cur, *l; - struct cache_item *item; + GChecksum *result; + GList *cur, *l; + struct cache_item *item; result = g_checksum_new (G_CHECKSUM_SHA1); @@ -94,7 +98,8 @@ get_mem_cksum (struct symbols_cache *cache) while (cur) { item = cur->data; if (item->s->symbol[0] != '\0') { - g_checksum_update (result, item->s->symbol, strlen (item->s->symbol)); + g_checksum_update (result, item->s->symbol, + strlen (item->s->symbol)); } cur = g_list_next (cur); } @@ -107,7 +112,8 @@ get_mem_cksum (struct symbols_cache *cache) while (cur) { item = cur->data; if (item->s->symbol[0] != '\0') { - g_checksum_update (result, item->s->symbol, strlen (item->s->symbol)); + g_checksum_update (result, item->s->symbol, + strlen (item->s->symbol)); } total_frequency += item->s->frequency; cur = g_list_next (cur); @@ -121,8 +127,8 @@ get_mem_cksum (struct symbols_cache *cache) static void post_cache_init (struct symbols_cache *cache) { - GList *cur; - struct cache_item *item; + GList *cur; + struct cache_item *item; total_frequency = 0; nsymbols = cache->used_items; @@ -139,7 +145,8 @@ post_cache_init (struct symbols_cache *cache) cur = g_list_next (cur); } - cache->negative_items = g_list_sort (cache->negative_items, cache_logic_cmp); + cache->negative_items = + g_list_sort (cache->negative_items, cache_logic_cmp); cache->static_items = g_list_sort (cache->static_items, cache_logic_cmp); } @@ -147,22 +154,27 @@ post_cache_init (struct symbols_cache *cache) static void unmap_cache_file (gpointer arg) { - struct symbols_cache *cache = arg; - + struct symbols_cache *cache = arg; + /* A bit ugly usage */ munmap (cache->map, cache->used_items * sizeof (struct saved_cache_item)); } -static gboolean +static gboolean mmap_cache_file (struct symbols_cache *cache, gint fd, rspamd_mempool_t *pool) { - guint8 *map; - gint i; - GList *cur; - struct cache_item *item; + guint8 *map; + gint i; + GList *cur; + struct cache_item *item; if (cache->used_items > 0) { - map = mmap (NULL, cache->used_items * sizeof (struct saved_cache_item), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + map = mmap (NULL, + cache->used_items * sizeof (struct saved_cache_item), + PROT_READ | PROT_WRITE, + MAP_SHARED, + fd, + 0); if (map == MAP_FAILED) { msg_err ("cannot mmap cache file: %d, %s", errno, strerror (errno)); close (fd); @@ -176,16 +188,20 @@ mmap_cache_file (struct symbols_cache *cache, gint fd, rspamd_mempool_t *pool) cur = g_list_first (cache->negative_items); while (cur) { item = cur->data; - item->s = (struct saved_cache_item *)(map + i * sizeof (struct saved_cache_item)); + item->s = + (struct saved_cache_item *)(map + i * + sizeof (struct saved_cache_item)); cur = g_list_next (cur); - i ++; + i++; } cur = g_list_first (cache->static_items); while (cur) { item = cur->data; - item->s = (struct saved_cache_item *)(map + i * sizeof (struct saved_cache_item)); + item->s = + (struct saved_cache_item *)(map + i * + sizeof (struct saved_cache_item)); cur = g_list_next (cur); - i ++; + i++; } post_cache_init (cache); @@ -195,14 +211,17 @@ mmap_cache_file (struct symbols_cache *cache, gint fd, rspamd_mempool_t *pool) } /* Fd must be opened for writing, after creating file is mmapped */ -static gboolean -create_cache_file (struct symbols_cache *cache, const gchar *filename, gint fd, rspamd_mempool_t *pool) +static gboolean +create_cache_file (struct symbols_cache *cache, + const gchar *filename, + gint fd, + rspamd_mempool_t *pool) { - GChecksum *cksum; - u_char *digest; - gsize cklen; - GList *cur; - struct cache_item *item; + GChecksum *cksum; + u_char *digest; + gsize cklen; + GList *cur; + struct cache_item *item; /* Calculate checksum */ cksum = get_mem_cksum (cache); @@ -269,23 +288,33 @@ enum rspamd_symbol_type { }; static void -register_symbol_common (struct symbols_cache **cache, const gchar *name, double weight, gint priority, - symbol_func_t func, gpointer user_data, enum rspamd_symbol_type type) +register_symbol_common (struct symbols_cache **cache, + const gchar *name, + double weight, + gint priority, + symbol_func_t func, + gpointer user_data, + enum rspamd_symbol_type type) { - struct cache_item *item = NULL; - struct symbols_cache *pcache = *cache; - GList **target; - double *w; + struct cache_item *item = NULL; + struct symbols_cache *pcache = *cache; + GList **target; + double *w; if (*cache == NULL) { pcache = g_new0 (struct symbols_cache, 1); *cache = pcache; - pcache->static_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); - pcache->items_by_symbol = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); + pcache->static_pool = + rspamd_mempool_new (rspamd_mempool_suggest_size ()); + pcache->items_by_symbol = g_hash_table_new (rspamd_str_hash, + rspamd_str_equal); } - - item = rspamd_mempool_alloc0 (pcache->static_pool, sizeof (struct cache_item)); - item->s = rspamd_mempool_alloc0 (pcache->static_pool, sizeof (struct saved_cache_item)); + + item = rspamd_mempool_alloc0 (pcache->static_pool, + sizeof (struct cache_item)); + item->s = + rspamd_mempool_alloc0 (pcache->static_pool, + sizeof (struct saved_cache_item)); rspamd_strlcpy (item->s->symbol, name, sizeof (item->s->symbol)); item->func = func; item->user_data = user_data; @@ -303,7 +332,10 @@ register_symbol_common (struct symbols_cache **cache, const gchar *name, double } /* Handle weight using default metric */ - if (pcache->cfg && pcache->cfg->default_metric && (w = g_hash_table_lookup (pcache->cfg->default_metric->symbols, name)) != NULL) { + if (pcache->cfg && pcache->cfg->default_metric && + (w = + g_hash_table_lookup (pcache->cfg->default_metric->symbols, + name)) != NULL) { item->s->weight = weight * (*w); } else { @@ -339,58 +371,100 @@ register_symbol_common (struct symbols_cache **cache, const gchar *name, double void register_symbol (struct symbols_cache **cache, const gchar *name, double weight, - symbol_func_t func, gpointer user_data) + symbol_func_t func, gpointer user_data) { - register_symbol_common (cache, name, weight, 0, func, user_data, SYMBOL_TYPE_NORMAL); + register_symbol_common (cache, + name, + weight, + 0, + func, + user_data, + SYMBOL_TYPE_NORMAL); } void -register_virtual_symbol (struct symbols_cache **cache, const gchar *name, double weight) +register_virtual_symbol (struct symbols_cache **cache, + const gchar *name, + double weight) { - register_symbol_common (cache, name, weight, 0, NULL, NULL, SYMBOL_TYPE_VIRTUAL); + register_symbol_common (cache, + name, + weight, + 0, + NULL, + NULL, + SYMBOL_TYPE_VIRTUAL); } void -register_callback_symbol (struct symbols_cache **cache, const gchar *name, double weight, - symbol_func_t func, gpointer user_data) +register_callback_symbol (struct symbols_cache **cache, + const gchar *name, + double weight, + symbol_func_t func, + gpointer user_data) { - register_symbol_common (cache, name, weight, 0, func, user_data, SYMBOL_TYPE_CALLBACK); + register_symbol_common (cache, + name, + weight, + 0, + func, + user_data, + SYMBOL_TYPE_CALLBACK); } void -register_callback_symbol_priority (struct symbols_cache **cache, const gchar *name, double weight, gint priority, - symbol_func_t func, gpointer user_data) +register_callback_symbol_priority (struct symbols_cache **cache, + const gchar *name, + double weight, + gint priority, + symbol_func_t func, + gpointer user_data) { - register_symbol_common (cache, name, weight, priority, func, user_data, SYMBOL_TYPE_CALLBACK); + register_symbol_common (cache, + name, + weight, + priority, + func, + user_data, + SYMBOL_TYPE_CALLBACK); } void -register_dynamic_symbol (rspamd_mempool_t *dynamic_pool, struct symbols_cache **cache, - const gchar *name, double weight, symbol_func_t func, - gpointer user_data, GList *networks) +register_dynamic_symbol (rspamd_mempool_t *dynamic_pool, + struct symbols_cache **cache, + const gchar *name, + double weight, + symbol_func_t func, + gpointer user_data, + GList *networks) { - struct cache_item *item = NULL; - struct symbols_cache *pcache = *cache; - GList *t, *cur; - uintptr_t r; - double *w; - guint32 mask = 0xFFFFFFFF; - struct dynamic_map_item *it; - gint rr; + struct cache_item *item = NULL; + struct symbols_cache *pcache = *cache; + GList *t, *cur; + uintptr_t r; + double *w; + guint32 mask = 0xFFFFFFFF; + struct dynamic_map_item *it; + gint rr; if (*cache == NULL) { pcache = g_new0 (struct symbols_cache, 1); *cache = pcache; - pcache->static_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + pcache->static_pool = + rspamd_mempool_new (rspamd_mempool_suggest_size ()); } - + item = rspamd_mempool_alloc0 (dynamic_pool, sizeof (struct cache_item)); - item->s = rspamd_mempool_alloc (dynamic_pool, sizeof (struct saved_cache_item)); + item->s = + rspamd_mempool_alloc (dynamic_pool, sizeof (struct saved_cache_item)); rspamd_strlcpy (item->s->symbol, name, sizeof (item->s->symbol)); item->func = func; item->user_data = user_data; /* Handle weight using default metric */ - if (pcache->cfg && pcache->cfg->default_metric && (w = g_hash_table_lookup (pcache->cfg->default_metric->symbols, name)) != NULL) { + if (pcache->cfg && pcache->cfg->default_metric && + (w = + g_hash_table_lookup (pcache->cfg->default_metric->symbols, + name)) != NULL) { item->s->weight = weight * (*w); } else { @@ -402,7 +476,7 @@ register_dynamic_symbol (rspamd_mempool_t *dynamic_pool, struct symbols_cache ** pcache->used_items++; msg_debug ("used items: %d, added symbol: %s", (*cache)->used_items, name); rspamd_set_counter (item->s->symbol, 0); - + g_hash_table_insert (pcache->items_by_symbol, item->s->symbol, item); if (networks == NULL) { @@ -420,50 +494,81 @@ register_dynamic_symbol (rspamd_mempool_t *dynamic_pool, struct symbols_cache ** r = ntohl (it->addr.s_addr & mask); if (it->negative) { /* For negatve items insert into list and into negative cache map */ - if ((r = radix32tree_find (pcache->negative_dynamic_map, r)) != RADIX_NO_VALUE) { + if ((r = + radix32tree_find (pcache->negative_dynamic_map, + r)) != RADIX_NO_VALUE) { t = (GList *)((gpointer)r); t = g_list_prepend (t, item); /* Replace pointers in radix tree and in destructor function */ - rspamd_mempool_replace_destructor (dynamic_pool, (rspamd_mempool_destruct_t)g_list_free, (gpointer)r, t); - rr = radix32tree_replace (pcache->negative_dynamic_map, ntohl (it->addr.s_addr), mask, (uintptr_t)t); + rspamd_mempool_replace_destructor (dynamic_pool, + (rspamd_mempool_destruct_t)g_list_free, (gpointer)r, t); + rr = radix32tree_replace (pcache->negative_dynamic_map, + ntohl (it->addr.s_addr), + mask, + (uintptr_t)t); if (rr == -1) { - msg_warn ("cannot replace ip to tree: %s, mask %X", inet_ntoa (it->addr), mask); + msg_warn ("cannot replace ip to tree: %s, mask %X", + inet_ntoa (it->addr), + mask); } } else { t = g_list_prepend (NULL, item); - rspamd_mempool_add_destructor (dynamic_pool, (rspamd_mempool_destruct_t)g_list_free, t); - rr = radix32tree_insert (pcache->negative_dynamic_map, ntohl (it->addr.s_addr), mask, (uintptr_t)t); + rspamd_mempool_add_destructor (dynamic_pool, + (rspamd_mempool_destruct_t)g_list_free, t); + rr = radix32tree_insert (pcache->negative_dynamic_map, + ntohl (it->addr.s_addr), + mask, + (uintptr_t)t); if (rr == -1) { - msg_warn ("cannot insert ip to tree: %s, mask %X", inet_ntoa (it->addr), mask); + msg_warn ("cannot insert ip to tree: %s, mask %X", + inet_ntoa (it->addr), + mask); } else if (rr == 1) { - msg_warn ("ip %s, mask %X, value already exists", inet_ntoa (it->addr), mask); + msg_warn ("ip %s, mask %X, value already exists", + inet_ntoa (it->addr), + mask); } } /* Insert into list */ - pcache->dynamic_items = g_list_prepend (pcache->dynamic_items, item); + pcache->dynamic_items = g_list_prepend (pcache->dynamic_items, + item); } else { - if ((r = radix32tree_find (pcache->dynamic_map, r)) != RADIX_NO_VALUE) { + if ((r = + radix32tree_find (pcache->dynamic_map, + r)) != RADIX_NO_VALUE) { t = (GList *)((gpointer)r); t = g_list_prepend (t, item); /* Replace pointers in radix tree and in destructor function */ - rspamd_mempool_replace_destructor (dynamic_pool, (rspamd_mempool_destruct_t)g_list_free, (gpointer)r, t); - rr = radix32tree_replace (pcache->dynamic_map, ntohl (it->addr.s_addr), mask, (uintptr_t)t); + rspamd_mempool_replace_destructor (dynamic_pool, + (rspamd_mempool_destruct_t)g_list_free, (gpointer)r, t); + rr = + radix32tree_replace (pcache->dynamic_map, + ntohl (it->addr.s_addr), mask, (uintptr_t)t); if (rr == -1) { - msg_warn ("cannot replace ip to tree: %s, mask %X", inet_ntoa (it->addr), mask); + msg_warn ("cannot replace ip to tree: %s, mask %X", + inet_ntoa (it->addr), + mask); } } else { t = g_list_prepend (NULL, item); - rspamd_mempool_add_destructor (dynamic_pool, (rspamd_mempool_destruct_t)g_list_free, t); - rr = radix32tree_insert (pcache->dynamic_map, ntohl (it->addr.s_addr), mask, (uintptr_t)t); + rspamd_mempool_add_destructor (dynamic_pool, + (rspamd_mempool_destruct_t)g_list_free, t); + rr = + radix32tree_insert (pcache->dynamic_map, + ntohl (it->addr.s_addr), mask, (uintptr_t)t); if (rr == -1) { - msg_warn ("cannot insert ip to tree: %s, mask %X", inet_ntoa (it->addr), mask); + msg_warn ("cannot insert ip to tree: %s, mask %X", + inet_ntoa (it->addr), + mask); } else if (rr == 1) { - msg_warn ("ip %s, mask %X, value already exists", inet_ntoa (it->addr), mask); + msg_warn ("ip %s, mask %X, value already exists", + inet_ntoa (it->addr), + mask); } } } @@ -493,8 +598,8 @@ remove_dynamic_rules (struct symbols_cache *cache) static void free_cache (gpointer arg) { - struct symbols_cache *cache = arg; - + struct symbols_cache *cache = arg; + if (cache->map != NULL) { unmap_cache_file (cache); } @@ -521,15 +626,18 @@ free_cache (gpointer arg) } gboolean -init_symbols_cache (rspamd_mempool_t * pool, struct symbols_cache *cache, struct rspamd_config *cfg, - const gchar *filename, gboolean ignore_checksum) +init_symbols_cache (rspamd_mempool_t * pool, + struct symbols_cache *cache, + struct rspamd_config *cfg, + const gchar *filename, + gboolean ignore_checksum) { - struct stat st; - gint fd; - GChecksum *cksum; - u_char *mem_sum, *file_sum; - gsize cklen; - gboolean res; + struct stat st; + gint fd; + GChecksum *cksum; + u_char *mem_sum, *file_sum; + gsize cklen; + gboolean res; if (cache == NULL) { return FALSE; @@ -545,14 +653,19 @@ init_symbols_cache (rspamd_mempool_t * pool, struct symbols_cache *cache, struct post_cache_init (cache); return TRUE; } - + /* First of all try to stat file */ if (stat (filename, &st) == -1) { /* Check errno */ if (errno == ENOENT) { /* Try to create file */ - if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) { - msg_info ("cannot create file %s, error %d, %s", filename, errno, strerror (errno)); + if ((fd = + open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | + S_IRUSR)) == -1) { + msg_info ("cannot create file %s, error %d, %s", + filename, + errno, + strerror (errno)); return FALSE; } else { @@ -560,13 +673,19 @@ init_symbols_cache (rspamd_mempool_t * pool, struct symbols_cache *cache, struct } } else { - msg_info ("cannot stat file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("cannot stat file %s, error %d, %s", + filename, + errno, + strerror (errno)); return FALSE; } } else { if ((fd = open (filename, O_RDWR)) == -1) { - msg_info ("cannot open file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("cannot open file %s, error %d, %s", + filename, + errno, + strerror (errno)); return FALSE; } } @@ -589,8 +708,13 @@ init_symbols_cache (rspamd_mempool_t * pool, struct symbols_cache *cache, struct if (errno == EINVAL) { /* Try to create file */ msg_info ("recreate cache file"); - if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) { - msg_info ("cannot create file %s, error %d, %s", filename, errno, strerror (errno)); + if ((fd = + open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | + S_IRUSR)) == -1) { + msg_info ("cannot create file %s, error %d, %s", + filename, + errno, + strerror (errno)); return FALSE; } else { @@ -600,7 +724,8 @@ init_symbols_cache (rspamd_mempool_t * pool, struct symbols_cache *cache, struct close (fd); g_free (mem_sum); g_checksum_free (cksum); - msg_err ("cannot seek to read checksum, %d, %s", errno, strerror (errno)); + msg_err ("cannot seek to read checksum, %d, %s", errno, + strerror (errno)); return FALSE; } file_sum = g_malloc (cklen); @@ -620,8 +745,13 @@ init_symbols_cache (rspamd_mempool_t * pool, struct symbols_cache *cache, struct g_checksum_free (cksum); msg_info ("checksum mismatch, recreating file"); /* Reopen with rw permissions */ - if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) { - msg_info ("cannot create file %s, error %d, %s", filename, errno, strerror (errno)); + if ((fd = + open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | + S_IRUSR)) == -1) { + msg_info ("cannot create file %s, error %d, %s", + filename, + errno, + strerror (errno)); return FALSE; } else { @@ -636,7 +766,9 @@ init_symbols_cache (rspamd_mempool_t * pool, struct symbols_cache *cache, struct /* MMap cache file and copy saved_cache structures */ res = mmap_cache_file (cache, fd, pool); - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t)free_cache, cache); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t)free_cache, + cache); return res; } @@ -648,10 +780,12 @@ check_dynamic_item (struct rspamd_task *task, struct symbols_cache *cache) /* TODO: radix doesn't support ipv6 addrs */ return NULL; #else - GList *res = NULL; - uintptr_t r; + GList *res = NULL; + uintptr_t r; if (cache->dynamic_map != NULL && task->from_addr.s_addr != INADDR_NONE) { - if ((r = radix32tree_find (cache->dynamic_map, ntohl (task->from_addr.s_addr))) != RADIX_NO_VALUE) { + if ((r = + radix32tree_find (cache->dynamic_map, + ntohl (task->from_addr.s_addr))) != RADIX_NO_VALUE) { res = (GList *)((gpointer)r); return res; } @@ -664,18 +798,23 @@ check_dynamic_item (struct rspamd_task *task, struct symbols_cache *cache) } static gboolean -check_negative_dynamic_item (struct rspamd_task *task, struct symbols_cache *cache, struct cache_item *item) +check_negative_dynamic_item (struct rspamd_task *task, + struct symbols_cache *cache, + struct cache_item *item) { #ifdef HAVE_INET_PTON /* TODO: radix doesn't support ipv6 addrs */ return FALSE; #else - GList *res = NULL; - uintptr_t r; - - if (cache->negative_dynamic_map != NULL && task->from_addr.s_addr != INADDR_NONE) { - if ((r = radix32tree_find (cache->negative_dynamic_map, ntohl (task->from_addr.s_addr))) != RADIX_NO_VALUE) { + GList *res = NULL; + uintptr_t r; + + if (cache->negative_dynamic_map != NULL && task->from_addr.s_addr != + INADDR_NONE) { + if ((r = + radix32tree_find (cache->negative_dynamic_map, + ntohl (task->from_addr.s_addr))) != RADIX_NO_VALUE) { res = (GList *)((gpointer)r); while (res) { if (res->data == (gpointer)item) { @@ -693,7 +832,7 @@ check_negative_dynamic_item (struct rspamd_task *task, struct symbols_cache *cac static gboolean check_debug_symbol (struct rspamd_config *cfg, const gchar *symbol) { - GList *cur; + GList *cur; cur = cfg->debug_symbols; while (cur) { @@ -736,11 +875,13 @@ rspamd_symbols_cache_metric_cb (gpointer k, gpointer v, gpointer ud) } gboolean -validate_cache (struct symbols_cache *cache, struct rspamd_config *cfg, gboolean strict) +validate_cache (struct symbols_cache *cache, + struct rspamd_config *cfg, + gboolean strict) { - struct cache_item *item; - GList *cur, *p, *metric_symbols; - gboolean res; + struct cache_item *item; + GList *cur, *p, *metric_symbols; + gboolean res; if (cache == NULL) { msg_err ("empty cache is invalid"); @@ -752,13 +893,16 @@ validate_cache (struct symbols_cache *cache, struct rspamd_config *cfg, gboolean while (cur) { item = cur->data; if (!item->is_callback) { - if (g_hash_table_lookup (cfg->metrics_symbols, item->s->symbol) == NULL) { + if (g_hash_table_lookup (cfg->metrics_symbols, + item->s->symbol) == NULL) { if (strict) { - msg_warn ("no weight registered for symbol %s", item->s->symbol); + msg_warn ("no weight registered for symbol %s", + item->s->symbol); return FALSE; } else { - msg_info ("no weight registered for symbol %s", item->s->symbol); + msg_info ("no weight registered for symbol %s", + item->s->symbol); } } } @@ -768,13 +912,16 @@ validate_cache (struct symbols_cache *cache, struct rspamd_config *cfg, gboolean while (cur) { item = cur->data; if (!item->is_callback) { - if (g_hash_table_lookup (cfg->metrics_symbols, item->s->symbol) == NULL) { + if (g_hash_table_lookup (cfg->metrics_symbols, + item->s->symbol) == NULL) { if (strict) { - msg_warn ("no weight registered for symbol %s", item->s->symbol); + msg_warn ("no weight registered for symbol %s", + item->s->symbol); return FALSE; } else { - msg_info ("no weight registered for symbol %s", item->s->symbol); + msg_info ("no weight registered for symbol %s", + item->s->symbol); } } } @@ -807,7 +954,9 @@ validate_cache (struct symbols_cache *cache, struct rspamd_config *cfg, gboolean } } if (!res) { - msg_warn ("symbol '%s' is registered in metric but not found in cache", cur->data); + msg_warn ( + "symbol '%s' is registered in metric but not found in cache", + cur->data); if (strict) { return FALSE; } @@ -819,10 +968,14 @@ validate_cache (struct symbols_cache *cache, struct rspamd_config *cfg, gboolean /* Now adjust symbol weights according to default metric */ if (cfg->default_metric != NULL) { - g_hash_table_foreach (cfg->default_metric->symbols, rspamd_symbols_cache_metric_cb, cache); + g_hash_table_foreach (cfg->default_metric->symbols, + rspamd_symbols_cache_metric_cb, + cache); /* Resort caches */ - cache->negative_items = g_list_sort (cache->negative_items, cache_logic_cmp); - cache->static_items = g_list_sort (cache->static_items, cache_logic_cmp); + cache->negative_items = g_list_sort (cache->negative_items, + cache_logic_cmp); + cache->static_items = + g_list_sort (cache->static_items, cache_logic_cmp); } return TRUE; @@ -840,16 +993,18 @@ struct symbol_callback_data { }; gboolean -call_symbol_callback (struct rspamd_task * task, struct symbols_cache * cache, gpointer *save) +call_symbol_callback (struct rspamd_task * task, + struct symbols_cache * cache, + gpointer *save) { #ifdef HAVE_CLOCK_GETTIME - struct timespec ts1, ts2; + struct timespec ts1, ts2; #else - struct timeval tv1, tv2; + struct timeval tv1, tv2; #endif - guint64 diff; - struct cache_item *item = NULL; - struct symbol_callback_data *s = *save; + guint64 diff; + struct cache_item *item = NULL; + struct symbol_callback_data *s = *save; if (s == NULL) { if (cache == NULL) { @@ -863,14 +1018,17 @@ call_symbol_callback (struct rspamd_task * task, struct symbols_cache * cache, g post_cache_init (cache); rspamd_mempool_wunlock_rwlock (cache->lock); } - s = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct symbol_callback_data)); + s = + rspamd_mempool_alloc0 (task->task_pool, + sizeof (struct symbol_callback_data)); *save = s; if (cache->negative_items != NULL) { s->list_pointer = g_list_first (cache->negative_items); s->saved_item = s->list_pointer->data; s->state = CACHE_STATE_NEGATIVE; } - else if ((s->list_pointer = check_dynamic_item (task, cache)) || cache->dynamic_items != NULL) { + else if ((s->list_pointer = + check_dynamic_item (task, cache)) || cache->dynamic_items != NULL) { if (s->list_pointer == NULL) { s->list_pointer = g_list_first (cache->dynamic_items); s->saved_item = s->list_pointer->data; @@ -898,63 +1056,47 @@ call_symbol_callback (struct rspamd_task * task, struct symbols_cache * cache, g return FALSE; } switch (s->state) { - case CACHE_STATE_NEGATIVE: - s->list_pointer = g_list_next (s->list_pointer); - if (s->list_pointer == NULL) { - if ((s->list_pointer = check_dynamic_item (task, cache)) || cache->dynamic_items != NULL) { - if (s->list_pointer == NULL) { - s->list_pointer = g_list_first (cache->dynamic_items); - s->saved_item = s->list_pointer->data; - s->state = CACHE_STATE_DYNAMIC; - } - else { - s->saved_item = s->list_pointer->data; - s->state = CACHE_STATE_DYNAMIC_MAP; - } + case CACHE_STATE_NEGATIVE: + s->list_pointer = g_list_next (s->list_pointer); + if (s->list_pointer == NULL) { + if ((s->list_pointer = + check_dynamic_item (task, + cache)) || cache->dynamic_items != NULL) { + if (s->list_pointer == NULL) { + s->list_pointer = g_list_first (cache->dynamic_items); + s->saved_item = s->list_pointer->data; + s->state = CACHE_STATE_DYNAMIC; } else { - s->state = CACHE_STATE_STATIC; - s->list_pointer = g_list_first (cache->static_items); - if (s->list_pointer) { - s->saved_item = s->list_pointer->data; - } - else { - return FALSE; - } + s->saved_item = s->list_pointer->data; + s->state = CACHE_STATE_DYNAMIC_MAP; } } else { - s->saved_item = s->list_pointer->data; - } - item = s->saved_item; - break; - case CACHE_STATE_DYNAMIC_MAP: - s->list_pointer = g_list_next (s->list_pointer); - if (s->list_pointer == NULL) { - s->list_pointer = g_list_first (cache->dynamic_items); + s->state = CACHE_STATE_STATIC; + s->list_pointer = g_list_first (cache->static_items); if (s->list_pointer) { s->saved_item = s->list_pointer->data; - s->state = CACHE_STATE_DYNAMIC; } else { - s->state = CACHE_STATE_STATIC; - s->list_pointer = g_list_first (cache->static_items); - if (s->list_pointer) { - s->saved_item = s->list_pointer->data; - } - else { - return FALSE; - } + return FALSE; } } - else { + } + else { + s->saved_item = s->list_pointer->data; + } + item = s->saved_item; + break; + case CACHE_STATE_DYNAMIC_MAP: + s->list_pointer = g_list_next (s->list_pointer); + if (s->list_pointer == NULL) { + s->list_pointer = g_list_first (cache->dynamic_items); + if (s->list_pointer) { s->saved_item = s->list_pointer->data; + s->state = CACHE_STATE_DYNAMIC; } - item = s->saved_item; - break; - case CACHE_STATE_DYNAMIC: - s->list_pointer = g_list_next (s->list_pointer); - if (s->list_pointer == NULL) { + else { s->state = CACHE_STATE_STATIC; s->list_pointer = g_list_first (cache->static_items); if (s->list_pointer) { @@ -964,39 +1106,58 @@ call_symbol_callback (struct rspamd_task * task, struct symbols_cache * cache, g return FALSE; } } - else { - s->saved_item = s->list_pointer->data; - /* Skip items that are in negative map */ - while (s->list_pointer != NULL && check_negative_dynamic_item (task, cache, s->saved_item)) { - s->list_pointer = g_list_next (s->list_pointer); - if (s->list_pointer != NULL) { - s->saved_item = s->list_pointer->data; - } - } - if (s->list_pointer == NULL) { - s->state = CACHE_STATE_STATIC; - s->list_pointer = g_list_first (cache->static_items); - if (s->list_pointer) { - s->saved_item = s->list_pointer->data; - } - else { - return FALSE; - } - } - } - item = s->saved_item; - break; - case CACHE_STATE_STATIC: - /* Next pointer */ - s->list_pointer = g_list_next (s->list_pointer); + } + else { + s->saved_item = s->list_pointer->data; + } + item = s->saved_item; + break; + case CACHE_STATE_DYNAMIC: + s->list_pointer = g_list_next (s->list_pointer); + if (s->list_pointer == NULL) { + s->state = CACHE_STATE_STATIC; + s->list_pointer = g_list_first (cache->static_items); if (s->list_pointer) { s->saved_item = s->list_pointer->data; } else { return FALSE; } - item = s->saved_item; - break; + } + else { + s->saved_item = s->list_pointer->data; + /* Skip items that are in negative map */ + while (s->list_pointer != NULL && + check_negative_dynamic_item (task, cache, s->saved_item)) { + s->list_pointer = g_list_next (s->list_pointer); + if (s->list_pointer != NULL) { + s->saved_item = s->list_pointer->data; + } + } + if (s->list_pointer == NULL) { + s->state = CACHE_STATE_STATIC; + s->list_pointer = g_list_first (cache->static_items); + if (s->list_pointer) { + s->saved_item = s->list_pointer->data; + } + else { + return FALSE; + } + } + } + item = s->saved_item; + break; + case CACHE_STATE_STATIC: + /* Next pointer */ + s->list_pointer = g_list_next (s->list_pointer); + if (s->list_pointer) { + s->saved_item = s->list_pointer->data; + } + else { + return FALSE; + } + item = s->saved_item; + break; } } if (!item) { @@ -1007,9 +1168,9 @@ call_symbol_callback (struct rspamd_task * task, struct symbols_cache * cache, g # ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts1); # elif defined(HAVE_CLOCK_VIRTUAL) - clock_gettime (CLOCK_VIRTUAL, &ts1); + clock_gettime (CLOCK_VIRTUAL, &ts1); # else - clock_gettime (CLOCK_REALTIME, &ts1); + clock_gettime (CLOCK_REALTIME, &ts1); # endif #else if (gettimeofday (&tv1, NULL) == -1) { @@ -1030,9 +1191,9 @@ call_symbol_callback (struct rspamd_task * task, struct symbols_cache * cache, g # ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts2); # elif defined(HAVE_CLOCK_VIRTUAL) - clock_gettime (CLOCK_VIRTUAL, &ts2); + clock_gettime (CLOCK_VIRTUAL, &ts2); # else - clock_gettime (CLOCK_REALTIME, &ts2); + clock_gettime (CLOCK_REALTIME, &ts2); # endif #else if (gettimeofday (&tv2, NULL) == -1) { @@ -1041,9 +1202,12 @@ call_symbol_callback (struct rspamd_task * task, struct symbols_cache * cache, g #endif #ifdef HAVE_CLOCK_GETTIME - diff = (ts2.tv_sec - ts1.tv_sec) * 1000000 + (ts2.tv_nsec - ts1.tv_nsec) / 1000; + diff = + (ts2.tv_sec - + ts1.tv_sec) * 1000000 + (ts2.tv_nsec - ts1.tv_nsec) / 1000; #else - diff = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec); + diff = + (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec); #endif item->s->avg_time = rspamd_set_counter (item->s->symbol, diff); } diff --git a/src/libserver/symbols_cache.h b/src/libserver/symbols_cache.h index b3835824d..e1fd3286f 100644 --- a/src/libserver/symbols_cache.h +++ b/src/libserver/symbols_cache.h @@ -32,7 +32,7 @@ struct cache_item { struct dynamic_map_item *networks; guint32 networks_number; gboolean is_dynamic; - + /* Callback data */ symbol_func_t func; gpointer user_data; @@ -53,7 +53,7 @@ struct symbols_cache { /* Items that have negative weights */ GList *negative_items; - + /* Radix map of dynamic rules with ip mappings */ radix_tree_t *dynamic_map; radix_tree_t *negative_dynamic_map; @@ -77,8 +77,11 @@ struct symbols_cache { /** * Load symbols cache from file, must be called _after_ init_symbols_cache */ -gboolean init_symbols_cache (rspamd_mempool_t *pool, struct symbols_cache *cache, struct rspamd_config *cfg, - const gchar *filename, gboolean ignore_checksum); +gboolean init_symbols_cache (rspamd_mempool_t *pool, + struct symbols_cache *cache, + struct rspamd_config *cfg, + const gchar *filename, + gboolean ignore_checksum); /** * Register function for symbols parsing @@ -86,15 +89,20 @@ gboolean init_symbols_cache (rspamd_mempool_t *pool, struct symbols_cache *cache * @param func pointer to handler * @param user_data pointer to user_data */ -void register_symbol (struct symbols_cache **cache, const gchar *name, double weight, - symbol_func_t func, gpointer user_data); +void register_symbol (struct symbols_cache **cache, + const gchar *name, + double weight, + symbol_func_t func, + gpointer user_data); /** * Register virtual symbol * @param name name of symbol */ -void register_virtual_symbol (struct symbols_cache **cache, const gchar *name, double weight); +void register_virtual_symbol (struct symbols_cache **cache, + const gchar *name, + double weight); /** * Register callback function for symbols parsing @@ -102,8 +110,11 @@ void register_virtual_symbol (struct symbols_cache **cache, const gchar *name, d * @param func pointer to handler * @param user_data pointer to user_data */ -void register_callback_symbol (struct symbols_cache **cache, const gchar *name, double weight, - symbol_func_t func, gpointer user_data); +void register_callback_symbol (struct symbols_cache **cache, + const gchar *name, + double weight, + symbol_func_t func, + gpointer user_data); /** * Register function for symbols parsing with strict priority @@ -111,8 +122,12 @@ void register_callback_symbol (struct symbols_cache **cache, const gchar *name, * @param func pointer to handler * @param user_data pointer to user_data */ -void register_callback_symbol_priority (struct symbols_cache **cache, const gchar *name, double weight, - gint priority, symbol_func_t func, gpointer user_data); +void register_callback_symbol_priority (struct symbols_cache **cache, + const gchar *name, + double weight, + gint priority, + symbol_func_t func, + gpointer user_data); /** * Register function for dynamic symbols parsing @@ -120,9 +135,13 @@ void register_callback_symbol_priority (struct symbols_cache **cache, const gcha * @param func pointer to handler * @param user_data pointer to user_data */ -void register_dynamic_symbol (rspamd_mempool_t *pool, struct symbols_cache **cache, const gchar *name, - double weight, symbol_func_t func, - gpointer user_data, GList *networks); +void register_dynamic_symbol (rspamd_mempool_t *pool, + struct symbols_cache **cache, + const gchar *name, + double weight, + symbol_func_t func, + gpointer user_data, + GList *networks); /** * Call function for cached symbol using saved callback @@ -130,7 +149,9 @@ void register_dynamic_symbol (rspamd_mempool_t *pool, struct symbols_cache **cac * @param cache symbols cache * @param saved_item pointer to currently saved item */ -gboolean call_symbol_callback (struct rspamd_task *task, struct symbols_cache *cache, gpointer *save); +gboolean call_symbol_callback (struct rspamd_task *task, + struct symbols_cache *cache, + gpointer *save); /** * Remove all dynamic rules from cache @@ -144,7 +165,9 @@ void remove_dynamic_rules (struct symbols_cache *cache); * @param cfg configuration * @param strict do strict checks - symbols MUST be described in metrics */ -gboolean validate_cache (struct symbols_cache *cache, struct rspamd_config *cfg, gboolean strict); +gboolean validate_cache (struct symbols_cache *cache, + struct rspamd_config *cfg, + gboolean strict); #endif diff --git a/src/libserver/task.c b/src/libserver/task.c index a46a70604..a796b3f93 100644 --- a/src/libserver/task.c +++ b/src/libserver/task.c @@ -34,7 +34,7 @@ static void rcpt_destruct (void *pointer) { - struct rspamd_task *task = (struct rspamd_task *) pointer; + struct rspamd_task *task = (struct rspamd_task *) pointer; if (task->rcpt) { g_list_free (task->rcpt); @@ -44,10 +44,10 @@ rcpt_destruct (void *pointer) /* * Create new task */ -struct rspamd_task * +struct rspamd_task * rspamd_task_new (struct rspamd_worker *worker) { - struct rspamd_task *new_task; + struct rspamd_task *new_task; new_task = g_slice_alloc0 (sizeof (struct rspamd_task)); @@ -60,9 +60,9 @@ rspamd_task_new (struct rspamd_worker *worker) # ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &new_task->ts); # elif defined(HAVE_CLOCK_VIRTUAL) - clock_gettime (CLOCK_VIRTUAL, &new_task->ts); + clock_gettime (CLOCK_VIRTUAL, &new_task->ts); # else - clock_gettime (CLOCK_REALTIME, &new_task->ts); + clock_gettime (CLOCK_REALTIME, &new_task->ts); # endif #endif if (gettimeofday (&new_task->tv, NULL) == -1) { @@ -73,27 +73,28 @@ rspamd_task_new (struct rspamd_worker *worker) /* Add destructor for recipients list (it would be better to use anonymous function here */ rspamd_mempool_add_destructor (new_task->task_pool, - (rspamd_mempool_destruct_t) rcpt_destruct, new_task); + (rspamd_mempool_destruct_t) rcpt_destruct, new_task); new_task->results = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); rspamd_mempool_add_destructor (new_task->task_pool, - (rspamd_mempool_destruct_t) g_hash_table_destroy, - new_task->results); + (rspamd_mempool_destruct_t) g_hash_table_destroy, + new_task->results); new_task->re_cache = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); rspamd_mempool_add_destructor (new_task->task_pool, - (rspamd_mempool_destruct_t) g_hash_table_destroy, - new_task->re_cache); - new_task->raw_headers = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); + (rspamd_mempool_destruct_t) g_hash_table_destroy, + new_task->re_cache); + new_task->raw_headers = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); rspamd_mempool_add_destructor (new_task->task_pool, - (rspamd_mempool_destruct_t) g_hash_table_destroy, - new_task->raw_headers); + (rspamd_mempool_destruct_t) g_hash_table_destroy, + new_task->raw_headers); new_task->emails = g_tree_new (compare_email_func); rspamd_mempool_add_destructor (new_task->task_pool, - (rspamd_mempool_destruct_t) g_tree_destroy, - new_task->emails); + (rspamd_mempool_destruct_t) g_tree_destroy, + new_task->emails); new_task->urls = g_tree_new (compare_url_func); rspamd_mempool_add_destructor (new_task->task_pool, - (rspamd_mempool_destruct_t) g_tree_destroy, - new_task->urls); + (rspamd_mempool_destruct_t) g_tree_destroy, + new_task->urls); new_task->sock = -1; new_task->is_mime = TRUE; new_task->is_json = TRUE; @@ -123,7 +124,7 @@ rspamd_task_reply (struct rspamd_task *task) gboolean rspamd_task_fin (void *arg) { - struct rspamd_task *task = (struct rspamd_task *) arg; + struct rspamd_task *task = (struct rspamd_task *) arg; gint r; GError *err = NULL; @@ -205,7 +206,7 @@ rspamd_task_fin (void *arg) void rspamd_task_restore (void *arg) { - struct rspamd_task *task = (struct rspamd_task *) arg; + struct rspamd_task *task = (struct rspamd_task *) arg; /* Call post filters */ if (task->state == WAIT_POST_FILTER && !task->skip_extra_filters) { @@ -220,8 +221,8 @@ rspamd_task_restore (void *arg) void rspamd_task_free (struct rspamd_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); @@ -257,14 +258,16 @@ rspamd_task_free (struct rspamd_task *task, gboolean is_soft) } } -void rspamd_task_free_hard (gpointer ud) +void +rspamd_task_free_hard (gpointer ud) { struct rspamd_task *task = ud; rspamd_task_free (task, FALSE); } -void rspamd_task_free_soft (gpointer ud) +void +rspamd_task_free_soft (gpointer ud) { struct rspamd_task *task = ud; @@ -274,8 +277,8 @@ void rspamd_task_free_soft (gpointer ud) gboolean rspamd_task_process (struct rspamd_task *task, - struct rspamd_http_message *msg, GThreadPool *classify_pool, - gboolean process_extra_filters) + struct rspamd_http_message *msg, GThreadPool *classify_pool, + gboolean process_extra_filters) { gint r; GError *err = NULL; diff --git a/src/libserver/task.h b/src/libserver/task.h index 4c3462d9a..d9ec9d8d2 100644 --- a/src/libserver/task.h +++ b/src/libserver/task.h @@ -62,7 +62,7 @@ struct custom_command { * Worker task structure */ struct rspamd_task { - struct rspamd_worker *worker; /**< pointer to worker object */ + struct rspamd_worker *worker; /**< pointer to worker object */ enum { READ_MESSAGE, WAIT_PRE_FILTER, @@ -70,82 +70,82 @@ struct rspamd_task { WAIT_POST_FILTER, WRITE_REPLY, CLOSING_CONNECTION - } state; /**< current session state */ - enum rspamd_command cmd; /**< command */ - struct custom_command *custom_cmd; /**< custom command if any */ - gint sock; /**< socket descriptor */ + } state; /**< current session state */ + enum rspamd_command cmd; /**< command */ + struct custom_command *custom_cmd; /**< custom command if any */ + gint sock; /**< socket descriptor */ gboolean is_mime; /**< if this task is mime task */ - gboolean is_json; /**< output is JSON */ - gboolean skip_extra_filters; /**< skip pre and post filters */ + gboolean is_json; /**< output is JSON */ + gboolean skip_extra_filters; /**< skip pre and post filters */ gboolean is_skipped; /**< whether message was skipped by configuration */ - gchar *helo; /**< helo header value */ - gchar *from; /**< from header value */ - gchar *queue_id; /**< queue id if specified */ - const gchar *message_id; /**< message id */ - GList *rcpt; /**< recipients list */ - guint nrcpt; /**< number of recipients */ - rspamd_inet_addr_t from_addr; /**< from addr for a task */ - rspamd_inet_addr_t client_addr; /**< address of connected socket */ - gchar *deliver_to; /**< address to deliver */ - gchar *user; /**< user to deliver */ - gchar *subject; /**< subject (for non-mime) */ - gchar *hostname; /**< hostname reported by MTA */ - GString *msg; /**< message buffer */ - struct rspamd_http_connection *http_conn; /**< HTTP server connection */ - struct rspamd_async_session* s; /**< async session object */ - gint parts_count; /**< mime parts count */ - GMimeMessage *message; /**< message, parsed with GMime */ - GMimeObject *parser_parent_part; /**< current parent part */ - InternetAddressList *rcpts; /**< list of all recipients */ - GList *parts; /**< list of parsed parts */ - GList *text_parts; /**< list of text parts */ - gchar *raw_headers_str; /**< list of raw headers */ - GList *received; /**< list of received headers */ - GTree *urls; /**< list of parsed urls */ - GTree *emails; /**< list of parsed emails */ - GList *images; /**< list of images */ - GHashTable *raw_headers; /**< list of raw headers */ - GHashTable *results; /**< hash table of metric_result indexed by - * metric's name */ - GHashTable *tokens; /**< hash table of tokens indexed by tokenizer - * pointer */ - GList *messages; /**< list of messages that would be reported */ - GHashTable *re_cache; /**< cache for matched or not matched regexps */ - struct rspamd_config *cfg; /**< pointer to config object */ - gchar *last_error; /**< last error */ - gint error_code; /**< code of last error */ - rspamd_mempool_t *task_pool; /**< memory pool for task */ + gchar *helo; /**< helo header value */ + gchar *from; /**< from header value */ + gchar *queue_id; /**< queue id if specified */ + const gchar *message_id; /**< message id */ + GList *rcpt; /**< recipients list */ + guint nrcpt; /**< number of recipients */ + rspamd_inet_addr_t from_addr; /**< from addr for a task */ + rspamd_inet_addr_t client_addr; /**< address of connected socket */ + gchar *deliver_to; /**< address to deliver */ + gchar *user; /**< user to deliver */ + gchar *subject; /**< subject (for non-mime) */ + gchar *hostname; /**< hostname reported by MTA */ + GString *msg; /**< message buffer */ + struct rspamd_http_connection *http_conn; /**< HTTP server connection */ + struct rspamd_async_session * s; /**< async session object */ + gint parts_count; /**< mime parts count */ + GMimeMessage *message; /**< message, parsed with GMime */ + GMimeObject *parser_parent_part; /**< current parent part */ + InternetAddressList *rcpts; /**< list of all recipients */ + GList *parts; /**< list of parsed parts */ + GList *text_parts; /**< list of text parts */ + gchar *raw_headers_str; /**< list of raw headers */ + GList *received; /**< list of received headers */ + GTree *urls; /**< list of parsed urls */ + GTree *emails; /**< list of parsed emails */ + GList *images; /**< list of images */ + GHashTable *raw_headers; /**< list of raw headers */ + GHashTable *results; /**< hash table of metric_result indexed by + * metric's name */ + GHashTable *tokens; /**< hash table of tokens indexed by tokenizer + * pointer */ + GList *messages; /**< list of messages that would be reported */ + GHashTable *re_cache; /**< cache for matched or not matched regexps */ + struct rspamd_config *cfg; /**< pointer to config object */ + gchar *last_error; /**< last error */ + gint error_code; /**< code of last error */ + rspamd_mempool_t *task_pool; /**< memory pool for task */ #ifdef HAVE_CLOCK_GETTIME - struct timespec ts; /**< time of connection */ + struct timespec ts; /**< time of connection */ #endif - struct timeval tv; /**< time of connection */ - guint32 scan_milliseconds; /**< how much milliseconds passed */ - gboolean pass_all_filters; /**< pass task throught every rule */ - gboolean no_log; /**< do not log or write this task to the history */ - guint32 parser_recursion; /**< for avoiding recursion stack overflow */ - gboolean (*fin_callback)(void *arg); /**< calback for filters finalizing */ - void *fin_arg; /**< argument for fin callback */ + struct timeval tv; /**< time of connection */ + guint32 scan_milliseconds; /**< how much milliseconds passed */ + gboolean pass_all_filters; /**< pass task throught every rule */ + gboolean no_log; /**< do not log or write this task to the history */ + guint32 parser_recursion; /**< for avoiding recursion stack overflow */ + gboolean (*fin_callback)(void *arg); /**< calback for filters finalizing */ + void *fin_arg; /**< argument for fin callback */ - guint32 dns_requests; /**< number of DNS requests per this task */ + guint32 dns_requests; /**< number of DNS requests per this task */ - struct rspamd_dns_resolver *resolver; /**< DNS resolver */ - struct event_base *ev_base; /**< Event base */ + struct rspamd_dns_resolver *resolver; /**< DNS resolver */ + struct event_base *ev_base; /**< Event base */ - GThreadPool *classify_pool; /**< A pool of classify threads */ + GThreadPool *classify_pool; /**< A pool of classify threads */ struct { - enum rspamd_metric_action action; /**< Action of pre filters */ - gchar *str; /**< String describing action */ - } pre_result; /**< Result of pre-filters */ + enum rspamd_metric_action action; /**< Action of pre filters */ + gchar *str; /**< String describing action */ + } pre_result; /**< Result of pre-filters */ - ucl_object_t *settings; /**< Settings applied to task */ + ucl_object_t *settings; /**< Settings applied to task */ }; /** * Construct new task for worker */ -struct rspamd_task* rspamd_task_new (struct rspamd_worker *worker); +struct rspamd_task * rspamd_task_new (struct rspamd_worker *worker); /** * Destroy task object and remove its IO dispatcher if it exists */ @@ -173,7 +173,7 @@ gboolean rspamd_task_fin (void *arg); * @return task has been successfully parsed and processed */ gboolean rspamd_task_process (struct rspamd_task *task, - struct rspamd_http_message *msg, GThreadPool *classify_pool, - gboolean process_extra_filters); + struct rspamd_http_message *msg, GThreadPool *classify_pool, + gboolean process_extra_filters); #endif /* TASK_H_ */ diff --git a/src/libserver/url.c b/src/libserver/url.c index c4313e8a9..df4e3102d 100644 --- a/src/libserver/url.c +++ b/src/libserver/url.c @@ -38,16 +38,16 @@ #define HIGHEST_PORT 65535 #define uri_port_is_valid(port) \ - (LOWEST_PORT <= (port) && (port) <= HIGHEST_PORT) + (LOWEST_PORT <= (port) && (port) <= HIGHEST_PORT) struct _proto { - guchar *name; - gint port; - uintptr_t *unused; - guint need_slashes:1; - guint need_slash_after_host:1; - guint free_syntax:1; - guint need_ssl:1; + guchar *name; + gint port; + uintptr_t *unused; + guint need_slashes : 1; + guint need_slash_after_host : 1; + guint free_syntax : 1; + guint need_ssl : 1; }; typedef struct url_match_s { @@ -64,314 +64,627 @@ typedef struct url_match_s { struct url_matcher { const gchar *pattern; const gchar *prefix; - gboolean (*start)(const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); - gboolean (*end)(const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); + gboolean (*start)(const gchar *begin, const gchar *end, const gchar *pos, + url_match_t *match); + gboolean (*end)(const gchar *begin, const gchar *end, const gchar *pos, + url_match_t *match); gint flags; }; -static gboolean url_file_start (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); -static gboolean url_file_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); - -static gboolean url_web_start (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); -static gboolean url_web_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); - -static gboolean url_tld_start (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); -static gboolean url_tld_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); - -static gboolean url_email_start (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); -static gboolean url_email_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match); +static gboolean url_file_start (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match); +static gboolean url_file_end (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match); + +static gboolean url_web_start (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match); +static gboolean url_web_end (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match); + +static gboolean url_tld_start (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match); +static gboolean url_tld_end (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match); + +static gboolean url_email_start (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match); +static gboolean url_email_end (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match); struct url_matcher matchers[] = { - /* Common prefixes */ - { "file://", "", url_file_start, url_file_end, 0 }, - { "ftp://", "", url_web_start, url_web_end, 0 }, - { "sftp://", "", url_web_start, url_web_end, 0 }, - { "http://", "", url_web_start, url_web_end, 0 }, - { "https://", "", url_web_start, url_web_end, 0 }, - { "news://", "", url_web_start, url_web_end, 0 }, - { "nntp://", "", url_web_start, url_web_end, 0 }, - { "telnet://", "", url_web_start, url_web_end, 0 }, - { "webcal://", "", url_web_start, url_web_end, 0 }, - { "mailto://", "", url_email_start, url_email_end, 0 }, - { "callto://", "", url_web_start, url_web_end, 0 }, - { "h323:", "", url_web_start, url_web_end, 0 }, - { "sip:", "", url_web_start, url_web_end, 0 }, - { "www.", "http://", url_web_start, url_web_end, 0 }, - { "ftp.", "ftp://", url_web_start, url_web_end, URL_FLAG_NOHTML }, - /* TLD domains parts */ - { ".ac", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ad", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ae", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".aero", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".af", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ag", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ai", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".al", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".am", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".an", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ao", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".aq", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ar", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".arpa", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".as", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".asia", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".at", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".au", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".aw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ax", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".az", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ba", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bb", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bd", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".be", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bf", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bh", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bi", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".biz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bj", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bo", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".br", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bs", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bt", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bv", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".by", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".bz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ca", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cat", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cc", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cd", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cf", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ch", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ci", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ck", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cl", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".co", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".com", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".coop", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cu", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cv", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cx", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cy", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".cz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".de", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".dj", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".dk", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".dm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".do", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".dz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ec", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".edu", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ee", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".eg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".er", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".es", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".et", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".eu", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".fi", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".fj", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".fk", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".fm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".fo", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".fr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ga", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gb", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gd", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ge", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gf", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gh", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gi", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gl", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gov", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gp", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gq", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gs", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gt", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gu", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".gy", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".hk", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".hm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".hn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".hr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ht", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".hu", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".id", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ie", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".il", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".im", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".in", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".info", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".int", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".io", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".iq", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ir", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".is", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".it", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".je", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".jm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".jo", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".jobs", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".jp", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ke", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".kg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".kh", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ki", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".km", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".kn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".kp", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".kr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".kw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ky", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".kz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".la", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".lb", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".lc", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".li", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".lk", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".lr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ls", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".lt", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".lu", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".lv", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ly", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ma", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mc", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".md", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".me", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mh", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mil", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mk", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ml", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mo", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mobi", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mp", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mq", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ms", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mt", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mu", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".museum", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mv", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mx", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".my", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".mz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".na", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".name", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".nc", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ne", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".net", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".nf", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ng", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ni", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".nl", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".no", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".np", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".nr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".nu", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".nz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".om", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".org", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pa", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pe", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pf", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ph", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pk", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pl", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pro", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ps", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pt", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".pw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".py", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".qa", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".re", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ro", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".rs", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ru", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".rw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sa", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sb", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sc", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sd", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".se", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sh", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".si", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sj", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sk", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sl", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".so", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".st", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".su", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sv", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sx", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sy", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".sz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tc", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".td", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tel", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tf", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".th", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tj", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tk", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tl", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".to", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tp", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tr", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".travel", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tt", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tv", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".tz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ua", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ug", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".uk", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".us", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".uy", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".uz", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".va", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".vc", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ve", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".vg", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".vi", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".vn", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".vu", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".wf", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ws", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".xxx", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".ye", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".yt", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".za", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".zm", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - { ".zw", "http://", url_tld_start, url_tld_end, URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, - /* Likely emails */ - { "@", "mailto://",url_email_start, url_email_end, URL_FLAG_NOHTML } + /* Common prefixes */ + { "file://", "", url_file_start, url_file_end, + 0 }, + { "ftp://", "", url_web_start, url_web_end, + 0 }, + { "sftp://", "", url_web_start, url_web_end, + 0 }, + { "http://", "", url_web_start, url_web_end, + 0 }, + { "https://", "", url_web_start, url_web_end, + 0 }, + { "news://", "", url_web_start, url_web_end, + 0 }, + { "nntp://", "", url_web_start, url_web_end, + 0 }, + { "telnet://", "", url_web_start, url_web_end, + 0 }, + { "webcal://", "", url_web_start, url_web_end, + 0 }, + { "mailto://", "", url_email_start, url_email_end, + 0 }, + { "callto://", "", url_web_start, url_web_end, + 0 }, + { "h323:", "", url_web_start, url_web_end, + 0 }, + { "sip:", "", url_web_start, url_web_end, + 0 }, + { "www.", "http://", url_web_start, url_web_end, + 0 }, + { "ftp.", "ftp://", url_web_start, url_web_end, + URL_FLAG_NOHTML }, + /* TLD domains parts */ + { ".ac", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ad", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ae", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".aero", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".af", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ag", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ai", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".al", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".am", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".an", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ao", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".aq", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ar", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".arpa", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".as", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".asia", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".at", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".au", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".aw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ax", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".az", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ba", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bb", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bd", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".be", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bf", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bh", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bi", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".biz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bj", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bo", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".br", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bs", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bt", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bv", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".by", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".bz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ca", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cat", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cc", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cd", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cf", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ch", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ci", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ck", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cl", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".co", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".com", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".coop", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cu", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cv", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cx", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cy", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".cz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".de", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".dj", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".dk", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".dm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".do", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".dz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ec", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".edu", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ee", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".eg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".er", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".es", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".et", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".eu", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".fi", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".fj", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".fk", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".fm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".fo", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".fr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ga", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gb", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gd", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ge", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gf", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gh", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gi", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gl", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gov", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gp", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gq", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gs", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gt", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gu", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".gy", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".hk", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".hm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".hn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".hr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ht", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".hu", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".id", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ie", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".il", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".im", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".in", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".info", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".int", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".io", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".iq", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ir", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".is", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".it", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".je", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".jm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".jo", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".jobs", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".jp", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ke", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".kg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".kh", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ki", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".km", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".kn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".kp", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".kr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".kw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ky", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".kz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".la", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".lb", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".lc", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".li", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".lk", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".lr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ls", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".lt", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".lu", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".lv", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ly", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ma", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mc", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".md", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".me", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mh", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mil", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mk", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ml", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mo", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mobi", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mp", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mq", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ms", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mt", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mu", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".museum", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mv", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mx", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".my", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".mz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".na", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".name", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".nc", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ne", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".net", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".nf", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ng", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ni", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".nl", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".no", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".np", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".nr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".nu", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".nz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".om", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".org", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pa", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pe", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pf", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ph", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pk", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pl", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pro", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ps", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pt", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".pw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".py", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".qa", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".re", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ro", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".rs", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ru", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".rw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sa", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sb", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sc", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sd", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".se", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sh", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".si", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sj", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sk", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sl", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".so", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".st", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".su", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sv", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sx", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sy", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".sz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tc", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".td", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tel", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tf", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".th", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tj", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tk", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tl", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".to", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tp", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tr", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".travel", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tt", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tv", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".tz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ua", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ug", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".uk", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".us", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".uy", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".uz", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".va", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".vc", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ve", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".vg", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".vi", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".vn", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".vu", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".wf", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ws", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".xxx", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".ye", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".yt", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".za", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".zm", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + { ".zw", "http://", url_tld_start, url_tld_end, + URL_FLAG_NOHTML | URL_FLAG_STRICT_MATCH }, + /* Likely emails */ + { "@", "mailto://",url_email_start, url_email_end, + URL_FLAG_NOHTML } }; struct url_match_scanner { @@ -382,7 +695,7 @@ struct url_match_scanner { struct url_match_scanner *url_scanner = NULL; -static const struct _proto protocol_backends[] = { +static const struct _proto protocol_backends[] = { {"file", 0, NULL, 1, 0, 0, 0}, {"ftp", 21, NULL, 1, 0, 0, 0}, {"http", 80, NULL, 1, 0, 0, 0}, @@ -395,7 +708,8 @@ static const struct _proto protocol_backends[] = { /* Convert an ASCII hex digit to the corresponding number between 0 and 15. H should be a hexadecimal digit that satisfies isxdigit; otherwise, the result is undefined. */ -#define XDIGIT_TO_NUM(h) ((h) < 'A' ? (h) - '0' : g_ascii_toupper (h) - 'A' + 10) +#define XDIGIT_TO_NUM(h) ((h) < 'A' ? (h) - '0' : g_ascii_toupper (h) - 'A' + \ + 10) #define X2DIGITS_TO_NUM(h1, h2) ((XDIGIT_TO_NUM (h1) << 4) + XDIGIT_TO_NUM (h2)) /* The reverse of the above: convert a number in the [0, 16) range to the ASCII representation of the corresponding hexadecimal digit. @@ -404,45 +718,47 @@ static const struct _proto protocol_backends[] = { #define XNUM_TO_digit(x) ("0123456789abcdef"[x] + 0) static guchar url_scanner_table[256] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 1, 1, 9, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 24,128,160,128,128,128,128,128,160,160,128,128,160,192,160,160, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,160,160, 32,128, 32,128, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 1, 1, 9, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 24,128,160,128,128,128,128,128,160,160,128,128,160,192,160,160, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,160,160, 32,128, 32,128, 160, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,160,160,160,128,192, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,160,160,160,128,192, 128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,128,128,128,128, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,128,128,128,128, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; enum { - IS_CTRL = (1 << 0), - IS_ALPHA = (1 << 1), - IS_DIGIT = (1 << 2), - IS_LWSP = (1 << 3), - IS_SPACE = (1 << 4), - IS_SPECIAL = (1 << 5), - IS_DOMAIN = (1 << 6), - IS_URLSAFE = (1 << 7) + IS_CTRL = (1 << 0), + IS_ALPHA = (1 << 1), + IS_DIGIT = (1 << 2), + IS_LWSP = (1 << 3), + IS_SPACE = (1 << 4), + IS_SPECIAL = (1 << 5), + IS_DOMAIN = (1 << 6), + IS_URLSAFE = (1 << 7) }; #define is_ctrl(x) ((url_scanner_table[(guchar)(x)] & IS_CTRL) != 0) #define is_lwsp(x) ((url_scanner_table[(guchar)(x)] & IS_LWSP) != 0) -#define is_atom(x) ((url_scanner_table[(guchar)(x)] & (IS_SPECIAL|IS_SPACE|IS_CTRL)) == 0) +#define is_atom(x) ((url_scanner_table[(guchar)(x)] & (IS_SPECIAL | IS_SPACE | \ + IS_CTRL)) == 0) #define is_alpha(x) ((url_scanner_table[(guchar)(x)] & IS_ALPHA) != 0) #define is_digit(x) ((url_scanner_table[(guchar)(x)] & IS_DIGIT) != 0) #define is_domain(x) ((url_scanner_table[(guchar)(x)] & IS_DOMAIN) != 0) -#define is_urlsafe(x) ((url_scanner_table[(guchar)(x)] & (IS_ALPHA|IS_DIGIT|IS_URLSAFE)) != 0) +#define is_urlsafe(x) ((url_scanner_table[(guchar)(x)] & (IS_ALPHA | IS_DIGIT | \ + IS_URLSAFE)) != 0) -const gchar * +const gchar * url_strerror (enum uri_errno err) { switch (err) { @@ -477,7 +793,7 @@ url_strerror (enum uri_errno err) static gint check_uri_file (gchar *name) { - static const gchar chars[] = POST_CHAR_S "#?"; + static const gchar chars[] = POST_CHAR_S "#?"; return strcspn (name, chars); } @@ -485,30 +801,41 @@ check_uri_file (gchar *name) static gint url_init (void) { - guint i; - gchar patbuf[128]; + guint i; + gchar patbuf[128]; if (url_scanner == NULL) { url_scanner = g_malloc (sizeof (struct url_match_scanner)); url_scanner->matchers = matchers; url_scanner->matchers_count = G_N_ELEMENTS (matchers); url_scanner->patterns = rspamd_trie_create (TRUE); - for (i = 0; i < url_scanner->matchers_count; i ++) { + for (i = 0; i < url_scanner->matchers_count; i++) { if (matchers[i].flags & URL_FLAG_STRICT_MATCH) { /* Insert more specific patterns */ /* some.tld/ */ - rspamd_snprintf (patbuf, sizeof (patbuf), "%s/", matchers[i].pattern); + rspamd_snprintf (patbuf, + sizeof (patbuf), + "%s/", + matchers[i].pattern); rspamd_trie_insert (url_scanner->patterns, patbuf, i); /* some.tld */ - rspamd_snprintf (patbuf, sizeof (patbuf), "%s ", matchers[i].pattern); + rspamd_snprintf (patbuf, + sizeof (patbuf), + "%s ", + matchers[i].pattern); rspamd_trie_insert (url_scanner->patterns, patbuf, i); /* some.tld: */ - rspamd_snprintf (patbuf, sizeof (patbuf), "%s:", matchers[i].pattern); + rspamd_snprintf (patbuf, + sizeof (patbuf), + "%s:", + matchers[i].pattern); rspamd_trie_insert (url_scanner->patterns, patbuf, i); } else { - rspamd_trie_insert (url_scanner->patterns, matchers[i].pattern, i); + rspamd_trie_insert (url_scanner->patterns, + matchers[i].pattern, + i); } } } @@ -522,10 +849,10 @@ get_protocol (gchar *name, gint namelen) /* These are really enum protocol values but can take on negative * values and since 0 <= -1 for enum values it's better to use clean * integer type. */ - gint start, end; - enum protocol protocol; - guchar *pname; - gint pnamelen, minlen, compare; + gint start, end; + enum protocol protocol; + guchar *pname; + gint pnamelen, minlen, compare; /* Almost dichotomic search is used here */ /* Starting at the HTTP entry which is the most common that will make @@ -590,7 +917,7 @@ get_protocol_free_syntax (enum protocol protocol) static gint get_protocol_length (const gchar *url) { - gchar *end = (gchar *)url; + gchar *end = (gchar *)url; /* Seek the end of the protocol name if any. */ /* RFC1738: @@ -610,11 +937,12 @@ get_protocol_length (const gchar *url) static guint url_calculate_escaped_hostlen (gchar *host, guint hostlen) { - guint i, result = hostlen; - gchar *p = host, c; + guint i, result = hostlen; + gchar *p = host, c; for (i = 0; i < hostlen; i++, p++) { - if (*p == '%' && g_ascii_isxdigit (*(p + 1)) && g_ascii_isxdigit (*(p + 2)) && i < hostlen - 2) { + if (*p == '%' && g_ascii_isxdigit (*(p + 1)) && + g_ascii_isxdigit (*(p + 2)) && i < hostlen - 2) { c = X2DIGITS_TO_NUM (*(p + 1), *(p + 2)); if (c != '\0') { result -= 2; @@ -637,18 +965,19 @@ url_calculate_escaped_hostlen (gchar *host, guint hostlen) static void url_unescape (gchar *s) { - gchar *t = s; /* t - tortoise */ - gchar *h = s; /* h - hare */ + gchar *t = s; /* t - tortoise */ + gchar *h = s; /* h - hare */ for (; *h; h++, t++) { if (*h != '%') { - copychar: +copychar: *t = *h; } else { - gchar c; + gchar c; /* Do nothing if '%' is not followed by two hex digits. */ - if (!h[1] || !h[2] || !(g_ascii_isxdigit (h[1]) && g_ascii_isxdigit (h[2]))) + if (!h[1] || !h[2] || + !(g_ascii_isxdigit (h[1]) && g_ascii_isxdigit (h[2]))) goto copychar; c = X2DIGITS_TO_NUM (h[1], h[2]); /* Don't unescape %00 because there is no way to insert it @@ -665,8 +994,8 @@ url_unescape (gchar *s) static void url_strip (gchar *s) { - gchar *t = s; /* t - tortoise */ - gchar *h = s; /* h - hare */ + gchar *t = s; /* t - tortoise */ + gchar *h = s; /* h - hare */ while (*h) { if (g_ascii_isgraph (*h)) { @@ -678,17 +1007,17 @@ url_strip (gchar *s) *t = '\0'; } -static gchar * +static gchar * url_escape_1 (const gchar *s, gint allow_passthrough, rspamd_mempool_t * pool) { - const gchar *p1; - gchar *p2, *newstr; - gint newlen; - gint addition = 0; + const gchar *p1; + gchar *p2, *newstr; + gint newlen; + gint addition = 0; for (p1 = s; *p1; p1++) if (!is_urlsafe (*p1)) { - addition += 2; /* Two more characters (hex digits) */ + addition += 2; /* Two more characters (hex digits) */ } if (!addition) { @@ -708,7 +1037,7 @@ url_escape_1 (const gchar *s, gint allow_passthrough, rspamd_mempool_t * pool) while (*p1) { /* Quote the characters that match the test mask. */ if (!is_urlsafe (*p1)) { - guchar c = *p1++; + guchar c = *p1++; *p2++ = '%'; *p2++ = XNUM_TO_DIGIT (c >> 4); *p2++ = XNUM_TO_DIGIT (c & 0xf); @@ -724,7 +1053,7 @@ url_escape_1 (const gchar *s, gint allow_passthrough, rspamd_mempool_t * pool) /* URL-escape the unsafe characters (see urlchr_table) in a given string, returning a freshly allocated string. */ -gchar * +gchar * url_escape (const gchar *s, rspamd_mempool_t * pool) { return url_escape_1 (s, 0, pool); @@ -747,7 +1076,7 @@ char_needs_escaping (const gchar *p) return TRUE; } } - else if (! is_urlsafe (*p)) { + else if (!is_urlsafe (*p)) { return TRUE; } return FALSE; @@ -755,16 +1084,16 @@ char_needs_escaping (const gchar *p) /* Translate a %-escaped (but possibly non-conformant) input string S into a %-escaped (and conformant) output string. -*/ + */ -static gchar * +static gchar * reencode_escapes (gchar *s, rspamd_mempool_t * pool) { - const gchar *p1; - gchar *newstr, *p2; - gint oldlen, newlen; + const gchar *p1; + gchar *newstr, *p2; + gint oldlen, newlen; - gint encode_count = 0; + gint encode_count = 0; /* First pass: inspect the string to see if there's anything to do, and to calculate the new length. */ @@ -789,7 +1118,7 @@ reencode_escapes (gchar *s, rspamd_mempool_t * pool) while (*p1) if (char_needs_escaping (p1)) { - guchar c = *p1++; + guchar c = *p1++; *p2++ = '%'; *p2++ = XNUM_TO_DIGIT (c >> 4); *p2++ = XNUM_TO_DIGIT (c & 0xf); @@ -809,10 +1138,10 @@ reencode_escapes (gchar *s, rspamd_mempool_t * pool) static void unescape_single_char (gchar *str, gchar chr) { - const gchar c1 = XNUM_TO_DIGIT (chr >> 4); - const gchar c2 = XNUM_TO_DIGIT (chr & 0xf); - gchar *h = str; /* hare */ - gchar *t = str; /* tortoise */ + const gchar c1 = XNUM_TO_DIGIT (chr >> 4); + const gchar c2 = XNUM_TO_DIGIT (chr & 0xf); + gchar *h = str; /* hare */ + gchar *t = str; /* tortoise */ for (; *h; h++, t++) { if (h[0] == '%' && h[1] == c1 && h[2] == c2) { @@ -835,10 +1164,10 @@ unescape_single_char (gchar *str, gchar chr) static gboolean path_simplify (gchar *path) { - gchar *h = path; /* hare */ - gchar *t = path; /* tortoise */ - gchar *beg = path; /* boundary for backing the tortoise */ - gchar *end = path + strlen (path); + gchar *h = path; /* hare */ + gchar *t = path; /* tortoise */ + gchar *beg = path; /* boundary for backing the tortoise */ + gchar *end = path + strlen (path); while (h < end) { /* Hare should be at the beginning of a path element. */ @@ -852,7 +1181,7 @@ path_simplify (gchar *path) if (t > beg) { /* Move backwards until T hits the beginning of the previous path element or the beginning of path. */ - for (--t; t > beg && t[-1] != '/'; t--); + for (--t; t > beg && t[-1] != '/'; t--) ; } else { /* If we're at the beginning, copy the "../" literally @@ -864,7 +1193,7 @@ path_simplify (gchar *path) h += 3; } else { - regular: +regular: /* A regular path element. If H hasn't advanced past T, simply skip to the next path element. Otherwise, copy the path element until the next slash. */ @@ -894,10 +1223,10 @@ path_simplify (gchar *path) enum uri_errno parse_uri (struct uri *uri, gchar *uristring, rspamd_mempool_t * pool) { - guchar *prefix_end, *host_end, *p; - guchar *lbracket, *rbracket; - gint datalen, n, addrlen; - guchar *frag_or_post, *user_end, *port_end; + guchar *prefix_end, *host_end, *p; + guchar *lbracket, *rbracket; + gint datalen, n, addrlen; + guchar *frag_or_post, *user_end, *port_end; memset (uri, 0, sizeof (*uri)); @@ -910,11 +1239,13 @@ parse_uri (struct uri *uri, gchar *uristring, rspamd_mempool_t * pool) uri->protocollen = get_protocol_length (struri (uri)); /* Assume http as default protocol */ - if (!uri->protocollen || (uri->protocol = get_protocol (struri (uri), uri->protocollen)) == PROTOCOL_UNKNOWN) { + if (!uri->protocollen || + (uri->protocol = + get_protocol (struri (uri), uri->protocollen)) == PROTOCOL_UNKNOWN) { /* Make exception for numeric urls */ p = uri->string; while (*p && (g_ascii_isalnum (*p) || *p == ':')) { - p ++; + p++; } if (*p == '\0') { return URI_ERRNO_INVALID_PROTOCOL; @@ -929,7 +1260,7 @@ parse_uri (struct uri *uri, gchar *uristring, rspamd_mempool_t * pool) /* Figure out whether the protocol is known */ msg_debug ("getting protocol from url: %d", uri->protocol); - prefix_end = struri (uri) + uri->protocollen; /* ':' */ + prefix_end = struri (uri) + uri->protocollen; /* ':' */ /* Check if there's a digit after the protocol name. */ if (g_ascii_isdigit (*prefix_end)) { @@ -1010,7 +1341,7 @@ parse_uri (struct uri *uri, gchar *uristring, rspamd_mempool_t * pool) /* Possibly skip auth part */ host_end = prefix_end + strcspn (prefix_end, "@"); - if (prefix_end + strcspn (prefix_end, "/?") > host_end && *host_end) { /* we have auth info here */ + if (prefix_end + strcspn (prefix_end, "/?") > host_end && *host_end) { /* we have auth info here */ /* Allow '@' in the password component */ while (strcspn (host_end + 1, "@") < strcspn (host_end + 1, "/?")) @@ -1054,7 +1385,7 @@ parse_uri (struct uri *uri, gchar *uristring, rspamd_mempool_t * pool) return URI_ERRNO_TRAILING_DOTS; } - if (*host_end == ':') { /* we have port here */ + if (*host_end == ':') { /* we have port here */ port_end = host_end + 1 + strcspn (host_end + 1, "/"); host_end++; @@ -1089,7 +1420,8 @@ parse_uri (struct uri *uri, gchar *uristring, rspamd_mempool_t * pool) host_end++; } - else if (get_protocol_need_slash_after_host (uri->protocol) && *host_end != '?') { + else if (get_protocol_need_slash_after_host (uri->protocol) && *host_end != + '?') { /* The need for slash after the host component depends on the * need for a host component. -- The dangerous mind of Jonah */ if (!uri->hostlen) @@ -1114,7 +1446,7 @@ parse_uri (struct uri *uri, gchar *uristring, rspamd_mempool_t * pool) } convert_to_lowercase (uri->string, uri->protocollen); - convert_to_lowercase (uri->host, uri->hostlen); + convert_to_lowercase (uri->host, uri->hostlen); /* Decode %HH sequences in host name. This is important not so much to support %HH sequences in host names (which other browser don't), but to support binary characters (which will have been @@ -1132,12 +1464,12 @@ parse_uri (struct uri *uri, gchar *uristring, rspamd_mempool_t * pool) } static const gchar url_braces[] = { - '(', ')' , - '{', '}' , - '[', ']' , - '<', '>' , - '|', '|' , - '\'', '\'' + '(', ')', + '{', '}', + '[', ']', + '<', '>', + '|', '|', + '\'', '\'' }; static gboolean @@ -1156,22 +1488,28 @@ is_open_brace (gchar c) } static gboolean -url_file_start (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match) +url_file_start (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match) { match->m_begin = pos; return TRUE; } static gboolean -url_file_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match) +url_file_end (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match) { - const gchar *p; - gchar stop; - guint i; + const gchar *p; + gchar stop; + guint i; p = pos + strlen (match->pattern); stop = *p; if (*p == '/') { - p ++; + p++; } for (i = 0; i < G_N_ELEMENTS (url_braces) / 2; i += 2) { @@ -1182,7 +1520,7 @@ url_file_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_ } while (p < end && *p != stop && is_urlsafe (*p)) { - p ++; + p++; } if (p == begin) { @@ -1195,14 +1533,18 @@ url_file_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_ } static gboolean -url_tld_start (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match) +url_tld_start (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match) { - const gchar *p = pos; + const gchar *p = pos; /* Try to find the start of the url by finding any non-urlsafe character or whitespace/punctuation */ while (p >= begin) { - if ((!is_domain (*p) && *p != '.' && *p != '/') || g_ascii_isspace (*p)) { - p ++; + if ((!is_domain (*p) && *p != '.' && + *p != '/') || g_ascii_isspace (*p)) { + p++; if (!g_ascii_isalnum (*p)) { /* Urls cannot start with strange symbols */ return FALSE; @@ -1228,16 +1570,19 @@ url_tld_start (const gchar *begin, const gchar *end, const gchar *pos, url_match /* Urls cannot contain '/' in their body */ return FALSE; } - p --; + p--; } return FALSE; } static gboolean -url_tld_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match) +url_tld_end (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match) { - const gchar *p; + const gchar *p; /* A url must be finished by tld, so it must be followed by space character */ p = pos + strlen (match->pattern); @@ -1250,7 +1595,10 @@ url_tld_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t p = match->m_begin; /* Check common prefix */ if (g_ascii_strncasecmp (p, "http://", sizeof ("http://") - 1) == 0) { - return url_web_end (begin, end, match->m_begin + sizeof ("http://") - 1, match); + return url_web_end (begin, + end, + match->m_begin + sizeof ("http://") - 1, + match); } else { return url_web_end (begin, end, match->m_begin, match); @@ -1261,10 +1609,15 @@ url_tld_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t } static gboolean -url_web_start (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match) +url_web_start (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match) { /* Check what we have found */ - if (pos > begin && (g_ascii_strncasecmp (pos, "www", 3) == 0 || g_ascii_strncasecmp (pos, "ftp", 3) == 0)) { + if (pos > begin && + (g_ascii_strncasecmp (pos, "www", + 3) == 0 || g_ascii_strncasecmp (pos, "ftp", 3) == 0)) { if (!is_open_brace (*(pos - 1)) && !g_ascii_isspace (*(pos - 1))) { return FALSE; } @@ -1279,13 +1632,16 @@ url_web_start (const gchar *begin, const gchar *end, const gchar *pos, url_match } static gboolean -url_web_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match) +url_web_end (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match) { - const gchar *p, *c; - gchar open_brace = '\0', close_brace = '\0'; - gint brace_stack = 0; - gboolean passwd = FALSE; - guint port, i; + const gchar *p, *c; + gchar open_brace = '\0', close_brace = '\0'; + gint brace_stack = 0; + gboolean passwd = FALSE; + guint port, i; p = pos + strlen (match->pattern); for (i = 0; i < G_N_ELEMENTS (url_braces) / 2; i += 2) { @@ -1311,7 +1667,8 @@ url_web_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t p++; } - if ((p + 1) < end && *p == '.' && (is_atom (*(p + 1)) || *(p + 1) == '/')) { + if ((p + 1) < end && *p == '.' && + (is_atom (*(p + 1)) || *(p + 1) == '/')) { p++; } } @@ -1338,7 +1695,9 @@ domain: p++; } - if ((p + 1) < end && *p == '.' && (is_domain (*(p + 1)) || *(p + 1) == '/' || (*(p + 1) & 0x80))) { + if ((p + 1) < end && *p == '.' && + (is_domain (*(p + 1)) || *(p + 1) == '/' || + (*(p + 1) & 0x80))) { p++; } } @@ -1372,7 +1731,7 @@ domain: } } else { - passwd: +passwd: passwd = TRUE; c = p; @@ -1396,7 +1755,7 @@ domain: break; } - /* we have a '/' so there could be a path - fall through */ + /* we have a '/' so there could be a path - fall through */ case '/': /* we've detected a path component to our url */ p++; case '?': @@ -1434,15 +1793,18 @@ domain: static gboolean -url_email_start (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match) +url_email_start (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match) { - const gchar *p; + const gchar *p; /* Check what we have found */ if (pos > begin && *pos == '@') { /* Try to extract it with username */ p = pos - 1; while (p > begin && (is_domain (*p) || *p == '.' || *p == '_')) { - p --; + p--; } if (!is_domain (*p) && p != pos - 1) { match->m_begin = p + 1; @@ -1464,10 +1826,13 @@ url_email_start (const gchar *begin, const gchar *end, const gchar *pos, url_mat } static gboolean -url_email_end (const gchar *begin, const gchar *end, const gchar *pos, url_match_t *match) +url_email_end (const gchar *begin, + const gchar *end, + const gchar *pos, + url_match_t *match) { - const gchar *p; - gboolean got_at = FALSE; + const gchar *p; + gboolean got_at = FALSE; p = pos + strlen (match->pattern); if (*pos == '@') { @@ -1475,12 +1840,12 @@ url_email_end (const gchar *begin, const gchar *end, const gchar *pos, url_match } while (p < end && (is_domain (*p) || *p == '_' - || (*p == '@' && !got_at) || - (*p == '.' && p + 1 < end && is_domain (*(p + 1))))) { + || (*p == '@' && !got_at) || + (*p == '.' && p + 1 < end && is_domain (*(p + 1))))) { if (*p == '@') { got_at = TRUE; } - p ++; + p++; } match->m_len = p - match->m_begin; match->add_prefix = TRUE; @@ -1488,13 +1853,16 @@ url_email_end (const gchar *begin, const gchar *end, const gchar *pos, url_match } void -url_parse_text (rspamd_mempool_t * pool, struct rspamd_task *task, struct mime_text_part *part, gboolean is_html) +url_parse_text (rspamd_mempool_t * pool, + struct rspamd_task *task, + struct mime_text_part *part, + gboolean is_html) { - gint rc; - gchar *url_str = NULL, *url_start, *url_end; - struct uri *new; - struct process_exception *ex; - gchar *p, *end, *begin; + gint rc; + gchar *url_str = NULL, *url_start, *url_end; + struct uri *new; + struct process_exception *ex; + gchar *p, *end, *begin; if (!part->orig->data || part->orig->len == 0) { @@ -1514,15 +1882,19 @@ url_parse_text (rspamd_mempool_t * pool, struct rspamd_task *task, struct mime_t p = begin; } while (p < end) { - if (url_try_text (pool, p, end - p, &url_start, &url_end, &url_str, is_html)) { + if (url_try_text (pool, p, end - p, &url_start, &url_end, &url_str, + is_html)) { if (url_str != NULL) { new = rspamd_mempool_alloc0 (pool, sizeof (struct uri)); - ex = rspamd_mempool_alloc0 (pool, sizeof (struct process_exception)); + ex = + rspamd_mempool_alloc0 (pool, + sizeof (struct process_exception)); if (new != NULL) { g_strstrip (url_str); rc = parse_uri (new, url_str, pool); - if ((rc == URI_ERRNO_OK || rc == URI_ERRNO_NO_SLASHES || rc == URI_ERRNO_NO_HOST_SLASH) && - new->hostlen > 0) { + if ((rc == URI_ERRNO_OK || rc == URI_ERRNO_NO_SLASHES || + rc == URI_ERRNO_NO_HOST_SLASH) && + new->hostlen > 0) { ex->pos = url_start - begin; ex->len = url_end - url_start; if (new->protocol == PROTOCOL_MAILTO) { @@ -1537,10 +1909,14 @@ url_parse_text (rspamd_mempool_t * pool, struct rspamd_task *task, struct mime_t g_tree_insert (task->urls, new, new); } } - part->urls_offset = g_list_prepend (part->urls_offset, ex); + part->urls_offset = g_list_prepend ( + part->urls_offset, + ex); } else if (rc != URI_ERRNO_OK) { - msg_info ("extract of url '%s' failed: %s", url_str, url_strerror (rc)); + msg_info ("extract of url '%s' failed: %s", + url_str, + url_strerror (rc)); } } } @@ -1554,21 +1930,30 @@ url_parse_text (rspamd_mempool_t * pool, struct rspamd_task *task, struct mime_t /* Handle offsets of this part */ if (part->urls_offset != NULL) { part->urls_offset = g_list_reverse (part->urls_offset); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, part->urls_offset); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, part->urls_offset); } } gboolean -url_try_text (rspamd_mempool_t *pool, const gchar *begin, gsize len, gchar **start, gchar **fin, gchar **url_str, gboolean is_html) +url_try_text (rspamd_mempool_t *pool, + const gchar *begin, + gsize len, + gchar **start, + gchar **fin, + gchar **url_str, + gboolean is_html) { - const gchar *end, *pos; - gint idx, l; - struct url_matcher *matcher; - url_match_t m; + const gchar *end, *pos; + gint idx, l; + struct url_matcher *matcher; + url_match_t m; end = begin + len; if (url_init () == 0) { - if ((pos = rspamd_trie_lookup (url_scanner->patterns, begin, len, &idx)) == NULL) { + if ((pos = + rspamd_trie_lookup (url_scanner->patterns, begin, len, + &idx)) == NULL) { return FALSE; } else { @@ -1580,11 +1965,17 @@ url_try_text (rspamd_mempool_t *pool, const gchar *begin, gsize len, gchar **sta m.pattern = matcher->pattern; m.prefix = matcher->prefix; m.add_prefix = FALSE; - if (matcher->start (begin, end, pos, &m) && matcher->end (begin, end, pos, &m)) { + if (matcher->start (begin, end, pos, + &m) && matcher->end (begin, end, pos, &m)) { if (m.add_prefix) { l = m.m_len + 1 + strlen (m.prefix); *url_str = rspamd_mempool_alloc (pool, l); - rspamd_snprintf (*url_str, l, "%s%*s", m.prefix, m.m_len, m.m_begin); + rspamd_snprintf (*url_str, + l, + "%s%*s", + m.prefix, + m.m_len, + m.m_begin); } else { *url_str = rspamd_mempool_alloc (pool, m.m_len + 1); diff --git a/src/libserver/url.h b/src/libserver/url.h index 60535ba5c..d8877f279 100644 --- a/src/libserver/url.h +++ b/src/libserver/url.h @@ -43,24 +43,24 @@ struct uri { guint fragmentlen; /* Flags */ - gboolean ipv6; /* URI contains IPv6 host */ - gboolean form; /* URI originated from form */ + gboolean ipv6; /* URI contains IPv6 host */ + gboolean form; /* URI originated from form */ gboolean is_phished; /* URI maybe phishing */ }; enum uri_errno { - URI_ERRNO_OK, /* Parsing went well */ - URI_ERRNO_EMPTY, /* The URI string was empty */ - URI_ERRNO_INVALID_PROTOCOL, /* No protocol was found */ - URI_ERRNO_NO_SLASHES, /* Slashes after protocol missing */ - URI_ERRNO_TOO_MANY_SLASHES, /* Too many slashes after protocol */ - URI_ERRNO_TRAILING_DOTS, /* '.' after host */ - URI_ERRNO_NO_HOST, /* Host part is missing */ - URI_ERRNO_NO_PORT_COLON, /* ':' after host without port */ - URI_ERRNO_NO_HOST_SLASH, /* Slash after host missing */ - URI_ERRNO_IPV6_SECURITY, /* IPv6 security bug detected */ - URI_ERRNO_INVALID_PORT, /* Port number is bad */ - URI_ERRNO_INVALID_PORT_RANGE /* Port number is not within 0-65535 */ + URI_ERRNO_OK, /* Parsing went well */ + URI_ERRNO_EMPTY, /* The URI string was empty */ + URI_ERRNO_INVALID_PROTOCOL, /* No protocol was found */ + URI_ERRNO_NO_SLASHES, /* Slashes after protocol missing */ + URI_ERRNO_TOO_MANY_SLASHES, /* Too many slashes after protocol */ + URI_ERRNO_TRAILING_DOTS, /* '.' after host */ + URI_ERRNO_NO_HOST, /* Host part is missing */ + URI_ERRNO_NO_PORT_COLON, /* ':' after host without port */ + URI_ERRNO_NO_HOST_SLASH, /* Slash after host missing */ + URI_ERRNO_IPV6_SECURITY, /* IPv6 security bug detected */ + URI_ERRNO_INVALID_PORT, /* Port number is bad */ + URI_ERRNO_INVALID_PORT_RANGE /* Port number is not within 0-65535 */ }; enum protocol { @@ -81,7 +81,10 @@ enum protocol { * @param part current text part * @param is_html turn on html euristic */ -void url_parse_text (rspamd_mempool_t *pool, struct rspamd_task *task, struct mime_text_part *part, gboolean is_html); +void url_parse_text (rspamd_mempool_t *pool, + struct rspamd_task *task, + struct mime_text_part *part, + gboolean is_html); /* * Parse a single url into an uri structure @@ -89,7 +92,9 @@ void url_parse_text (rspamd_mempool_t *pool, struct rspamd_task *task, struct mi * @param uristring text form of url * @param uri url object, must be pre allocated */ -enum uri_errno parse_uri(struct uri *uri, gchar *uristring, rspamd_mempool_t *pool); +enum uri_errno parse_uri (struct uri *uri, + gchar *uristring, + rspamd_mempool_t *pool); /* * Try to extract url from a text @@ -101,11 +106,17 @@ enum uri_errno parse_uri(struct uri *uri, gchar *uristring, rspamd_mempool_t *po * @param url_str storage for url string(or NULL) * @return TRUE if url is found in specified text */ -gboolean url_try_text (rspamd_mempool_t *pool, const gchar *begin, gsize len, gchar **start, gchar **end, gchar **url_str, gboolean is_html); +gboolean url_try_text (rspamd_mempool_t *pool, + const gchar *begin, + gsize len, + gchar **start, + gchar **end, + gchar **url_str, + gboolean is_html); /* * Return text representation of url parsing error */ -const gchar* url_strerror (enum uri_errno err); +const gchar * url_strerror (enum uri_errno err); #endif diff --git a/src/libserver/worker_util.c b/src/libserver/worker_util.c index 74a83cb70..f2f04b397 100644 --- a/src/libserver/worker_util.c +++ b/src/libserver/worker_util.c @@ -26,24 +26,24 @@ #include "message.h" #include "lua/lua_common.h" -extern struct rspamd_main *rspamd_main; +extern struct rspamd_main *rspamd_main; /** * Return worker's control structure by its type * @param type * @return worker's control structure or NULL */ -worker_t* +worker_t * rspamd_get_worker_by_type (GQuark type) { - worker_t **cur; + worker_t **cur; cur = &workers[0]; while (*cur) { if (g_quark_from_string ((*cur)->name) == type) { return *cur; } - cur ++; + cur++; } return NULL; @@ -52,18 +52,21 @@ rspamd_get_worker_by_type (GQuark type) double rspamd_set_counter (const gchar *name, guint32 value) { - struct counter_data *cd; - double alpha; - gchar *key; + struct counter_data *cd; + double alpha; + gchar *key; cd = rspamd_hash_lookup (rspamd_main->counters, (gpointer) name); if (cd == NULL) { - cd = rspamd_mempool_alloc_shared (rspamd_main->counters->pool, sizeof (struct counter_data)); + cd = + rspamd_mempool_alloc_shared (rspamd_main->counters->pool, + sizeof (struct counter_data)); cd->value = value; cd->number = 0; key = rspamd_mempool_strdup_shared (rspamd_main->counters->pool, name); - rspamd_hash_insert (rspamd_main->counters, (gpointer) key, (gpointer) cd); + rspamd_hash_insert (rspamd_main->counters, (gpointer) key, + (gpointer) cd); } else { /* Calculate new value */ @@ -88,7 +91,7 @@ static void worker_sig_handler (gint signo, siginfo_t * info, void *unused) #endif { - struct timeval tv; + struct timeval tv; switch (signo) { case SIGINT: @@ -113,9 +116,9 @@ worker_sig_handler (gint signo, siginfo_t * info, void *unused) static void worker_sigusr2_handler (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *) arg; + struct rspamd_worker *worker = (struct rspamd_worker *) arg; /* Do not accept new connections, preparing to end worker's process */ - struct timeval tv; + struct timeval tv; if (!wanna_die) { tv.tv_sec = SOFT_SHUTDOWN_TIME; @@ -135,7 +138,7 @@ worker_sigusr2_handler (gint fd, short what, void *arg) static void worker_sigusr1_handler (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *) arg; + struct rspamd_worker *worker = (struct rspamd_worker *) arg; reopen_log (worker->srv->logger); @@ -144,16 +147,16 @@ worker_sigusr1_handler (gint fd, short what, void *arg) struct event_base * rspamd_prepare_worker (struct rspamd_worker *worker, const char *name, - void (*accept_handler)(int, short, void *)) + void (*accept_handler)(int, short, void *)) { - struct event_base *ev_base; - struct event *accept_event; - struct sigaction signals; - GList *cur; - gint listen_socket; + struct event_base *ev_base; + struct event *accept_event; + struct sigaction signals; + GList *cur; + gint listen_socket; #ifdef WITH_PROFILER - extern void _start (void), etext (void); + extern void _start (void), etext (void); monstartup ((u_long) & _start, (u_long) & etext); #endif @@ -173,23 +176,24 @@ rspamd_prepare_worker (struct rspamd_worker *worker, const char *name, if (listen_socket != -1) { accept_event = g_slice_alloc0 (sizeof (struct event)); event_set (accept_event, listen_socket, EV_READ | EV_PERSIST, - accept_handler, worker); + accept_handler, worker); event_base_set (ev_base, accept_event); event_add (accept_event, NULL); - worker->accept_events = g_list_prepend (worker->accept_events, accept_event); + worker->accept_events = g_list_prepend (worker->accept_events, + accept_event); } cur = g_list_next (cur); } /* SIGUSR2 handler */ signal_set (&worker->sig_ev_usr2, SIGUSR2, worker_sigusr2_handler, - (void *) worker); + (void *) worker); event_base_set (ev_base, &worker->sig_ev_usr2); signal_add (&worker->sig_ev_usr2, NULL); /* SIGUSR1 handler */ signal_set (&worker->sig_ev_usr1, SIGUSR1, worker_sigusr1_handler, - (void *) worker); + (void *) worker); event_base_set (ev_base, &worker->sig_ev_usr1); signal_add (&worker->sig_ev_usr1, NULL); @@ -199,8 +203,8 @@ rspamd_prepare_worker (struct rspamd_worker *worker, const char *name, void rspamd_worker_stop_accept (struct rspamd_worker *worker) { - GList *cur; - struct event *event; + GList *cur; + struct event *event; /* Remove all events */ cur = worker->accept_events; @@ -218,8 +222,8 @@ rspamd_worker_stop_accept (struct rspamd_worker *worker) void rspamd_controller_send_error (struct rspamd_http_connection_entry *entry, - gint code, - const gchar *error_msg) + gint code, + const gchar *error_msg) { struct rspamd_http_message *msg; @@ -230,14 +234,20 @@ rspamd_controller_send_error (struct rspamd_http_connection_entry *entry, msg->status = g_string_new (error_msg); rspamd_printf_gstring (msg->body, "{\"error\":\"%s\"}", error_msg); rspamd_http_connection_reset (entry->conn); - rspamd_http_connection_write_message (entry->conn, msg, NULL, - "application/json", entry, entry->conn->fd, entry->rt->ptv, entry->rt->ev_base); + rspamd_http_connection_write_message (entry->conn, + msg, + NULL, + "application/json", + entry, + entry->conn->fd, + entry->rt->ptv, + entry->rt->ev_base); entry->is_reply = TRUE; } void rspamd_controller_send_string (struct rspamd_http_connection_entry *entry, - const gchar *str) + const gchar *str) { struct rspamd_http_message *msg; @@ -246,14 +256,20 @@ rspamd_controller_send_string (struct rspamd_http_connection_entry *entry, msg->code = 200; msg->body = g_string_new (str); rspamd_http_connection_reset (entry->conn); - rspamd_http_connection_write_message (entry->conn, msg, NULL, - "application/json", entry, entry->conn->fd, entry->rt->ptv, entry->rt->ev_base); + rspamd_http_connection_write_message (entry->conn, + msg, + NULL, + "application/json", + entry, + entry->conn->fd, + entry->rt->ptv, + entry->rt->ev_base); entry->is_reply = TRUE; } void rspamd_controller_send_ucl (struct rspamd_http_connection_entry *entry, - ucl_object_t *obj) + ucl_object_t *obj) { struct rspamd_http_message *msg; @@ -263,7 +279,13 @@ rspamd_controller_send_ucl (struct rspamd_http_connection_entry *entry, msg->body = g_string_sized_new (BUFSIZ); rspamd_ucl_emit_gstring (obj, UCL_EMIT_JSON_COMPACT, msg->body); rspamd_http_connection_reset (entry->conn); - rspamd_http_connection_write_message (entry->conn, msg, NULL, - "application/json", entry, entry->conn->fd, entry->rt->ptv, entry->rt->ev_base); + rspamd_http_connection_write_message (entry->conn, + msg, + NULL, + "application/json", + entry, + entry->conn->fd, + entry->rt->ptv, + entry->rt->ev_base); entry->is_reply = TRUE; } diff --git a/src/libserver/worker_util.h b/src/libserver/worker_util.h index 2af32d1e8..54926e5f8 100644 --- a/src/libserver/worker_util.h +++ b/src/libserver/worker_util.h @@ -32,7 +32,7 @@ * @param type * @return worker's control structure or NULL */ -worker_t* rspamd_get_worker_by_type (GQuark type); +worker_t * rspamd_get_worker_by_type (GQuark type); /** * Set counter for a symbol @@ -57,7 +57,7 @@ struct rspamd_worker; */ struct event_base * rspamd_prepare_worker (struct rspamd_worker *worker, const char *name, - void (*accept_handler)(int, short, void *)); + void (*accept_handler)(int, short, void *)); /** * Stop accepting new connections for a worker @@ -66,9 +66,9 @@ rspamd_prepare_worker (struct rspamd_worker *worker, const char *name, void rspamd_worker_stop_accept (struct rspamd_worker *worker); typedef gint (*rspamd_controller_func_t) ( - struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, - struct module_ctx *ctx); + struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg, + struct module_ctx *ctx); struct rspamd_custom_controller_command { const gchar *command; @@ -85,8 +85,8 @@ struct rspamd_custom_controller_command { * @param error_msg error message */ void rspamd_controller_send_error (struct rspamd_http_connection_entry *entry, - gint code, - const gchar *error_msg); + gint code, + const gchar *error_msg); /** * Send a custom string using HTTP @@ -94,7 +94,7 @@ void rspamd_controller_send_error (struct rspamd_http_connection_entry *entry, * @param str string to send */ void rspamd_controller_send_string (struct rspamd_http_connection_entry *entry, - const gchar *str); + const gchar *str); /** * Send UCL using HTTP and JSON serialization @@ -102,6 +102,6 @@ void rspamd_controller_send_string (struct rspamd_http_connection_entry *entry, * @param obj object to send */ void rspamd_controller_send_ucl (struct rspamd_http_connection_entry *entry, - ucl_object_t *obj); + ucl_object_t *obj); #endif /* WORKER_UTIL_H_ */ diff --git a/src/libutil/aio_event.c b/src/libutil/aio_event.c index ccda37083..99b8845d5 100644 --- a/src/libutil/aio_event.c +++ b/src/libutil/aio_event.c @@ -47,7 +47,8 @@ # define SYS_io_submit 209 # define SYS_io_cancel 210 #else -# warning "aio is not supported on this platform, please contact author for details" +# warning \ + "aio is not supported on this platform, please contact author for details" # define SYS_io_setup 0 # define SYS_io_destroy 0 # define SYS_io_getevents 0 @@ -101,7 +102,7 @@ typedef enum io_iocb_cmd { struct iocb { /* these are internal to the kernel/libc. */ guint64 aio_data; /* data to be returned in event's data */ - guint32 PADDED(aio_key, aio_reserved1); + guint32 PADDED (aio_key, aio_reserved1); /* the kernel sets aio_key to the req # */ /* common fields */ @@ -127,27 +128,31 @@ struct iocb { }; struct io_event { - guint64 data; /* the data field from the iocb */ - guint64 obj; /* what iocb this event came from */ - gint64 res; /* result code for this event */ - gint64 res2; /* secondary result */ + guint64 data; /* the data field from the iocb */ + guint64 obj; /* what iocb this event came from */ + gint64 res; /* result code for this event */ + gint64 res2; /* secondary result */ }; /* Linux specific io calls */ static int io_setup (guint nr_reqs, aio_context_t *ctx) { - return syscall (SYS_io_setup, nr_reqs, ctx); + return syscall (SYS_io_setup, nr_reqs, ctx); } static int io_destroy (aio_context_t ctx) { - return syscall (SYS_io_destroy, ctx); + return syscall (SYS_io_destroy, ctx); } static int -io_getevents (aio_context_t ctx, long min_nr, long nr, struct io_event *events, struct timespec *tmo) +io_getevents (aio_context_t ctx, + long min_nr, + long nr, + struct io_event *events, + struct timespec *tmo) { return syscall (SYS_io_getevents, ctx, min_nr, nr, events, tmo); } @@ -155,13 +160,13 @@ io_getevents (aio_context_t ctx, long min_nr, long nr, struct io_event *events, static int io_submit (aio_context_t ctx, long n, struct iocb **paiocb) { - return syscall (SYS_io_submit, ctx, n, paiocb); + return syscall (SYS_io_submit, ctx, n, paiocb); } static int io_cancel (aio_context_t ctx, struct iocb *iocb, struct io_event *result) { - return syscall (SYS_io_cancel, ctx, iocb, result); + return syscall (SYS_io_cancel, ctx, iocb, result); } # ifndef HAVE_SYS_EVENTFD_H @@ -179,7 +184,7 @@ eventfd (guint initval, guint flags) */ struct aio_context { struct event_base *base; - gboolean has_aio; /**< Whether we have aio support on a system */ + gboolean has_aio; /**< Whether we have aio support on a system */ #ifdef LINUX /* Eventfd variant */ gint event_fd; @@ -196,12 +201,12 @@ struct aio_context { static void rspamd_eventfdcb (gint fd, gshort what, gpointer ud) { - struct aio_context *ctx = ud; - guint64 ready; - gint done, i; - struct io_event event[32]; - struct timespec ts; - struct io_cbdata *ev_data; + struct aio_context *ctx = ud; + guint64 ready; + gint done, i; + struct io_event event[32]; + struct timespec ts; + struct io_cbdata *ev_data; /* Eventfd returns number of events ready got from kernel */ if (read (fd, &ready, 8) != 8) { @@ -221,10 +226,14 @@ rspamd_eventfdcb (gint fd, gshort what, gpointer ud) if (done > 0) { ready -= done; - for (i = 0; i < done; i ++) { + for (i = 0; i < done; i++) { ev_data = (struct io_cbdata *) (uintptr_t) event[i].data; /* Call this callback */ - ev_data->cb (ev_data->fd, event[i].res, ev_data->len, ev_data->buf, ev_data->ud); + ev_data->cb (ev_data->fd, + event[i].res, + ev_data->len, + ev_data->buf, + ev_data->ud); if (ev_data->io_buf) { free (ev_data->io_buf); } @@ -247,10 +256,10 @@ rspamd_eventfdcb (gint fd, gshort what, gpointer ud) /** * Initialize aio with specified event base */ -struct aio_context* +struct aio_context * rspamd_aio_init (struct event_base *base) { - struct aio_context *new; + struct aio_context *new; /* First of all we need to detect which type of aio we can try to use */ new = g_malloc0 (sizeof (struct aio_context)); @@ -269,7 +278,11 @@ rspamd_aio_init (struct event_base *base) close (new->event_fd); } else { - event_set (&new->eventfd_ev, new->event_fd, EV_READ|EV_PERSIST, rspamd_eventfdcb, new); + event_set (&new->eventfd_ev, + new->event_fd, + EV_READ | EV_PERSIST, + rspamd_eventfdcb, + new); event_base_set (new->base, &new->eventfd_ev); event_add (&new->eventfd_ev, NULL); if (io_setup (MAX_AIO_EV, &new->io_ctx) == -1) { @@ -294,7 +307,7 @@ rspamd_aio_init (struct event_base *base) gint rspamd_aio_open (struct aio_context *ctx, const gchar *path, int flags) { - gint fd = -1; + gint fd = -1; /* Fallback */ if (!ctx->has_aio) { return open (path, flags); @@ -315,14 +328,20 @@ rspamd_aio_open (struct aio_context *ctx, const gchar *path, int flags) * Asynchronous read of file */ gint -rspamd_aio_read (gint fd, gpointer buf, guint64 len, guint64 offset, struct aio_context *ctx, rspamd_aio_cb cb, gpointer ud) +rspamd_aio_read (gint fd, + gpointer buf, + guint64 len, + guint64 offset, + struct aio_context *ctx, + rspamd_aio_cb cb, + gpointer ud) { - struct io_cbdata *cbdata; - gint r = -1; + struct io_cbdata *cbdata; + gint r = -1; if (ctx->has_aio) { #ifdef LINUX - struct iocb *iocb[1]; + struct iocb *iocb[1]; cbdata = g_slice_alloc (sizeof (struct io_cbdata)); cbdata->cb = cb; @@ -385,14 +404,20 @@ blocking: * Asynchronous write of file */ gint -rspamd_aio_write (gint fd, gpointer buf, guint64 len, guint64 offset, struct aio_context *ctx, rspamd_aio_cb cb, gpointer ud) +rspamd_aio_write (gint fd, + gpointer buf, + guint64 len, + guint64 offset, + struct aio_context *ctx, + rspamd_aio_cb cb, + gpointer ud) { - struct io_cbdata *cbdata; - gint r = -1; + struct io_cbdata *cbdata; + gint r = -1; if (ctx->has_aio) { #ifdef LINUX - struct iocb *iocb[1]; + struct iocb *iocb[1]; cbdata = g_slice_alloc (sizeof (struct io_cbdata)); cbdata->cb = cb; @@ -461,12 +486,12 @@ blocking: gint rspamd_aio_close (gint fd, struct aio_context *ctx) { - gint r = -1; + gint r = -1; if (ctx->has_aio) { #ifdef LINUX - struct iocb iocb; - struct io_event ev; + struct iocb iocb; + struct io_event ev; memset (&iocb, 0, sizeof (struct iocb)); iocb.aio_fildes = fd; diff --git a/src/libutil/aio_event.h b/src/libutil/aio_event.h index 45f6015de..7eaf95c2b 100644 --- a/src/libutil/aio_event.h +++ b/src/libutil/aio_event.h @@ -35,12 +35,13 @@ struct aio_context; /** * Callback for notifying */ -typedef void (*rspamd_aio_cb) (gint fd, gint res, guint64 len, gpointer data, gpointer ud); +typedef void (*rspamd_aio_cb) (gint fd, gint res, guint64 len, gpointer data, + gpointer ud); /** * Initialize aio with specified event base */ -struct aio_context* rspamd_aio_init (struct event_base *base); +struct aio_context * rspamd_aio_init (struct event_base *base); /** * Open file for aio @@ -51,13 +52,13 @@ gint rspamd_aio_open (struct aio_context *ctx, const gchar *path, int flags); * Asynchronous read of file */ gint rspamd_aio_read (gint fd, gpointer buf, guint64 len, guint64 offset, - struct aio_context *ctx, rspamd_aio_cb cb, gpointer ud); + struct aio_context *ctx, rspamd_aio_cb cb, gpointer ud); /** * Asynchronous write of file */ gint rspamd_aio_write (gint fd, gpointer buf, guint64 len, guint64 offset, - struct aio_context *ctx, rspamd_aio_cb cb, gpointer ud); + struct aio_context *ctx, rspamd_aio_cb cb, gpointer ud); /** * Close of aio operations diff --git a/src/libutil/bloom.c b/src/libutil/bloom.c index f857d2e49..044cdaa10 100644 --- a/src/libutil/bloom.c +++ b/src/libutil/bloom.c @@ -30,40 +30,51 @@ #define SIZE_BIT 4 /* These macroes are for 4 bits for counting element */ -#define INCBIT(a, n, acc) do { \ - acc = a[n * SIZE_BIT / CHAR_BIT] & (0xF << (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT)); \ - acc ++; \ - acc &= 0xF; \ - \ - a[n * SIZE_BIT / CHAR_BIT] &= (0xF << (4 - (n % (CHAR_BIT/SIZE_BIT) * SIZE_BIT))); \ - a[n * SIZE_BIT / CHAR_BIT] |= (acc << (n % (CHAR_BIT/SIZE_BIT) * SIZE_BIT)); \ +#define INCBIT(a, n, acc) do { \ + acc = \ + a[n * SIZE_BIT / CHAR_BIT] & (0xF << \ + (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT)); \ + acc ++; \ + acc &= 0xF; \ + \ + a[n * SIZE_BIT / \ + CHAR_BIT] &= (0xF << (4 - (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT))); \ + a[n * SIZE_BIT / \ + CHAR_BIT] |= (acc << (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT)); \ } while (0); -#define DECBIT(a, n, acc) do { \ - acc = a[n * SIZE_BIT / CHAR_BIT] & (0xF << (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT)); \ - acc --; \ - acc &= 0xF; \ - \ - a[n * SIZE_BIT / CHAR_BIT] &= (0xF << (4 - (n % (CHAR_BIT/SIZE_BIT) * SIZE_BIT))); \ - a[n * SIZE_BIT / CHAR_BIT] |= (acc << (n % (CHAR_BIT/SIZE_BIT) * SIZE_BIT)); \ +#define DECBIT(a, n, acc) do { \ + acc = \ + a[n * SIZE_BIT / CHAR_BIT] & (0xF << \ + (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT)); \ + acc --; \ + acc &= 0xF; \ + \ + a[n * SIZE_BIT / \ + CHAR_BIT] &= (0xF << (4 - (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT))); \ + a[n * SIZE_BIT / \ + CHAR_BIT] |= (acc << (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT)); \ } while (0); -#define GETBIT(a, n) (a[n * SIZE_BIT / CHAR_BIT] & (0xF << (n % (CHAR_BIT/SIZE_BIT) * SIZE_BIT))) +#define GETBIT(a, \ + n) (a[n * SIZE_BIT / CHAR_BIT] & (0xF << \ + (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT))) /* Common hash functions */ -rspamd_bloom_filter_t * +rspamd_bloom_filter_t * rspamd_bloom_create (size_t size, size_t nfuncs, ...) { - rspamd_bloom_filter_t *bloom; - va_list l; - gsize n; + rspamd_bloom_filter_t *bloom; + va_list l; + gsize n; if (!(bloom = g_malloc (sizeof (rspamd_bloom_filter_t)))) { return NULL; } - if (!(bloom->a = g_new0 (gchar, (size + CHAR_BIT - 1) / CHAR_BIT * SIZE_BIT))) { + if (!(bloom->a = + g_new0 (gchar, (size + CHAR_BIT - 1) / CHAR_BIT * SIZE_BIT))) { g_free (bloom); return NULL; } @@ -96,9 +107,9 @@ rspamd_bloom_destroy (rspamd_bloom_filter_t * bloom) gboolean rspamd_bloom_add (rspamd_bloom_filter_t * bloom, const gchar *s) { - size_t n, len; - u_char t; - guint v; + size_t n, len; + u_char t; + guint v; if (s == NULL) { return FALSE; @@ -115,9 +126,9 @@ rspamd_bloom_add (rspamd_bloom_filter_t * bloom, const gchar *s) gboolean rspamd_bloom_del (rspamd_bloom_filter_t * bloom, const gchar *s) { - size_t n, len; - u_char t; - guint v; + size_t n, len; + u_char t; + guint v; if (s == NULL) { return FALSE; @@ -135,8 +146,8 @@ rspamd_bloom_del (rspamd_bloom_filter_t * bloom, const gchar *s) gboolean rspamd_bloom_check (rspamd_bloom_filter_t * bloom, const gchar *s) { - size_t n, len; - guint v; + size_t n, len; + guint v; if (s == NULL) { return FALSE; diff --git a/src/libutil/bloom.h b/src/libutil/bloom.h index 380143c80..9866e9988 100644 --- a/src/libutil/bloom.h +++ b/src/libutil/bloom.h @@ -4,10 +4,10 @@ #include "config.h" typedef struct rspamd_bloom_filter_s { - size_t asize; - gchar *a; - size_t nfuncs; - guint32 *seeds; + size_t asize; + gchar *a; + size_t nfuncs; + guint32 *seeds; } rspamd_bloom_filter_t; @@ -23,7 +23,7 @@ typedef struct rspamd_bloom_filter_s { * @param nfuncs number of hash functions * @param ... hash functions list */ -rspamd_bloom_filter_t* rspamd_bloom_create (size_t size, size_t nfuncs, ...); +rspamd_bloom_filter_t * rspamd_bloom_create (size_t size, size_t nfuncs, ...); /* * Destroy bloom filter diff --git a/src/libutil/diff.c b/src/libutil/diff.c index 4038d8680..cee175ceb 100644 --- a/src/libutil/diff.c +++ b/src/libutil/diff.c @@ -39,8 +39,8 @@ #include "diff.h" -#define FV(k) _v(ctx, (k), 0) -#define RV(k) _v(ctx, (k), 1) +#define FV(k) _v (ctx, (k), 0) +#define RV(k) _v (ctx, (k), 1) #define MAX_DIFF 1024 @@ -58,7 +58,8 @@ struct middle_snake }; static -void maybe_resize_array(GArray *arr, guint k) +void +maybe_resize_array (GArray *arr, guint k) { if (k > arr->len) { g_array_set_size (arr, k); @@ -67,7 +68,7 @@ void maybe_resize_array(GArray *arr, guint k) } static void -_setv(struct _ctx *ctx, gint k, gint r, gint val) +_setv (struct _ctx *ctx, gint k, gint r, gint val) { gint j; gint *i; @@ -81,7 +82,7 @@ _setv(struct _ctx *ctx, gint k, gint r, gint val) } static gint -_v(struct _ctx *ctx, gint k, gint r) +_v (struct _ctx *ctx, gint k, gint r) { gint j; @@ -91,8 +92,8 @@ _v(struct _ctx *ctx, gint k, gint r) } static gint -_find_middle_snake(const void *a, gint aoff, gint n, const void *b, - gint boff, gint m, struct _ctx *ctx, struct middle_snake *ms) +_find_middle_snake (const void *a, gint aoff, gint n, const void *b, + gint boff, gint m, struct _ctx *ctx, struct middle_snake *ms) { gint delta, odd, mid, d; @@ -101,7 +102,7 @@ _find_middle_snake(const void *a, gint aoff, gint n, const void *b, mid = (n + m) / 2; mid += odd; - _setv (ctx, 1, 0, 0); + _setv (ctx, 1, 0, 0); _setv (ctx, delta - 1, 1, n); for (d = 0; d <= mid; d++) { @@ -112,11 +113,11 @@ _find_middle_snake(const void *a, gint aoff, gint n, const void *b, } for (k = d; k >= -d; k -= 2) { - if (k == -d || (k != d && FV(k - 1) < FV(k + 1))) { - x = FV(k + 1); + if (k == -d || (k != d && FV (k - 1) < FV (k + 1))) { + x = FV (k + 1); } else { - x = FV(k - 1) + 1; + x = FV (k - 1) + 1; } y = x - k; @@ -131,7 +132,7 @@ _find_middle_snake(const void *a, gint aoff, gint n, const void *b, _setv (ctx, k, 0, x); if (odd && k >= (delta - (d - 1)) && k <= (delta + (d - 1))) { - if (x >= RV(k)) { + if (x >= RV (k)) { ms->u = x; ms->v = y; return 2 * d - 1; @@ -141,11 +142,11 @@ _find_middle_snake(const void *a, gint aoff, gint n, const void *b, for (k = d; k >= -d; k -= 2) { gint kr = (n - m) + k; - if (k == d || (k != -d && RV(kr - 1) < RV(kr + 1))) { - x = RV(kr - 1); + if (k == d || (k != -d && RV (kr - 1) < RV (kr + 1))) { + x = RV (kr - 1); } else { - x = RV(kr + 1) - 1; + x = RV (kr + 1) - 1; } y = x - kr; @@ -160,7 +161,7 @@ _find_middle_snake(const void *a, gint aoff, gint n, const void *b, _setv (ctx, kr, 1, x); if (!odd && kr >= -d && kr <= d) { - if (x <= FV(kr)) { + if (x <= FV (kr)) { ms->x = x; ms->y = y; return 2 * d; @@ -175,7 +176,7 @@ _find_middle_snake(const void *a, gint aoff, gint n, const void *b, } static void -_edit(struct _ctx *ctx, gint op, gint off, gint len) +_edit (struct _ctx *ctx, gint op, gint off, gint len) { struct diff_edit *e = NULL, newe; @@ -201,8 +202,8 @@ _edit(struct _ctx *ctx, gint op, gint off, gint len) } static gint -_ses(const void *a, gint aoff, gint n, const void *b, gint boff, - gint m, struct _ctx *ctx) +_ses (const void *a, gint aoff, gint n, const void *b, gint boff, + gint m, struct _ctx *ctx) { struct middle_snake ms = { .x = 0, @@ -269,22 +270,22 @@ _ses(const void *a, gint aoff, gint n, const void *b, gint boff, if (m > n) { if (x == u) { - _edit (ctx, DIFF_MATCH, aoff, n); + _edit (ctx, DIFF_MATCH, aoff, n); _edit (ctx, DIFF_INSERT, boff + (m - 1), 1); } else { _edit (ctx, DIFF_INSERT, boff, 1); - _edit (ctx, DIFF_MATCH, aoff, n); + _edit (ctx, DIFF_MATCH, aoff, n); } } else { if (x == u) { - _edit (ctx, DIFF_MATCH, aoff, m); + _edit (ctx, DIFF_MATCH, aoff, m); _edit (ctx, DIFF_DELETE, aoff + (n - 1), 1); } else { - _edit (ctx, DIFF_DELETE, aoff, 1); - _edit (ctx, DIFF_MATCH, aoff + 1, m); + _edit (ctx, DIFF_DELETE, aoff, 1); + _edit (ctx, DIFF_MATCH, aoff + 1, m); } } } @@ -294,8 +295,8 @@ _ses(const void *a, gint aoff, gint n, const void *b, gint boff, } gint -rspamd_diff(const void *a, gint aoff, gint n, const void *b, gint boff, gint m, - gint dmax, GArray *ses, gint *sn) +rspamd_diff (const void *a, gint aoff, gint n, const void *b, gint boff, gint m, + gint dmax, GArray *ses, gint *sn) { struct _ctx ctx; gint d, x, y; @@ -345,14 +346,14 @@ compare_diff_distance_unnormalized (f_str_t *s1, f_str_t *s2) ses = g_array_sized_new (FALSE, TRUE, sizeof (struct diff_edit), MAX_DIFF); if (rspamd_diff (s1->begin, 0, s1->len, - s2->begin, 0, s2->len, MAX_DIFF, ses, NULL) == -1) { + s2->begin, 0, s2->len, MAX_DIFF, ses, NULL) == -1) { /* Diff failed, strings are different */ g_array_free (ses, TRUE); return 0; } - for (i = 0; i < ses->len; i ++) { - e = &g_array_index(ses, struct diff_edit, i); + for (i = 0; i < ses->len; i++) { + e = &g_array_index (ses, struct diff_edit, i); if (e->op != DIFF_MATCH) { distance += e->len; } @@ -367,7 +368,10 @@ guint32 compare_diff_distance (f_str_t *s1, f_str_t *s2) { - return 100 - (2 * compare_diff_distance_unnormalized (s1, s2) * 100) / (s1->len + s2->len); + return 100 - + (2 * + compare_diff_distance_unnormalized (s1, + s2) * 100) / (s1->len + s2->len); } @@ -394,9 +398,9 @@ compare_diff_distance_normalized (f_str_t *s1, f_str_t *s2) if (!g_ascii_isspace (*h)) { *t++ = g_ascii_tolower (*h); } - h ++; - p1 ++; - r1 --; + h++; + p1++; + r1--; } t1.begin = b1; @@ -409,9 +413,9 @@ compare_diff_distance_normalized (f_str_t *s1, f_str_t *s2) if (!g_ascii_isspace (*h)) { *t++ = g_ascii_tolower (*h); } - h ++; - p2 ++; - r2 --; + h++; + p2++; + r2--; } t2.begin = b2; @@ -424,20 +428,20 @@ compare_diff_distance_normalized (f_str_t *s1, f_str_t *s2) h = p1; while (r1 > 0) { if (!g_ascii_isspace (*h)) { - cur_diff ++; + cur_diff++; } - r1 --; - h ++; + r1--; + h++; } } else if (r2 > 0) { h = p2; while (r2 > 0) { if (!g_ascii_isspace (*h)) { - cur_diff ++; + cur_diff++; } - r2 --; - h ++; + r2--; + h++; } } diff --git a/src/libutil/diff.h b/src/libutil/diff.h index cea5e5d4a..7caa35dd8 100644 --- a/src/libutil/diff.h +++ b/src/libutil/diff.h @@ -55,8 +55,15 @@ struct diff_edit * @param sn here would be stored a number of differences between a and b * @return distance between strings or -1 in case of error */ -gint rspamd_diff(const void *a, gint aoff, gint n, const void *b, gint boff, gint m, - gint dmax, GArray *ses, gint *sn); +gint rspamd_diff (const void *a, + gint aoff, + gint n, + const void *b, + gint boff, + gint m, + gint dmax, + GArray *ses, + gint *sn); /* * Calculate distance between two strings (in percentage) using diff algorithm. @@ -68,7 +75,7 @@ guint32 compare_diff_distance (f_str_t *s1, f_str_t *s2); * Calculate distance between two strings (in percentage) using diff algorithm. Strings are normalized before: * all spaces are removed and all characters are lowercased. * @return 100 in case of identical strings and 0 in case of totally different strings. -*/ + */ guint32 compare_diff_distance_normalized (f_str_t *s1, f_str_t *s2); #endif /* DIFF_H_ */ diff --git a/src/libutil/fstring.c b/src/libutil/fstring.c index 098824101..a83bbd662 100644 --- a/src/libutil/fstring.c +++ b/src/libutil/fstring.c @@ -30,7 +30,7 @@ ssize_t fstrchr (f_str_t * src, gchar c) { - register size_t cur = 0; + register size_t cur = 0; while (cur < src->len) { if (*(src->begin + cur) == c) { @@ -48,7 +48,7 @@ fstrchr (f_str_t * src, gchar c) ssize_t fstrrchr (f_str_t * src, gchar c) { - register ssize_t cur = src->len; + register ssize_t cur = src->len; while (cur > 0) { if (*(src->begin + cur) == c) { @@ -66,7 +66,7 @@ fstrrchr (f_str_t * src, gchar c) ssize_t fstrstr (f_str_t * orig, f_str_t * pattern) { - register size_t cur = 0, pcur = 0; + register size_t cur = 0, pcur = 0; if (pattern->len > orig->len) { return -1; @@ -97,16 +97,18 @@ fstrstr (f_str_t * orig, f_str_t * pattern) ssize_t fstrstri (f_str_t * orig, f_str_t * pattern) { - register size_t cur = 0, pcur = 0; + register size_t cur = 0, pcur = 0; if (pattern->len > orig->len) { return -1; } while (cur < orig->len) { - if (g_ascii_tolower (*(orig->begin + cur)) == g_ascii_tolower (*pattern->begin)) { + if (g_ascii_tolower (*(orig->begin + cur)) == + g_ascii_tolower (*pattern->begin)) { while (cur < orig->len && pcur < pattern->len) { - if (g_ascii_tolower (*(orig->begin + cur)) != g_ascii_tolower (*(pattern->begin + pcur))) { + if (g_ascii_tolower (*(orig->begin + cur)) != + g_ascii_tolower (*(pattern->begin + pcur))) { pcur = 0; break; } @@ -127,14 +129,14 @@ fstrstri (f_str_t * orig, f_str_t * pattern) * word contains parsed word * * Return: -1 - no new words can be extracted - * 1 - word was extracted and there are more words - * 0 - last word extracted + * 1 - word was extracted and there are more words + * 0 - last word extracted */ gint fstrtok (f_str_t * text, const gchar *sep, f_tok_t * state) { - register size_t cur; - const gchar *csep = sep; + register size_t cur; + const gchar *csep = sep; if (state->pos >= text->len) { return -1; @@ -170,7 +172,7 @@ fstrtok (f_str_t * text, const gchar *sep, f_tok_t * state) size_t fstrcpy (f_str_t * dest, f_str_t * src) { - register size_t cur = 0; + register size_t cur = 0; if (dest->size < src->len) { return 0; @@ -190,8 +192,8 @@ fstrcpy (f_str_t * dest, f_str_t * src) size_t fstrcat (f_str_t * dest, f_str_t * src) { - register size_t cur = 0; - gchar *p = dest->begin + dest->len; + register size_t cur = 0; + gchar *p = dest->begin + dest->len; if (dest->size < src->len + dest->len) { return 0; @@ -212,10 +214,10 @@ fstrcat (f_str_t * dest, f_str_t * src) /* * Make copy of string to 0-terminated string */ -gchar * +gchar * fstrcstr (f_str_t * str, rspamd_mempool_t * pool) { - gchar *res; + gchar *res; res = rspamd_mempool_alloc (pool, str->len + 1); /* Do not allow multiply \0 characters */ @@ -247,7 +249,7 @@ fstrpush (f_str_t * dest, gchar c) gint fstrpush_unichar (f_str_t * dest, gunichar c) { - int l; + int l; if (dest->size < dest->len) { /* Need to reallocate string */ return 0; @@ -261,10 +263,10 @@ fstrpush_unichar (f_str_t * dest, gunichar c) /* * Allocate memory for f_str_t */ -f_str_t * +f_str_t * fstralloc (rspamd_mempool_t * pool, size_t len) { - f_str_t *res = rspamd_mempool_alloc (pool, sizeof (f_str_t)); + f_str_t *res = rspamd_mempool_alloc (pool, sizeof (f_str_t)); res->begin = rspamd_mempool_alloc (pool, len); @@ -276,10 +278,10 @@ fstralloc (rspamd_mempool_t * pool, size_t len) /* * Allocate memory for f_str_t from temporary pool */ -f_str_t * +f_str_t * fstralloc_tmp (rspamd_mempool_t * pool, size_t len) { - f_str_t *res = rspamd_mempool_alloc_tmp (pool, sizeof (f_str_t)); + f_str_t *res = rspamd_mempool_alloc_tmp (pool, sizeof (f_str_t)); res->begin = rspamd_mempool_alloc_tmp (pool, len); @@ -291,10 +293,10 @@ fstralloc_tmp (rspamd_mempool_t * pool, size_t len) /* * Truncate string to its len */ -f_str_t * +f_str_t * fstrtruncate (rspamd_mempool_t * pool, f_str_t * orig) { - f_str_t *res; + f_str_t *res; if (orig == NULL || orig->len == 0 || orig->size <= orig->len) { return orig; @@ -312,10 +314,10 @@ fstrtruncate (rspamd_mempool_t * pool, f_str_t * orig) /* * Enlarge string to new size */ -f_str_t * +f_str_t * fstrgrow (rspamd_mempool_t * pool, f_str_t * orig, size_t newlen) { - f_str_t *res; + f_str_t *res; if (orig == NULL || orig->len == 0 || orig->size >= newlen) { return orig; @@ -333,7 +335,7 @@ fstrgrow (rspamd_mempool_t * pool, f_str_t * orig, size_t newlen) static guint32 fstrhash_c (gchar c, guint32 hval) { - guint32 tmp; + guint32 tmp; /* * xor in the current byte against each byte of hval * (which alone gaurantees that every bit of input will have @@ -364,9 +366,9 @@ fstrhash_c (gchar c, guint32 hval) guint32 fstrhash (f_str_t * str) { - size_t i; - guint32 hval; - gchar *c = str->begin; + size_t i; + guint32 hval; + gchar *c = str->begin; if (str == NULL) { return 0; @@ -385,11 +387,11 @@ fstrhash (f_str_t * str) guint32 fstrhash_lowercase (f_str_t * str, gboolean is_utf) { - gsize i; - guint32 j, hval; - const gchar *p = str->begin, *end = NULL; - gchar t; - gunichar uc; + gsize i; + guint32 j, hval; + const gchar *p = str->begin, *end = NULL; + gchar t; + gunichar uc; if (str == NULL) { return 0; @@ -403,7 +405,7 @@ fstrhash_lowercase (f_str_t * str, gboolean is_utf) } while (p < end) { uc = g_unichar_tolower (g_utf8_get_char (p)); - for (j = 0; j < sizeof (gunichar); j ++) { + for (j = 0; j < sizeof (gunichar); j++) { t = (uc >> (j * 8)) & 0xff; if (t != 0) { hval = fstrhash_c (t, hval); @@ -427,8 +429,8 @@ fstrhash_lowercase (f_str_t * str, gboolean is_utf) void fstrstrip (f_str_t * str) { - gchar *p = str->begin; - guint r = 0; + gchar *p = str->begin; + guint r = 0; while (r < str->len) { if (g_ascii_isspace (*p)) { diff --git a/src/libutil/fstring.h b/src/libutil/fstring.h index bd680e365..3cba00592 100644 --- a/src/libutil/fstring.h +++ b/src/libutil/fstring.h @@ -8,7 +8,8 @@ #include "config.h" #include "mem_pool.h" -#define update_buf_size(x) (x)->free = (x)->buf->size - ((x)->pos - (x)->buf->begin); (x)->buf->len = (x)->pos - (x)->buf->begin +#define update_buf_size(x) (x)->free = (x)->buf->size - \ + ((x)->pos - (x)->buf->begin); (x)->buf->len = (x)->pos - (x)->buf->begin typedef struct f_str_s { gchar *begin; @@ -76,22 +77,22 @@ gint fstrpush_unichar (f_str_t *dest, gunichar c); /* * Allocate memory for f_str_t */ -f_str_t* fstralloc (rspamd_mempool_t *pool, size_t len); +f_str_t * fstralloc (rspamd_mempool_t *pool, size_t len); /* * Allocate memory for f_str_t from temporary pool */ -f_str_t* fstralloc_tmp (rspamd_mempool_t *pool, size_t len); +f_str_t * fstralloc_tmp (rspamd_mempool_t *pool, size_t len); /* * Truncate string to its len */ -f_str_t* fstrtruncate (rspamd_mempool_t *pool, f_str_t *orig); +f_str_t * fstrtruncate (rspamd_mempool_t *pool, f_str_t *orig); /* * Enlarge string to new size */ -f_str_t* fstrgrow (rspamd_mempool_t *pool, f_str_t *orig, size_t newlen); +f_str_t * fstrgrow (rspamd_mempool_t *pool, f_str_t *orig, size_t newlen); /* * Return specified character @@ -110,7 +111,7 @@ guint32 fstrhash_lowercase (f_str_t *str, gboolean is_utf); /* * Make copy of string to 0-terminated string */ -gchar* fstrcstr (f_str_t *str, rspamd_mempool_t *pool); +gchar * fstrcstr (f_str_t *str, rspamd_mempool_t *pool); /* * Strip fstr string from space symbols diff --git a/src/libutil/fuzzy.c b/src/libutil/fuzzy.c index 7e8a01ce3..3ba20bbad 100644 --- a/src/libutil/fuzzy.c +++ b/src/libutil/fuzzy.c @@ -35,19 +35,20 @@ #define MIN_FUZZY_BLOCK_SIZE 3 #define HASH_INIT 0x28021967 -static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char *b64 = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; struct roll_state { - guint32 h[3]; - gchar window[ROLL_WINDOW_SIZE]; - gint n; + guint32 h[3]; + gchar window[ROLL_WINDOW_SIZE]; + gint n; }; -static struct roll_state rs; +static struct roll_state rs; /* Rolling hash function based on Adler-32 checksum */ -static guint32 +static guint32 fuzzy_roll_hash (guint c) { /* Check window position */ @@ -72,19 +73,20 @@ fuzzy_roll_hash (guint c) } /* A simple non-rolling hash, based on the FNV hash */ -static guint32 +static guint32 fuzzy_fnv_hash (guint c, guint32 hval) { hval ^= c; - hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); + hval += + (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); return hval; } /* Calculate blocksize depending on length of input */ -static guint32 +static guint32 fuzzy_blocksize (guint32 len) { - guint32 nlen = MIN_FUZZY_BLOCK_SIZE; + guint32 nlen = MIN_FUZZY_BLOCK_SIZE; while (nlen * (FUZZY_HASHLEN - 1) < len) { nlen *= 2; @@ -141,12 +143,12 @@ fuzzy_update2 (fuzzy_hash_t * h1, fuzzy_hash_t *h2, guint c) guint32 lev_distance (gchar *s1, gint len1, gchar *s2, gint len2) { - gint i; - gint *row; /* we only need to keep one row of costs */ - gint *end; - gint half, nx; - gchar *sx, *char2p, char1; - gint *p, D, x, offset, c3; + gint i; + gint *row; /* we only need to keep one row of costs */ + gint *end; + gint half, nx; + gchar *sx, *char2p, char1; + gint *p, D, x, offset, c3; /* strip common prefix */ while (len1 > 0 && len2 > 0 && *s1 == *s2) { @@ -252,13 +254,13 @@ lev_distance (gchar *s1, gint len1, gchar *s2, gint len2) } /* Calculate fuzzy hash for specified string */ -fuzzy_hash_t * +fuzzy_hash_t * fuzzy_init (f_str_t * in, rspamd_mempool_t * pool) { - fuzzy_hash_t *new; - guint i, repeats = 0; - gchar *c = in->begin, last = '\0'; - gsize real_len = 0; + fuzzy_hash_t *new; + guint i, repeats = 0; + gchar *c = in->begin, last = '\0'; + gsize real_len = 0; new = rspamd_mempool_alloc0 (pool, sizeof (fuzzy_hash_t)); bzero (&rs, sizeof (rs)); @@ -270,7 +272,7 @@ fuzzy_init (f_str_t * in, rspamd_mempool_t * pool) repeats = 0; } if (!g_ascii_isspace (*c) && !g_ascii_ispunct (*c) && repeats < 3) { - real_len ++; + real_len++; } last = *c; c++; @@ -301,10 +303,10 @@ fuzzy_init (f_str_t * in, rspamd_mempool_t * pool) return new; } -fuzzy_hash_t * +fuzzy_hash_t * fuzzy_init_byte_array (GByteArray * in, rspamd_mempool_t * pool) { - f_str_t f; + f_str_t f; f.begin = (gchar *)in->data; f.len = in->len; @@ -313,15 +315,17 @@ fuzzy_init_byte_array (GByteArray * in, rspamd_mempool_t * pool) } void -fuzzy_init_part (struct mime_text_part *part, rspamd_mempool_t *pool, gsize max_diff) +fuzzy_init_part (struct mime_text_part *part, + rspamd_mempool_t *pool, + gsize max_diff) { - fuzzy_hash_t *new, *new2; - gchar *c, *end, *begin; - gsize real_len = 0, len = part->content->len; - GList *cur_offset; - struct process_exception *cur_ex = NULL; - gunichar uc; - gboolean write_diff = FALSE; + fuzzy_hash_t *new, *new2; + gchar *c, *end, *begin; + gsize real_len = 0, len = part->content->len; + GList *cur_offset; + struct process_exception *cur_ex = NULL; + gunichar uc; + gboolean write_diff = FALSE; cur_offset = part->urls_offset; if (cur_offset != NULL) { @@ -347,7 +351,7 @@ fuzzy_init_part (struct mime_text_part *part, rspamd_mempool_t *pool, gsize max_ else { uc = g_utf8_get_char (c); if (g_unichar_isalnum (uc)) { - real_len ++; + real_len++; } c = g_utf8_next_char (c); } @@ -364,7 +368,7 @@ fuzzy_init_part (struct mime_text_part *part, rspamd_mempool_t *pool, gsize max_ } else { if (!g_ascii_isspace (*c) && !g_ascii_ispunct (*c)) { - real_len ++; + real_len++; } c++; } @@ -450,7 +454,7 @@ fuzzy_init_part (struct mime_text_part *part, rspamd_mempool_t *pool, gsize max_ gint fuzzy_compare_hashes (fuzzy_hash_t * h1, fuzzy_hash_t * h2) { - gint res, l1, l2; + gint res, l1, l2; /* If we have hashes of different size, input strings are too different */ if (h1->block_size != h2->block_size) { @@ -493,6 +497,6 @@ fuzzy_compare_parts (struct mime_text_part *p1, struct mime_text_part *p2) return 0; } -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/libutil/fuzzy.h b/src/libutil/fuzzy.h index c226c5765..22a7cbfe6 100644 --- a/src/libutil/fuzzy.h +++ b/src/libutil/fuzzy.h @@ -13,11 +13,11 @@ #define FUZZY_HASHLEN 64 typedef struct fuzzy_hash_s { - gchar hash_pipe[FUZZY_HASHLEN]; /**< result hash */ - guint32 block_size; /**< current blocksize */ - guint32 rh; /**< roll hash value */ - guint32 h; /**< hash of block */ - guint32 hi; /**< current index in hash pipe */ + gchar hash_pipe[FUZZY_HASHLEN]; /**< result hash */ + guint32 block_size; /**< current blocksize */ + guint32 rh; /**< roll hash value */ + guint32 h; /**< hash of block */ + guint32 hi; /**< current index in hash pipe */ } fuzzy_hash_t; struct mime_text_part; @@ -44,13 +44,15 @@ fuzzy_hash_t * fuzzy_init_byte_array (GByteArray *in, rspamd_mempool_t *pool); * @param max_diff maximum text length to use diff algorithm in comparasions * @return fuzzy_hash object allocated in pool */ -void fuzzy_init_part (struct mime_text_part *part, rspamd_mempool_t *pool, gsize max_diff); +void fuzzy_init_part (struct mime_text_part *part, + rspamd_mempool_t *pool, + gsize max_diff); /** - * Compare score of difference between two hashes + * Compare score of difference between two hashes * @param h1 first hash * @param h2 second hash - * @return result in percents 0 - different hashes, 100 - identical hashes + * @return result in percents 0 - different hashes, 100 - identical hashes */ gint fuzzy_compare_hashes (fuzzy_hash_t *h1, fuzzy_hash_t *h2); diff --git a/src/libutil/hash.c b/src/libutil/hash.c index 3bb381651..0e8b1646e 100644 --- a/src/libutil/hash.c +++ b/src/libutil/hash.c @@ -33,11 +33,13 @@ * will use this function internally. */ static inline struct rspamd_hash_node ** -rspamd_hash_lookup_node (rspamd_hash_t * hash, gconstpointer key, guint * hash_return) +rspamd_hash_lookup_node (rspamd_hash_t * hash, + gconstpointer key, + guint * hash_return) { - struct rspamd_hash_node **node_ptr, *node; - guint hash_value; - hash_value = (*hash->hash_func) (key); + struct rspamd_hash_node **node_ptr, *node; + guint hash_value; + hash_value = (*hash->hash_func)(key); if (hash->shared) { rspamd_mempool_rlock_rwlock (hash->lock); @@ -58,7 +60,8 @@ rspamd_hash_lookup_node (rspamd_hash_t * hash, gconstpointer key, guint * hash_r */ if (hash->key_equal_func) { while ((node = *node_ptr)) { - if (node->key_hash == hash_value && hash->key_equal_func (node->key, key)) { + if (node->key_hash == hash_value && + hash->key_equal_func (node->key, key)) { break; } node_ptr = &(*node_ptr)->next; @@ -83,9 +86,10 @@ rspamd_hash_lookup_node (rspamd_hash_t * hash, gconstpointer key, guint * hash_r * No table resize is performed. */ static void -rspamd_hash_remove_node (rspamd_hash_t * hash, struct rspamd_hash_node ***node_ptr_ptr) +rspamd_hash_remove_node (rspamd_hash_t * hash, + struct rspamd_hash_node ***node_ptr_ptr) { - struct rspamd_hash_node **node_ptr, *node; + struct rspamd_hash_node **node_ptr, *node; if (hash->shared) { rspamd_mempool_wlock_rwlock (hash->lock); @@ -108,19 +112,23 @@ rspamd_hash_remove_node (rspamd_hash_t * hash, struct rspamd_hash_node ***node_p static void rspamd_hash_resize (rspamd_hash_t * hash) { - struct rspamd_hash_node **new_nodes; - struct rspamd_hash_node *node, *next; - guint hash_val; - gint new_size, i; + struct rspamd_hash_node **new_nodes; + struct rspamd_hash_node *node, *next; + guint hash_val; + gint new_size, i; new_size = g_spaced_primes_closest (hash->nnodes); new_size = CLAMP (new_size, HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE); if (hash->shared) { - new_nodes = rspamd_mempool_alloc_shared (hash->pool, sizeof (struct rspamd_hash_node *) * new_size); + new_nodes = + rspamd_mempool_alloc_shared (hash->pool, + sizeof (struct rspamd_hash_node *) * new_size); } else { - new_nodes = rspamd_mempool_alloc (hash->pool, sizeof (struct rspamd_hash_node *) * new_size); + new_nodes = + rspamd_mempool_alloc (hash->pool, + sizeof (struct rspamd_hash_node *) * new_size); } if (hash->shared) { @@ -150,46 +158,56 @@ rspamd_hash_resize (rspamd_hash_t * hash) static inline void rspamd_hash_maybe_resize (rspamd_hash_t * hash) { - gint nnodes = hash->nnodes; - gint size = hash->size; + gint nnodes = hash->nnodes; + gint size = hash->size; - if ((size >= 3 * nnodes && size > HASH_TABLE_MIN_SIZE) || (3 * size <= nnodes && size < HASH_TABLE_MAX_SIZE)) { + if ((size >= 3 * nnodes && + size > HASH_TABLE_MIN_SIZE) || + (3 * size <= nnodes && size < HASH_TABLE_MAX_SIZE)) { rspamd_hash_resize (hash); } } /* Create new hash in specified pool */ -rspamd_hash_t * -rspamd_hash_new (rspamd_mempool_t * pool, GHashFunc hash_func, GEqualFunc key_equal_func) +rspamd_hash_t * +rspamd_hash_new (rspamd_mempool_t * pool, + GHashFunc hash_func, + GEqualFunc key_equal_func) { - rspamd_hash_t *hash; + rspamd_hash_t *hash; hash = rspamd_mempool_alloc (pool, sizeof (rspamd_hash_t)); hash->size = HASH_TABLE_MIN_SIZE; hash->nnodes = 0; hash->hash_func = hash_func ? hash_func : g_direct_hash; hash->key_equal_func = key_equal_func; - hash->nodes = rspamd_mempool_alloc0 (pool, sizeof (struct rspamd_hash_node *) * hash->size); + hash->nodes = rspamd_mempool_alloc0 (pool, + sizeof (struct rspamd_hash_node *) * hash->size); hash->shared = 0; hash->pool = pool; return hash; } -/* - * Create new hash in specified pool using shared memory +/* + * Create new hash in specified pool using shared memory */ -rspamd_hash_t * -rspamd_hash_new_shared (rspamd_mempool_t * pool, GHashFunc hash_func, GEqualFunc key_equal_func, gint size) +rspamd_hash_t * +rspamd_hash_new_shared (rspamd_mempool_t * pool, + GHashFunc hash_func, + GEqualFunc key_equal_func, + gint size) { - rspamd_hash_t *hash; + rspamd_hash_t *hash; hash = rspamd_mempool_alloc_shared (pool, sizeof (rspamd_hash_t)); hash->size = size; hash->nnodes = 0; hash->hash_func = hash_func ? hash_func : g_direct_hash; hash->key_equal_func = key_equal_func; - hash->nodes = rspamd_mempool_alloc0_shared (pool, sizeof (struct rspamd_hash_node *) * hash->size); + hash->nodes = + rspamd_mempool_alloc0_shared (pool, + sizeof (struct rspamd_hash_node *) * hash->size); hash->shared = 1; /* Get mutex from pool for locking on insert/remove operations */ hash->lock = rspamd_mempool_get_rwlock (pool); @@ -198,14 +216,14 @@ rspamd_hash_new_shared (rspamd_mempool_t * pool, GHashFunc hash_func, GEqualFunc return hash; } -/* - * Insert item in hash +/* + * Insert item in hash */ void rspamd_hash_insert (rspamd_hash_t * hash, gpointer key, gpointer value) { - struct rspamd_hash_node **node_ptr, *node; - guint key_hash; + struct rspamd_hash_node **node_ptr, *node; + guint key_hash; g_return_if_fail (hash != NULL); node_ptr = rspamd_hash_lookup_node (hash, key, &key_hash); @@ -219,10 +237,14 @@ rspamd_hash_insert (rspamd_hash_t * hash, gpointer key, gpointer value) } else { if (hash->shared) { - node = rspamd_mempool_alloc_shared (hash->pool, sizeof (struct rspamd_hash_node)); + node = + rspamd_mempool_alloc_shared (hash->pool, + sizeof (struct rspamd_hash_node)); } else { - node = rspamd_mempool_alloc (hash->pool, sizeof (struct rspamd_hash_node)); + node = + rspamd_mempool_alloc (hash->pool, + sizeof (struct rspamd_hash_node)); } node->key = key; @@ -242,13 +264,13 @@ rspamd_hash_insert (rspamd_hash_t * hash, gpointer key, gpointer value) } } -/* - * Remove item from hash +/* + * Remove item from hash */ gboolean rspamd_hash_remove (rspamd_hash_t * hash, gpointer key) { - struct rspamd_hash_node **node_ptr; + struct rspamd_hash_node **node_ptr; g_return_val_if_fail (hash != NULL, FALSE); @@ -262,13 +284,13 @@ rspamd_hash_remove (rspamd_hash_t * hash, gpointer key) return TRUE; } -/* - * Lookup item from hash +/* + * Lookup item from hash */ gpointer rspamd_hash_lookup (rspamd_hash_t * hash, gpointer key) { - struct rspamd_hash_node *node; + struct rspamd_hash_node *node; g_return_val_if_fail (hash != NULL, NULL); node = *rspamd_hash_lookup_node (hash, key, NULL); @@ -276,14 +298,14 @@ rspamd_hash_lookup (rspamd_hash_t * hash, gpointer key) return node ? node->value : NULL; } -/* - * Iterate throught hash +/* + * Iterate throught hash */ void rspamd_hash_foreach (rspamd_hash_t * hash, GHFunc func, gpointer user_data) { - struct rspamd_hash_node *node; - gint i; + struct rspamd_hash_node *node; + gint i; g_return_if_fail (hash != NULL); g_return_if_fail (func != NULL); @@ -293,7 +315,7 @@ rspamd_hash_foreach (rspamd_hash_t * hash, GHFunc func, gpointer user_data) } for (i = 0; i < hash->size; i++) { for (node = hash->nodes[i]; node; node = node->next) { - (*func) (node->key, node->value, user_data); + (*func)(node->key, node->value, user_data); } } if (hash->shared) { @@ -308,7 +330,7 @@ rspamd_hash_foreach (rspamd_hash_t * hash, GHFunc func, gpointer user_data) static void rspamd_lru_hash_destroy_node (gpointer v) { - rspamd_lru_element_t *node = v; + rspamd_lru_element_t *node = v; if (node->hash->value_destroy) { node->hash->value_destroy (node->data); @@ -317,10 +339,14 @@ rspamd_lru_hash_destroy_node (gpointer v) g_slice_free1 (sizeof (rspamd_lru_element_t), node); } -static rspamd_lru_element_t* -rspamd_lru_create_node (rspamd_lru_hash_t *hash, gpointer key, gpointer value, time_t now, guint ttl) +static rspamd_lru_element_t * +rspamd_lru_create_node (rspamd_lru_hash_t *hash, + gpointer key, + gpointer value, + time_t now, + guint ttl) { - rspamd_lru_element_t *node; + rspamd_lru_element_t *node; node = g_slice_alloc (sizeof (rspamd_lru_element_t)); node->data = value; @@ -340,14 +366,21 @@ rspamd_lru_create_node (rspamd_lru_hash_t *hash, gpointer key, gpointer value, t * @param key_equal_func pointer to function for comparing keys * @return new rspamd_hash object */ -rspamd_lru_hash_t* -rspamd_lru_hash_new (GHashFunc hash_func, GEqualFunc key_equal_func, gint maxsize, gint maxage, - GDestroyNotify key_destroy, GDestroyNotify value_destroy) +rspamd_lru_hash_t * +rspamd_lru_hash_new (GHashFunc hash_func, + GEqualFunc key_equal_func, + gint maxsize, + gint maxage, + GDestroyNotify key_destroy, + GDestroyNotify value_destroy) { - rspamd_lru_hash_t *new; + rspamd_lru_hash_t *new; new = g_malloc (sizeof (rspamd_lru_hash_t)); - new->storage = g_hash_table_new_full (hash_func, key_equal_func, key_destroy, rspamd_lru_hash_destroy_node); + new->storage = g_hash_table_new_full (hash_func, + key_equal_func, + key_destroy, + rspamd_lru_hash_destroy_node); new->maxage = maxage; new->maxsize = maxsize; new->value_destroy = value_destroy; @@ -368,13 +401,19 @@ rspamd_lru_hash_new (GHashFunc hash_func, GEqualFunc key_equal_func, gint maxsiz * @param key_equal_func pointer to function for comparing keys * @return new rspamd_hash object */ -rspamd_lru_hash_t* -rspamd_lru_hash_new_full (GHashFunc hash_func, GEqualFunc key_equal_func, - gint maxsize, gint maxage, GDestroyNotify key_destroy, GDestroyNotify value_destroy, - gpointer storage, lru_cache_insert_func insert_func, lru_cache_lookup_func lookup_func, - lru_cache_delete_func delete_func) +rspamd_lru_hash_t * +rspamd_lru_hash_new_full (GHashFunc hash_func, + GEqualFunc key_equal_func, + gint maxsize, + gint maxage, + GDestroyNotify key_destroy, + GDestroyNotify value_destroy, + gpointer storage, + lru_cache_insert_func insert_func, + lru_cache_lookup_func lookup_func, + lru_cache_delete_func delete_func) { - rspamd_lru_hash_t *new; + rspamd_lru_hash_t *new; new = g_malloc (sizeof (rspamd_lru_hash_t)); new->storage = storage; @@ -400,7 +439,7 @@ rspamd_lru_hash_new_full (GHashFunc hash_func, GEqualFunc key_equal_func, gpointer rspamd_lru_hash_lookup (rspamd_lru_hash_t *hash, gpointer key, time_t now) { - rspamd_lru_element_t *res; + rspamd_lru_element_t *res; if ((res = hash->lookup_func (hash->storage, key)) != NULL) { if (res->ttl != 0) { @@ -434,17 +473,17 @@ rspamd_lru_hash_lookup (rspamd_lru_hash_t *hash, gpointer key, time_t now) */ void rspamd_lru_hash_insert (rspamd_lru_hash_t *hash, gpointer key, gpointer value, - time_t now, guint ttl) + time_t now, guint ttl) { - rspamd_lru_element_t *res; - gint removed = 0; + rspamd_lru_element_t *res; + gint removed = 0; if ((res = hash->lookup_func (hash->storage, key)) != NULL) { hash->delete_func (hash->storage, res->key); } else { if (hash->maxsize > 0 && - (gint)g_queue_get_length (hash->q) >= hash->maxsize) { + (gint)g_queue_get_length (hash->q) >= hash->maxsize) { /* Expire some elements */ res = g_queue_peek_tail (hash->q); if (hash->maxage > 0) { @@ -456,7 +495,7 @@ rspamd_lru_hash_insert (rspamd_lru_hash_t *hash, gpointer key, gpointer value, break; } res = g_queue_peek_tail (hash->q); - removed ++; + removed++; } } if (removed == 0) { diff --git a/src/libutil/hash.h b/src/libutil/hash.h index c5d4639af..7f4f82b43 100644 --- a/src/libutil/hash.h +++ b/src/libutil/hash.h @@ -10,49 +10,50 @@ #include "mem_pool.h" struct rspamd_hash_node { - gpointer key; - gpointer value; - guint key_hash; + gpointer key; + gpointer value; + guint key_hash; struct rspamd_hash_node *next; }; typedef struct rspamd_hash_s { - gint size; - gint nnodes; + gint size; + gint nnodes; struct rspamd_hash_node **nodes; - GHashFunc hash_func; - GEqualFunc key_equal_func; - gint shared; - rspamd_mempool_rwlock_t *lock; - rspamd_mempool_t *pool; + GHashFunc hash_func; + GEqualFunc key_equal_func; + gint shared; + rspamd_mempool_rwlock_t *lock; + rspamd_mempool_t *pool; } rspamd_hash_t; -typedef void (*lru_cache_insert_func)(gpointer storage, gpointer key, gpointer value); +typedef void (*lru_cache_insert_func)(gpointer storage, gpointer key, + gpointer value); typedef gpointer (*lru_cache_lookup_func)(gpointer storage, gpointer key); typedef gboolean (*lru_cache_delete_func)(gpointer storage, gpointer key); typedef void (*lru_cache_destroy_func)(gpointer storage); typedef struct rspamd_lru_hash_s { - gint maxsize; - gint maxage; - GDestroyNotify value_destroy; - GDestroyNotify key_destroy; - GQueue *q; - gpointer storage; - lru_cache_insert_func insert_func; - lru_cache_lookup_func lookup_func; - lru_cache_delete_func delete_func; - lru_cache_destroy_func destroy_func; + gint maxsize; + gint maxage; + GDestroyNotify value_destroy; + GDestroyNotify key_destroy; + GQueue *q; + gpointer storage; + lru_cache_insert_func insert_func; + lru_cache_lookup_func lookup_func; + lru_cache_delete_func delete_func; + lru_cache_destroy_func destroy_func; } rspamd_lru_hash_t; typedef struct rspamd_lru_element_s { - gpointer data; - gpointer key; - time_t store_time; - guint ttl; - rspamd_lru_hash_t *hash; - GList *link; + gpointer data; + gpointer key; + time_t store_time; + guint ttl; + rspamd_lru_hash_t *hash; + GList *link; } rspamd_lru_element_t; @@ -65,7 +66,9 @@ typedef struct rspamd_lru_element_s { * @param key_equal_func pointer to function for comparing keys * @return new rspamd_hash object */ -rspamd_hash_t* rspamd_hash_new (rspamd_mempool_t *pool, GHashFunc hash_func, GEqualFunc key_equal_func); +rspamd_hash_t * rspamd_hash_new (rspamd_mempool_t *pool, + GHashFunc hash_func, + GEqualFunc key_equal_func); /** * Create new hash in specified pool using shared memory @@ -74,7 +77,10 @@ rspamd_hash_t* rspamd_hash_new (rspamd_mempool_t *pool, GHashFunc hash_func, GEq * @param key_equal_func pointer to function for comparing keys * @return new rspamd_hash object */ -rspamd_hash_t* rspamd_hash_new_shared (rspamd_mempool_t *pool, GHashFunc hash_func, GEqualFunc key_equal_func, gint size); +rspamd_hash_t * rspamd_hash_new_shared (rspamd_mempool_t *pool, + GHashFunc hash_func, + GEqualFunc key_equal_func, + gint size); /** * Insert item in hash @@ -99,7 +105,7 @@ gboolean rspamd_hash_remove (rspamd_hash_t *hash, gpointer key); */ gpointer rspamd_hash_lookup (rspamd_hash_t *hash, gpointer key); -/** +/** * Iterate throught hash * @param hash hash object * @param func user's function that would be called for each key/value pair @@ -115,8 +121,12 @@ void rspamd_hash_foreach (rspamd_hash_t *hash, GHFunc func, gpointer user_data); * @param key_equal_func pointer to function for comparing keys * @return new rspamd_hash object */ -rspamd_lru_hash_t* rspamd_lru_hash_new (GHashFunc hash_func, GEqualFunc key_equal_func, - gint maxsize, gint maxage, GDestroyNotify key_destroy, GDestroyNotify value_destroy); +rspamd_lru_hash_t * rspamd_lru_hash_new (GHashFunc hash_func, + GEqualFunc key_equal_func, + gint maxsize, + gint maxage, + GDestroyNotify key_destroy, + GDestroyNotify value_destroy); /** * Create new lru hash with custom storage @@ -126,25 +136,36 @@ rspamd_lru_hash_t* rspamd_lru_hash_new (GHashFunc hash_func, GEqualFunc key_equa * @param key_equal_func pointer to function for comparing keys * @return new rspamd_hash object */ -rspamd_lru_hash_t* rspamd_lru_hash_new_full (GHashFunc hash_func, GEqualFunc key_equal_func, - gint maxsize, gint maxage, GDestroyNotify key_destroy, GDestroyNotify value_destroy, - gpointer storage, lru_cache_insert_func insert_func, lru_cache_lookup_func lookup_func, - lru_cache_delete_func delete_func); +rspamd_lru_hash_t * rspamd_lru_hash_new_full (GHashFunc hash_func, + GEqualFunc key_equal_func, + gint maxsize, + gint maxage, + GDestroyNotify key_destroy, + GDestroyNotify value_destroy, + gpointer storage, + lru_cache_insert_func insert_func, + lru_cache_lookup_func lookup_func, + lru_cache_delete_func delete_func); /** * Lookup item from hash * @param hash hash object * @param key key to find * @return value of key or NULL if key is not found */ -gpointer rspamd_lru_hash_lookup (rspamd_lru_hash_t *hash, gpointer key, time_t now); +gpointer rspamd_lru_hash_lookup (rspamd_lru_hash_t *hash, + gpointer key, + time_t now); /** * Insert item in hash * @param hash hash object * @param key key to insert * @param value value of key */ -void rspamd_lru_hash_insert (rspamd_lru_hash_t *hash, gpointer key, gpointer value, - time_t now, guint ttl); +void rspamd_lru_hash_insert (rspamd_lru_hash_t *hash, + gpointer key, + gpointer value, + time_t now, + guint ttl); /** * Remove lru hash diff --git a/src/libutil/http.c b/src/libutil/http.c index 420dd165c..3cfc433e1 100644 --- a/src/libutil/http.c +++ b/src/libutil/http.c @@ -65,9 +65,9 @@ static const struct _rspamd_http_magic { [HTTP_MAGIC_JPG] = { "jpg", "image/jpeg" }, }; -static gchar *http_week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; -static gchar *http_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +static gchar *http_week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; +static gchar *http_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; #define HTTP_ERROR http_error_quark () @@ -228,13 +228,13 @@ rspamd_http_parse_date (const gchar *header, gsize len) if (fmt == rfc822) { if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9' - || *(p + 2) < '0' || *(p + 2) > '9' || *(p + 3) < '0' - || *(p + 3) > '9') { + || *(p + 2) < '0' || *(p + 2) > '9' || *(p + 3) < '0' + || *(p + 3) > '9') { return (time_t)-1; } year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100 - + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; + + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; p += 4; } @@ -312,13 +312,13 @@ rspamd_http_parse_date (const gchar *header, gsize len) } if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9' - || *(p + 2) < '0' || *(p + 2) > '9' || *(p + 3) < '0' - || *(p + 3) > '9') { + || *(p + 2) < '0' || *(p + 2) > '9' || *(p + 3) < '0' + || *(p + 3) > '9') { return (time_t)-1; } year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100 - + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; + + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; } if (hour > 23 || min > 59 || sec > 59) { @@ -348,24 +348,24 @@ rspamd_http_parse_date (const gchar *header, gsize len) /* Gauss' formula for Gregorian days since March 1, 1 BC */ time = (guint64) ( - /* days in years including leap years since March 1, 1 BC */ + /* days in years including leap years since March 1, 1 BC */ - 365 * year + year / 4 - year / 100 + year / 400 + 365 * year + year / 4 - year / 100 + year / 400 - /* days before the month */ + /* days before the month */ - + 367 * month / 12 - 30 + + 367 * month / 12 - 30 - /* days before the day */ + /* days before the day */ - + day - 1 + + day - 1 - /* - * 719527 days were between March 1, 1 BC and March 1, 1970, - * 31 and 28 days were in January and February 1970 - */ + /* + * 719527 days were between March 1, 1 BC and March 1, 1970, + * 31 and 28 days were in January and February 1970 + */ - - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec; + - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec; return (time_t) time; } @@ -380,9 +380,10 @@ rspamd_http_check_date (struct rspamd_http_connection_private *priv) } static gint -rspamd_http_on_url (http_parser* parser, const gchar *at, size_t length) +rspamd_http_on_url (http_parser * parser, const gchar *at, size_t length) { - struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection *conn = + (struct rspamd_http_connection *)parser->data; struct rspamd_http_connection_private *priv; priv = conn->priv; @@ -393,9 +394,10 @@ rspamd_http_on_url (http_parser* parser, const gchar *at, size_t length) } static gint -rspamd_http_on_status (http_parser* parser, const gchar *at, size_t length) +rspamd_http_on_status (http_parser * parser, const gchar *at, size_t length) { - struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection *conn = + (struct rspamd_http_connection *)parser->data; struct rspamd_http_connection_private *priv; priv = conn->priv; @@ -411,9 +413,12 @@ rspamd_http_on_status (http_parser* parser, const gchar *at, size_t length) } static gint -rspamd_http_on_header_field (http_parser* parser, const gchar *at, size_t length) +rspamd_http_on_header_field (http_parser * parser, + const gchar *at, + size_t length) { - struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection *conn = + (struct rspamd_http_connection *)parser->data; struct rspamd_http_connection_private *priv; priv = conn->priv; @@ -438,9 +443,12 @@ rspamd_http_on_header_field (http_parser* parser, const gchar *at, size_t length } static gint -rspamd_http_on_header_value (http_parser* parser, const gchar *at, size_t length) +rspamd_http_on_header_value (http_parser * parser, + const gchar *at, + size_t length) { - struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection *conn = + (struct rspamd_http_connection *)parser->data; struct rspamd_http_connection_private *priv; priv = conn->priv; @@ -457,9 +465,10 @@ rspamd_http_on_header_value (http_parser* parser, const gchar *at, size_t length } static int -rspamd_http_on_headers_complete (http_parser* parser) +rspamd_http_on_headers_complete (http_parser * parser) { - struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection *conn = + (struct rspamd_http_connection *)parser->data; struct rspamd_http_connection_private *priv; priv = conn->priv; @@ -484,9 +493,10 @@ rspamd_http_on_headers_complete (http_parser* parser) } static int -rspamd_http_on_body (http_parser* parser, const gchar *at, size_t length) +rspamd_http_on_body (http_parser * parser, const gchar *at, size_t length) { - struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection *conn = + (struct rspamd_http_connection *)parser->data; struct rspamd_http_connection_private *priv; priv = conn->priv; @@ -501,9 +511,10 @@ rspamd_http_on_body (http_parser* parser, const gchar *at, size_t length) } static int -rspamd_http_on_message_complete (http_parser* parser) +rspamd_http_on_message_complete (http_parser * parser) { - struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection *conn = + (struct rspamd_http_connection *)parser->data; struct rspamd_http_connection_private *priv; int ret = 0; @@ -515,7 +526,10 @@ rspamd_http_on_message_complete (http_parser* parser) ret = conn->body_handler (conn, priv->msg, NULL, 0); } else { - ret = conn->body_handler (conn, priv->msg, priv->msg->body->str, priv->msg->body->len); + ret = conn->body_handler (conn, + priv->msg, + priv->msg->body->str, + priv->msg->body->len); } rspamd_http_connection_unref (conn); } @@ -557,13 +571,13 @@ rspamd_http_write_helper (struct rspamd_http_connection *conn) start = &priv->out[0]; niov = priv->outlen; remain = priv->wr_pos; - for (i = 0; i < priv->outlen && remain > 0; i ++) { + for (i = 0; i < priv->outlen && remain > 0; i++) { /* Find out the first iov required */ start = &priv->out[i]; if (start->iov_len <= remain) { remain -= start->iov_len; start = &priv->out[i + 1]; - niov --; + niov--; } else { start->iov_base = (void *)((char *)start->iov_base + remain); @@ -575,7 +589,9 @@ rspamd_http_write_helper (struct rspamd_http_connection *conn) r = writev (conn->fd, start, MIN (IOV_MAX, niov)); if (r == -1) { - err = g_error_new (HTTP_ERROR, errno, "IO write error: %s", strerror (errno)); + err = + g_error_new (HTTP_ERROR, errno, "IO write error: %s", strerror ( + errno)); rspamd_http_connection_ref (conn); conn->error_handler (conn, err); rspamd_http_connection_unref (conn); @@ -613,7 +629,10 @@ rspamd_http_event_handler (int fd, short what, gpointer ud) if (what == EV_READ) { r = read (fd, buf->str, buf->allocated_len); if (r == -1) { - err = g_error_new (HTTP_ERROR, errno, "IO read error: %s", strerror (errno)); + err = g_error_new (HTTP_ERROR, + errno, + "IO read error: %s", + strerror (errno)); conn->error_handler (conn, err); g_error_free (err); return; @@ -624,7 +643,9 @@ rspamd_http_event_handler (int fd, short what, gpointer ud) return; } else { - err = g_error_new (HTTP_ERROR, errno, "IO read error: unexpected EOF"); + err = g_error_new (HTTP_ERROR, + errno, + "IO read error: unexpected EOF"); conn->error_handler (conn, err); g_error_free (err); return; @@ -633,9 +654,11 @@ rspamd_http_event_handler (int fd, short what, gpointer ud) else { buf->len = r; rspamd_http_connection_ref (conn); - if (http_parser_execute (&priv->parser, &priv->parser_cb, buf->str, r) != (size_t)r) { + if (http_parser_execute (&priv->parser, &priv->parser_cb, buf->str, + r) != (size_t)r) { err = g_error_new (HTTP_ERROR, priv->parser.http_errno, - "HTTP parser error: %s", http_errno_description (priv->parser.http_errno)); + "HTTP parser error: %s", + http_errno_description (priv->parser.http_errno)); conn->error_handler (conn, err); g_error_free (err); rspamd_http_connection_unref (conn); @@ -658,12 +681,12 @@ rspamd_http_event_handler (int fd, short what, gpointer ud) } } -struct rspamd_http_connection* +struct rspamd_http_connection * rspamd_http_connection_new (rspamd_http_body_handler_t body_handler, - rspamd_http_error_handler_t error_handler, - rspamd_http_finish_handler_t finish_handler, - enum rspamd_http_options opts, - enum rspamd_http_connection_type type) + rspamd_http_error_handler_t error_handler, + rspamd_http_finish_handler_t finish_handler, + enum rspamd_http_options opts, + enum rspamd_http_connection_type type) { struct rspamd_http_connection *new; struct rspamd_http_connection_private *priv; @@ -684,7 +707,8 @@ rspamd_http_connection_new (rspamd_http_body_handler_t body_handler, /* Init priv */ priv = g_slice_alloc0 (sizeof (struct rspamd_http_connection_private)); - http_parser_init (&priv->parser, type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE); + http_parser_init (&priv->parser, + type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE); priv->parser.data = new; priv->parser_cb.on_url = rspamd_http_on_url; priv->parser_cb.on_status = rspamd_http_on_status; @@ -734,19 +758,20 @@ rspamd_http_connection_free (struct rspamd_http_connection *conn) priv = conn->priv; rspamd_http_connection_reset (conn); g_slice_free1 (sizeof (struct rspamd_http_connection_private), priv); - g_slice_free1 (sizeof (struct rspamd_http_connection), conn); + g_slice_free1 (sizeof (struct rspamd_http_connection), conn); } void rspamd_http_connection_read_message (struct rspamd_http_connection *conn, - gpointer ud, gint fd, struct timeval *timeout, struct event_base *base) + gpointer ud, gint fd, struct timeval *timeout, struct event_base *base) { struct rspamd_http_connection_private *priv = conn->priv; struct rspamd_http_message *req; conn->fd = fd; conn->ud = ud; - req = rspamd_http_new_message (conn->type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE); + req = rspamd_http_new_message ( + conn->type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE); priv->msg = req; if (timeout == NULL) { @@ -760,15 +785,19 @@ rspamd_http_connection_read_message (struct rspamd_http_connection *conn, priv->buf = g_string_sized_new (BUFSIZ); priv->new_header = TRUE; - event_set (&priv->ev, fd, EV_READ | EV_PERSIST, rspamd_http_event_handler, conn); + event_set (&priv->ev, + fd, + EV_READ | EV_PERSIST, + rspamd_http_event_handler, + conn); event_base_set (base, &priv->ev); event_add (&priv->ev, priv->ptv); } void rspamd_http_connection_write_message (struct rspamd_http_connection *conn, - struct rspamd_http_message *msg, const gchar *host, const gchar *mime_type, - gpointer ud, gint fd, struct timeval *timeout, struct event_base *base) + struct rspamd_http_message *msg, const gchar *host, const gchar *mime_type, + gpointer ud, gint fd, struct timeval *timeout, struct event_base *base) { struct rspamd_http_connection_private *priv = conn->priv; struct rspamd_http_header *hdr; @@ -820,29 +849,32 @@ rspamd_http_connection_write_message (struct rspamd_http_connection *conn, if (msg->method < HTTP_SYMBOLS) { ptm = gmtime (&msg->date); t = *ptm; - rspamd_snprintf (datebuf, sizeof (datebuf), "%s, %02d %s %4d %02d:%02d:%02d GMT", - http_week[t.tm_wday], - t.tm_mday, - http_month[t.tm_mon], - t.tm_year + 1900, - t.tm_hour, - t.tm_min, - t.tm_sec); + rspamd_snprintf (datebuf, + sizeof (datebuf), + "%s, %02d %s %4d %02d:%02d:%02d GMT", + http_week[t.tm_wday], + t.tm_mday, + http_month[t.tm_mon], + t.tm_year + 1900, + t.tm_hour, + t.tm_min, + t.tm_sec); if (mime_type == NULL) { mime_type = "text/plain"; } rspamd_printf_gstring (priv->buf, "HTTP/1.1 %d %s\r\n" - "Connection: close\r\n" - "Server: %s\r\n" - "Date: %s\r\n" - "Content-Length: %z\r\n" - "Content-Type: %s\r\n", - msg->code, - msg->status ? msg->status->str : rspamd_http_code_to_str (msg->code), - "rspamd/" RVERSION, - datebuf, - bodylen, - mime_type); + "Connection: close\r\n" + "Server: %s\r\n" + "Date: %s\r\n" + "Content-Length: %z\r\n" + "Content-Type: %s\r\n", + msg->code, + msg->status ? msg->status->str : rspamd_http_code_to_str (msg-> + code), + "rspamd/" RVERSION, + datebuf, + bodylen, + mime_type); } else { /* Legacy spamd reply */ @@ -853,21 +885,22 @@ rspamd_http_connection_write_message (struct rspamd_http_connection *conn, /* Format request */ if (host != NULL) { rspamd_printf_gstring (priv->buf, "%s %v HTTP/1.1\r\n" - "Connection: close\r\n" - "Host: %s\r\n" - "Content-Length: %z\r\n", + "Connection: close\r\n" + "Host: %s\r\n" + "Content-Length: %z\r\n", http_method_str (msg->method), msg->url, host, bodylen); } else { /* Fallback to HTTP/1.0 */ rspamd_printf_gstring (priv->buf, "%s %v HTTP/1.0\r\n" - "Content-Length: %z\r\n", + "Content-Length: %z\r\n", http_method_str (msg->method), msg->url, bodylen); } } /* Allocate iov */ priv->wr_total = bodylen + priv->buf->len + 2; - DL_FOREACH (msg->headers, hdr) { + DL_FOREACH (msg->headers, hdr) + { /* <name><: ><value><\r\n> */ priv->wr_total += hdr->name->len + hdr->value->len + 4; priv->outlen += 4; @@ -879,7 +912,8 @@ rspamd_http_connection_write_message (struct rspamd_http_connection *conn, priv->out[0].iov_base = priv->buf->str; priv->out[0].iov_len = priv->buf->len; i = 1; - LL_FOREACH (msg->headers, hdr) { + LL_FOREACH (msg->headers, hdr) + { priv->out[i].iov_base = hdr->name->str; priv->out[i++].iov_len = hdr->name->len; priv->out[i].iov_base = ": "; @@ -907,7 +941,7 @@ rspamd_http_connection_write_message (struct rspamd_http_connection *conn, event_add (&priv->ev, priv->ptv); } -struct rspamd_http_message* +struct rspamd_http_message * rspamd_http_new_message (enum http_parser_type type) { struct rspamd_http_message *new; @@ -935,8 +969,9 @@ rspamd_http_message_free (struct rspamd_http_message *msg) { struct rspamd_http_header *hdr, *tmp_hdr; - LL_FOREACH_SAFE (msg->headers, hdr, tmp_hdr) { - g_string_free (hdr->name, TRUE); + LL_FOREACH_SAFE (msg->headers, hdr, tmp_hdr) + { + g_string_free (hdr->name, TRUE); g_string_free (hdr->value, TRUE); g_slice_free1 (sizeof (struct rspamd_http_header), hdr); } @@ -952,9 +987,10 @@ rspamd_http_message_free (struct rspamd_http_message *msg) g_slice_free1 (sizeof (struct rspamd_http_message), msg); } -void rspamd_http_message_add_header (struct rspamd_http_message *msg, - const gchar *name, - const gchar *value) +void +rspamd_http_message_add_header (struct rspamd_http_message *msg, + const gchar *name, + const gchar *value) { struct rspamd_http_header *hdr; @@ -966,15 +1002,17 @@ void rspamd_http_message_add_header (struct rspamd_http_message *msg, } } -const gchar* -rspamd_http_message_find_header (struct rspamd_http_message *msg, const gchar *name) +const gchar * +rspamd_http_message_find_header (struct rspamd_http_message *msg, + const gchar *name) { struct rspamd_http_header *hdr; const gchar *res = NULL; guint slen = strlen (name); if (msg != NULL) { - LL_FOREACH (msg->headers, hdr) { + LL_FOREACH (msg->headers, hdr) + { if (hdr->name->len == slen) { if (memcmp (hdr->name->str, name, slen) == 0) { res = hdr->value->str; @@ -1005,7 +1043,8 @@ rspamd_http_entry_free (struct rspamd_http_connection_entry *entry) } static void -rspamd_http_router_error_handler (struct rspamd_http_connection *conn, GError *err) +rspamd_http_router_error_handler (struct rspamd_http_connection *conn, + GError *err) { struct rspamd_http_connection_entry *entry = conn->ud; struct rspamd_http_message *msg; @@ -1027,8 +1066,14 @@ rspamd_http_router_error_handler (struct rspamd_http_connection *conn, GError *e msg->code = err->code; msg->body = g_string_new (err->message); rspamd_http_connection_reset (entry->conn); - rspamd_http_connection_write_message (entry->conn, msg, NULL, - "text/plain", entry, entry->conn->fd, entry->rt->ptv, entry->rt->ev_base); + rspamd_http_connection_write_message (entry->conn, + msg, + NULL, + "text/plain", + entry, + entry->conn->fd, + entry->rt->ptv, + entry->rt->ev_base); entry->is_reply = TRUE; } } @@ -1043,9 +1088,9 @@ rspamd_http_router_detect_ct (const gchar *path) if (dot == NULL) { return http_file_types[HTTP_MAGIC_PLAIN].ct; } - dot ++; + dot++; - for (i = 0; i < G_N_ELEMENTS (http_file_types); i ++) { + for (i = 0; i < G_N_ELEMENTS (http_file_types); i++) { if (strcmp (http_file_types[i].ext, dot) == 0) { return http_file_types[i].ct; } @@ -1065,11 +1110,11 @@ rspamd_http_router_is_subdir (const gchar *parent, const gchar *sub) if (*sub != *parent) { return FALSE; } - parent ++; - sub ++; + parent++; + sub++; } - parent --; + parent--; if (*parent == G_DIR_SEPARATOR) { return TRUE; } @@ -1079,7 +1124,7 @@ rspamd_http_router_is_subdir (const gchar *parent, const gchar *sub) static gboolean rspamd_http_router_try_file (struct rspamd_http_connection_entry *entry, - struct rspamd_http_message *msg, gboolean expand_path) + struct rspamd_http_message *msg, gboolean expand_path) { struct stat st; gint fd; @@ -1087,17 +1132,17 @@ rspamd_http_router_try_file (struct rspamd_http_connection_entry *entry, struct rspamd_http_message *reply_msg; rspamd_snprintf (filebuf, sizeof (filebuf), "%s%c%v", - entry->rt->default_fs_path, G_DIR_SEPARATOR, msg->url); + entry->rt->default_fs_path, G_DIR_SEPARATOR, msg->url); if (realpath (filebuf, realbuf) == NULL || - lstat (realbuf, &st) == -1) { + lstat (realbuf, &st) == -1) { return FALSE; } if (S_ISDIR (st.st_mode) && expand_path) { /* Try to append 'index.html' to the url */ g_string_append_printf (msg->url, "%c%s", G_DIR_SEPARATOR, - "index.html"); + "index.html"); return rspamd_http_router_try_file (entry, msg, FALSE); } else if (!S_ISREG (st.st_mode)) { @@ -1107,8 +1152,9 @@ rspamd_http_router_try_file (struct rspamd_http_connection_entry *entry, /* We also need to ensure that file is inside the defined dir */ rspamd_strlcpy (filebuf, realbuf, sizeof (filebuf)); dir = dirname (filebuf); - if (dir == NULL || !rspamd_http_router_is_subdir (entry->rt->default_fs_path, - dir)) { + if (dir == NULL || + !rspamd_http_router_is_subdir (entry->rt->default_fs_path, + dir)) { return FALSE; } @@ -1136,15 +1182,15 @@ rspamd_http_router_try_file (struct rspamd_http_connection_entry *entry, /* XXX: detect content type */ rspamd_http_connection_write_message (entry->conn, reply_msg, NULL, - rspamd_http_router_detect_ct (realbuf), entry, entry->conn->fd, - entry->rt->ptv, entry->rt->ev_base); + rspamd_http_router_detect_ct (realbuf), entry, entry->conn->fd, + entry->rt->ptv, entry->rt->ev_base); return TRUE; } static int rspamd_http_router_finish_handler (struct rspamd_http_connection *conn, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { struct rspamd_http_connection_entry *entry = conn->ud; rspamd_http_router_handler_t handler = NULL; @@ -1152,7 +1198,8 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn, struct rspamd_http_message *err_msg; GError *err; - G_STATIC_ASSERT (sizeof (rspamd_http_router_handler_t) == sizeof (gpointer)); + G_STATIC_ASSERT (sizeof (rspamd_http_router_handler_t) == + sizeof (gpointer)); if (entry->is_reply) { /* Request is finished, it is safe to free a connection */ @@ -1170,7 +1217,7 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn, } else { if (entry->rt->default_fs_path == NULL || - !rspamd_http_router_try_file (entry, msg, TRUE)) { + !rspamd_http_router_try_file (entry, msg, TRUE)) { err = g_error_new (HTTP_ERROR, 404, "Not found"); if (entry->rt->error_handler != NULL) { @@ -1181,9 +1228,14 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn, err_msg->code = err->code; err_msg->body = g_string_new (err->message); rspamd_http_connection_reset (entry->conn); - rspamd_http_connection_write_message (entry->conn, err_msg, NULL, - "text/plain", entry, entry->conn->fd, - entry->rt->ptv, entry->rt->ev_base); + rspamd_http_connection_write_message (entry->conn, + err_msg, + NULL, + "text/plain", + entry, + entry->conn->fd, + entry->rt->ptv, + entry->rt->ev_base); g_error_free (err); } } @@ -1192,13 +1244,13 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn, return 0; } -struct rspamd_http_connection_router* +struct rspamd_http_connection_router * rspamd_http_router_new (rspamd_http_router_error_handler_t eh, - rspamd_http_router_finish_handler_t fh, - struct timeval *timeout, struct event_base *base, - const char *default_fs_path) + rspamd_http_router_finish_handler_t fh, + struct timeval *timeout, struct event_base *base, + const char *default_fs_path) { - struct rspamd_http_connection_router* new; + struct rspamd_http_connection_router * new; struct stat st; new = g_slice_alloc (sizeof (struct rspamd_http_connection_router)); @@ -1235,10 +1287,11 @@ rspamd_http_router_new (rspamd_http_router_error_handler_t eh, void rspamd_http_router_add_path (struct rspamd_http_connection_router *router, - const gchar *path, rspamd_http_router_handler_t handler) + const gchar *path, rspamd_http_router_handler_t handler) { gpointer ptr; - G_STATIC_ASSERT (sizeof (rspamd_http_router_handler_t) == sizeof (gpointer)); + G_STATIC_ASSERT (sizeof (rspamd_http_router_handler_t) == + sizeof (gpointer)); if (path != NULL && handler != NULL && router != NULL) { memcpy (&ptr, &handler, sizeof (ptr)); @@ -1248,7 +1301,7 @@ rspamd_http_router_add_path (struct rspamd_http_connection_router *router, void rspamd_http_router_handle_socket (struct rspamd_http_connection_router *router, - gint fd, gpointer ud) + gint fd, gpointer ud) { struct rspamd_http_connection_entry *conn; @@ -1257,11 +1310,14 @@ rspamd_http_router_handle_socket (struct rspamd_http_connection_router *router, conn->ud = ud; conn->is_reply = FALSE; - conn->conn = rspamd_http_connection_new (NULL, rspamd_http_router_error_handler, - rspamd_http_router_finish_handler, 0, RSPAMD_HTTP_SERVER); + conn->conn = rspamd_http_connection_new (NULL, + rspamd_http_router_error_handler, + rspamd_http_router_finish_handler, + 0, + RSPAMD_HTTP_SERVER); rspamd_http_connection_read_message (conn->conn, conn, fd, router->ptv, - router->ev_base); + router->ev_base); LL_PREPEND (router->conns, conn); } @@ -1271,7 +1327,8 @@ rspamd_http_router_free (struct rspamd_http_connection_router *router) struct rspamd_http_connection_entry *conn, *tmp; if (router) { - LL_FOREACH_SAFE (router->conns, conn, tmp) { + LL_FOREACH_SAFE (router->conns, conn, tmp) + { rspamd_http_entry_free (conn); } diff --git a/src/libutil/http.h b/src/libutil/http.h index 695f23896..c6a142e3b 100644 --- a/src/libutil/http.h +++ b/src/libutil/http.h @@ -67,7 +67,7 @@ struct rspamd_http_message { * Options for HTTP connection */ enum rspamd_http_options { - RSPAMD_HTTP_BODY_PARTIAL = 0x1//!< RSPAMD_HTTP_BODY_PARTIAL + RSPAMD_HTTP_BODY_PARTIAL = 0x1 //!< RSPAMD_HTTP_BODY_PARTIAL }; struct rspamd_http_connection_private; @@ -76,20 +76,24 @@ struct rspamd_http_connection_router; struct rspamd_http_connection_entry; typedef int (*rspamd_http_body_handler_t) (struct rspamd_http_connection *conn, - struct rspamd_http_message *msg, - const gchar *chunk, - gsize len); + struct rspamd_http_message *msg, + const gchar *chunk, + gsize len); -typedef void (*rspamd_http_error_handler_t) (struct rspamd_http_connection *conn, GError *err); +typedef void (*rspamd_http_error_handler_t) (struct rspamd_http_connection *conn, + GError *err); typedef int (*rspamd_http_finish_handler_t) (struct rspamd_http_connection *conn, - struct rspamd_http_message *msg); + struct rspamd_http_message *msg); -typedef int (*rspamd_http_router_handler_t) (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg); -typedef void (*rspamd_http_router_error_handler_t) (struct rspamd_http_connection_entry *conn_ent, - GError *err); -typedef void (*rspamd_http_router_finish_handler_t) (struct rspamd_http_connection_entry *conn_ent); +typedef int (*rspamd_http_router_handler_t) (struct rspamd_http_connection_entry + *conn_ent, + struct rspamd_http_message *msg); +typedef void (*rspamd_http_router_error_handler_t) (struct + rspamd_http_connection_entry *conn_ent, + GError *err); +typedef void (*rspamd_http_router_finish_handler_t) (struct + rspamd_http_connection_entry *conn_ent); /** * HTTP connection structure @@ -132,12 +136,12 @@ struct rspamd_http_connection_router { * @param opts options * @return new connection structure */ -struct rspamd_http_connection* rspamd_http_connection_new ( - rspamd_http_body_handler_t body_handler, - rspamd_http_error_handler_t error_handler, - rspamd_http_finish_handler_t finish_handler, - enum rspamd_http_options opts, - enum rspamd_http_connection_type type); +struct rspamd_http_connection * rspamd_http_connection_new ( + rspamd_http_body_handler_t body_handler, + rspamd_http_error_handler_t error_handler, + rspamd_http_finish_handler_t finish_handler, + enum rspamd_http_options opts, + enum rspamd_http_connection_type type); /** * Handle a request using socket fd and user data ud @@ -146,11 +150,11 @@ struct rspamd_http_connection* rspamd_http_connection_new ( * @param fd fd to read/write */ void rspamd_http_connection_read_message ( - struct rspamd_http_connection *conn, - gpointer ud, - gint fd, - struct timeval *timeout, - struct event_base *base); + struct rspamd_http_connection *conn, + gpointer ud, + gint fd, + struct timeval *timeout, + struct event_base *base); /** * Send reply using initialised connection @@ -160,14 +164,14 @@ void rspamd_http_connection_read_message ( * @param fd fd to read/write */ void rspamd_http_connection_write_message ( - struct rspamd_http_connection *conn, - struct rspamd_http_message *msg, - const gchar *host, - const gchar *mime_type, - gpointer ud, - gint fd, - struct timeval *timeout, - struct event_base *base); + struct rspamd_http_connection *conn, + struct rspamd_http_message *msg, + const gchar *host, + const gchar *mime_type, + gpointer ud, + gint fd, + struct timeval *timeout, + struct event_base *base); /** * Free connection structure @@ -183,7 +187,7 @@ void rspamd_http_connection_free (struct rspamd_http_connection *conn); static inline struct rspamd_http_connection * rspamd_http_connection_ref (struct rspamd_http_connection *conn) { - conn->ref ++; + conn->ref++; return conn; } @@ -210,7 +214,7 @@ void rspamd_http_connection_reset (struct rspamd_http_connection *conn); * @param code code to pass * @return new reply object */ -struct rspamd_http_message* rspamd_http_new_message (enum http_parser_type type); +struct rspamd_http_message * rspamd_http_new_message (enum http_parser_type type); /** * Append a header to reply @@ -218,14 +222,17 @@ struct rspamd_http_message* rspamd_http_new_message (enum http_parser_type type) * @param name * @param value */ -void rspamd_http_message_add_header (struct rspamd_http_message *rep, const gchar *name, const gchar *value); +void rspamd_http_message_add_header (struct rspamd_http_message *rep, + const gchar *name, + const gchar *value); /** * Search for a specified header in message * @param rep message * @param name name of header */ -const gchar* rspamd_http_message_find_header (struct rspamd_http_message *rep, const gchar *name); +const gchar * rspamd_http_message_find_header (struct rspamd_http_message *rep, + const gchar *name); /** * Free HTTP reply @@ -249,18 +256,18 @@ time_t rspamd_http_parse_date (const gchar *header, gsize len); * the specified directory * @return */ -struct rspamd_http_connection_router* rspamd_http_router_new ( - rspamd_http_router_error_handler_t eh, - rspamd_http_router_finish_handler_t fh, - struct timeval *timeout, - struct event_base *base, - const char *default_fs_path); +struct rspamd_http_connection_router * rspamd_http_router_new ( + rspamd_http_router_error_handler_t eh, + rspamd_http_router_finish_handler_t fh, + struct timeval *timeout, + struct event_base *base, + const char *default_fs_path); /** * Add new path to the router */ void rspamd_http_router_add_path (struct rspamd_http_connection_router *router, - const gchar *path, rspamd_http_router_handler_t handler); + const gchar *path, rspamd_http_router_handler_t handler); /** * Handle new accepted socket @@ -268,8 +275,10 @@ void rspamd_http_router_add_path (struct rspamd_http_connection_router *router, * @param fd server socket * @param ud opaque userdata */ -void rspamd_http_router_handle_socket (struct rspamd_http_connection_router *router, - gint fd, gpointer ud); +void rspamd_http_router_handle_socket ( + struct rspamd_http_connection_router *router, + gint fd, + gpointer ud); /** * Free router and all connections associated diff --git a/src/libutil/logger.c b/src/libutil/logger.c index 47e308ecd..c91d56982 100644 --- a/src/libutil/logger.c +++ b/src/libutil/logger.c @@ -38,29 +38,29 @@ * It is NOT shared between processes and is created by main process */ struct rspamd_logger_s { - rspamd_log_func_t log_func; - struct rspamd_config *cfg; + rspamd_log_func_t log_func; + struct rspamd_config *cfg; struct { - guint32 size; - guint32 used; - u_char *buf; + guint32 size; + guint32 used; + u_char *buf; } io_buf; - gint fd; - gboolean is_buffered; - gboolean enabled; - gboolean is_debug; - gboolean throttling; - time_t throttling_time; - sig_atomic_t do_reopen_log; - enum rspamd_log_type type; - pid_t pid; - GQuark process_type; - radix_tree_t *debug_ip; - guint32 last_line_cksum; - guint32 repeats; - gchar *saved_message; - gchar *saved_function; - GMutex *mtx; + gint fd; + gboolean is_buffered; + gboolean enabled; + gboolean is_debug; + gboolean throttling; + time_t throttling_time; + sig_atomic_t do_reopen_log; + enum rspamd_log_type type; + pid_t pid; + GQuark process_type; + radix_tree_t *debug_ip; + guint32 last_line_cksum; + guint32 repeats; + gchar *saved_message; + gchar *saved_function; + GMutex *mtx; }; static const gchar lf_chr = '\n'; @@ -69,13 +69,13 @@ static rspamd_logger_t *default_logger = NULL; static void -syslog_log_function (const gchar * log_domain, const gchar *function, - GLogLevelFlags log_level, const gchar * message, - gboolean forced, gpointer arg); +syslog_log_function (const gchar * log_domain, const gchar *function, + GLogLevelFlags log_level, const gchar * message, + gboolean forced, gpointer arg); static void -file_log_function (const gchar * log_domain, const gchar *function, - GLogLevelFlags log_level, const gchar * message, - gboolean forced, gpointer arg); +file_log_function (const gchar * log_domain, const gchar *function, + GLogLevelFlags log_level, const gchar * message, + gboolean forced, gpointer arg); /** * Calculate checksum for log line (used for repeating logic) @@ -83,31 +83,36 @@ file_log_function (const gchar * log_domain, const gchar *function, static inline guint32 rspamd_log_calculate_cksum (const gchar *message, size_t mlen) { - const gchar *bp = message; - const gchar *be = bp + mlen; - guint32 hval = 0; - - while (bp < be) { - hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24); - hval ^= (guint32)*bp++; - } - - /* return our new hash value */ - return hval; - + const gchar *bp = message; + const gchar *be = bp + mlen; + guint32 hval = 0; + + while (bp < be) { + hval += + (hval << + 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); + hval ^= (guint32) * bp++; + } + + /* return our new hash value */ + return hval; + } /* * Write a line to log file (unbuffered) */ static void -direct_write_log_line (rspamd_logger_t *rspamd_log, void *data, gint count, gboolean is_iov) +direct_write_log_line (rspamd_logger_t *rspamd_log, + void *data, + gint count, + gboolean is_iov) { - gchar errmsg[128]; - struct iovec *iov; - const gchar *line; - gint r; - + gchar errmsg[128]; + struct iovec *iov; + const gchar *line; + gint r; + if (rspamd_log->enabled) { if (is_iov) { iov = (struct iovec *)data; @@ -119,7 +124,10 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, void *data, gint count, gboo } if (r == -1) { /* We cannot write message to file, so we need to detect error and make decision */ - r = rspamd_snprintf (errmsg, sizeof (errmsg), "direct_write_log_line: cannot write log line: %s", strerror (errno)); + r = rspamd_snprintf (errmsg, + sizeof (errmsg), + "direct_write_log_line: cannot write log line: %s", + strerror (errno)); if (errno == EIO || errno == EINTR) { /* Descriptor is somehow invalid, try to restart */ reopen_log (rspamd_log); @@ -128,7 +136,8 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, void *data, gint count, gboo direct_write_log_line (rspamd_log, data, count, is_iov); } } - else if (errno == EFAULT || errno == EINVAL || errno == EFBIG || errno == ENOSPC) { + else if (errno == EFAULT || errno == EINVAL || errno == EFBIG || + errno == ENOSPC) { /* Rare case */ rspamd_log->throttling = TRUE; rspamd_log->throttling_time = time (NULL); @@ -156,7 +165,7 @@ rspamd_escape_log_string (gchar *str) else if (*p == '\n' || *p == '\r') { *p = ' '; } - p ++; + p++; } } @@ -174,16 +183,17 @@ open_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid) rspamd_log->enabled = TRUE; return 0; case RSPAMD_LOG_FILE: - rspamd_log->fd = open (rspamd_log->cfg->log_file, O_CREAT | O_WRONLY | O_APPEND, + rspamd_log->fd = open (rspamd_log->cfg->log_file, + O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); if (rspamd_log->fd == -1) { fprintf (stderr, "open_log: cannot open desired log file: %s, %s", - rspamd_log->cfg->log_file, strerror (errno)); + rspamd_log->cfg->log_file, strerror (errno)); return -1; } if (fchown (rspamd_log->fd, uid, gid) == -1) { fprintf (stderr, "open_log: cannot chown desired log file: %s, %s", - rspamd_log->cfg->log_file, strerror (errno)); + rspamd_log->cfg->log_file, strerror (errno)); close (rspamd_log->fd); return -1; } @@ -196,7 +206,7 @@ open_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid) void close_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid) { - gchar tmpbuf[256]; + gchar tmpbuf[256]; flush_log_buf (rspamd_log); switch (rspamd_log->type) { @@ -209,17 +219,30 @@ close_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid) case RSPAMD_LOG_FILE: if (rspamd_log->enabled) { if (rspamd_log->repeats > REPEATS_MIN) { - rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "Last message repeated %ud times", rspamd_log->repeats); + rspamd_snprintf (tmpbuf, + sizeof (tmpbuf), + "Last message repeated %ud times", + rspamd_log->repeats); rspamd_log->repeats = 0; if (rspamd_log->saved_message) { - file_log_function (NULL, rspamd_log->saved_function, rspamd_log->cfg->log_level, rspamd_log->saved_message, TRUE, rspamd_log); + file_log_function (NULL, + rspamd_log->saved_function, + rspamd_log->cfg->log_level, + rspamd_log->saved_message, + TRUE, + rspamd_log); g_free (rspamd_log->saved_message); g_free (rspamd_log->saved_function); rspamd_log->saved_message = NULL; rspamd_log->saved_function = NULL; - } + } /* It is safe to use temporary buffer here as it is not static */ - file_log_function (NULL, __FUNCTION__, rspamd_log->cfg->log_level, tmpbuf, TRUE, rspamd_log); + file_log_function (NULL, + __FUNCTION__, + rspamd_log->cfg->log_level, + tmpbuf, + TRUE, + rspamd_log); return; } @@ -275,12 +298,14 @@ reopen_log (rspamd_logger_t *logger) * Setup logger */ void -rspamd_set_logger (struct rspamd_config *cfg, GQuark ptype, struct rspamd_main *rspamd) +rspamd_set_logger (struct rspamd_config *cfg, + GQuark ptype, + struct rspamd_main *rspamd) { - gchar **strvec, *p, *err; - gint num, i, k; - struct in_addr addr; - guint32 mask = 0xFFFFFFFF; + gchar **strvec, *p, *err; + gint num, i, k; + struct in_addr addr; + guint32 mask = 0xFFFFFFFF; if (rspamd->logger == NULL) { rspamd->logger = g_malloc (sizeof (rspamd_logger_t)); @@ -299,16 +324,16 @@ rspamd_set_logger (struct rspamd_config *cfg, GQuark ptype, struct rspamd_main * #endif switch (cfg->log_type) { - case RSPAMD_LOG_CONSOLE: - rspamd->logger->log_func = file_log_function; - rspamd->logger->fd = STDERR_FILENO; - break; - case RSPAMD_LOG_SYSLOG: - rspamd->logger->log_func = syslog_log_function; - break; - case RSPAMD_LOG_FILE: - rspamd->logger->log_func = file_log_function; - break; + case RSPAMD_LOG_CONSOLE: + rspamd->logger->log_func = file_log_function; + rspamd->logger->fd = STDERR_FILENO; + break; + case RSPAMD_LOG_SYSLOG: + rspamd->logger->log_func = syslog_log_function; + break; + case RSPAMD_LOG_FILE: + rspamd->logger->log_func = file_log_function; + break; } rspamd->logger->cfg = cfg; @@ -330,8 +355,10 @@ rspamd_set_logger (struct rspamd_config *cfg, GQuark ptype, struct rspamd_main * radix_tree_free (rspamd->logger->debug_ip); } rspamd->logger->debug_ip = radix_tree_create (); - if (!add_map (rspamd->cfg, rspamd->cfg->debug_ip_map, "IP addresses for which debug logs are enabled", - read_radix_list, fin_radix_list, (void **)&rspamd->logger->debug_ip)) { + if (!add_map (rspamd->cfg, rspamd->cfg->debug_ip_map, + "IP addresses for which debug logs are enabled", + read_radix_list, fin_radix_list, + (void **)&rspamd->logger->debug_ip)) { /* Try to parse it as list */ strvec = g_strsplit_set (rspamd->cfg->debug_ip_map, ",; ", 0); num = g_strv_length (strvec); @@ -342,7 +369,7 @@ rspamd_set_logger (struct rspamd_config *cfg, GQuark ptype, struct rspamd_main * if ((p = strchr (strvec[i], '/')) != NULL) { /* Try to extract mask */ *p = '\0'; - p ++; + p++; errno = 0; k = strtoul (p, &err, 10); if (errno != 0 || *err != '\0' || k > 32) { @@ -355,7 +382,8 @@ rspamd_set_logger (struct rspamd_config *cfg, GQuark ptype, struct rspamd_main * if (inet_aton (strvec[i], &addr)) { /* Check ip */ mask = mask << (32 - k); - radix32tree_insert (rspamd->logger->debug_ip, ntohl (addr.s_addr), mask, 1); + radix32tree_insert (rspamd->logger->debug_ip, + ntohl (addr.s_addr), mask, 1); } } g_strfreev (strvec); @@ -385,19 +413,27 @@ update_log_pid (GQuark ptype, rspamd_logger_t *rspamd_log) void flush_log_buf (rspamd_logger_t *rspamd_log) { - if (rspamd_log->is_buffered && (rspamd_log->type == RSPAMD_LOG_CONSOLE || rspamd_log->type == RSPAMD_LOG_FILE)) { - direct_write_log_line (rspamd_log, rspamd_log->io_buf.buf, rspamd_log->io_buf.used, FALSE); + if (rspamd_log->is_buffered && + (rspamd_log->type == RSPAMD_LOG_CONSOLE || rspamd_log->type == + RSPAMD_LOG_FILE)) { + direct_write_log_line (rspamd_log, + rspamd_log->io_buf.buf, + rspamd_log->io_buf.used, + FALSE); rspamd_log->io_buf.used = 0; } } void -rspamd_common_logv (rspamd_logger_t *rspamd_log, GLogLevelFlags log_level, const gchar *function, - const gchar *fmt, va_list args) +rspamd_common_logv (rspamd_logger_t *rspamd_log, + GLogLevelFlags log_level, + const gchar *function, + const gchar *fmt, + va_list args) { - static gchar logbuf[BUFSIZ]; - u_char *end; + static gchar logbuf[BUFSIZ]; + u_char *end; if (rspamd_log == NULL) { rspamd_log = default_logger; @@ -417,7 +453,12 @@ rspamd_common_logv (rspamd_logger_t *rspamd_log, GLogLevelFlags log_level, const end = rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, args); *end = '\0'; rspamd_escape_log_string (logbuf); - rspamd_log->log_func (NULL, function, log_level, logbuf, FALSE, rspamd_log); + rspamd_log->log_func (NULL, + function, + log_level, + logbuf, + FALSE, + rspamd_log); g_mutex_unlock (rspamd_log->mtx); } } @@ -426,10 +467,13 @@ rspamd_common_logv (rspamd_logger_t *rspamd_log, GLogLevelFlags log_level, const * This log functions select real logger and write message if level is less or equal to configured log level */ void -rspamd_common_log_function (rspamd_logger_t *rspamd_log, GLogLevelFlags log_level, - const gchar *function, const gchar *fmt, ...) +rspamd_common_log_function (rspamd_logger_t *rspamd_log, + GLogLevelFlags log_level, + const gchar *function, + const gchar *fmt, + ...) { - va_list vp; + va_list vp; va_start (vp, fmt); rspamd_common_logv (rspamd_log, log_level, function, fmt, vp); @@ -438,17 +482,17 @@ rspamd_common_log_function (rspamd_logger_t *rspamd_log, GLogLevelFlags log_leve void rspamd_default_logv (GLogLevelFlags log_level, const gchar *function, - const gchar *fmt, va_list args) + const gchar *fmt, va_list args) { rspamd_common_logv (NULL, log_level, function, fmt, args); } void rspamd_default_log_function (GLogLevelFlags log_level, - const gchar *function, const gchar *fmt, ...) + const gchar *function, const gchar *fmt, ...) { - va_list vp; + va_list vp; va_start (vp, fmt); rspamd_default_logv (log_level, function, fmt, vp); @@ -462,10 +506,12 @@ rspamd_default_log_function (GLogLevelFlags log_level, static void fill_buffer (rspamd_logger_t *rspamd_log, const struct iovec *iov, gint iovcnt) { - gint i; + gint i; - for (i = 0; i < iovcnt; i ++) { - memcpy (rspamd_log->io_buf.buf + rspamd_log->io_buf.used, iov[i].iov_base, iov[i].iov_len); + for (i = 0; i < iovcnt; i++) { + memcpy (rspamd_log->io_buf.buf + rspamd_log->io_buf.used, + iov[i].iov_base, + iov[i].iov_len); rspamd_log->io_buf.used += iov[i].iov_len; } @@ -475,18 +521,20 @@ fill_buffer (rspamd_logger_t *rspamd_log, const struct iovec *iov, gint iovcnt) * Write message to buffer or to file (using direct_write_log_line function) */ static void -file_log_helper (rspamd_logger_t *rspamd_log, const struct iovec *iov, gint iovcnt) +file_log_helper (rspamd_logger_t *rspamd_log, + const struct iovec *iov, + gint iovcnt) { - size_t len = 0; - gint i; + size_t len = 0; + gint i; - if (! rspamd_log->is_buffered) { + if (!rspamd_log->is_buffered) { /* Write string directly */ direct_write_log_line (rspamd_log, (void *)iov, iovcnt, TRUE); } else { /* Calculate total length */ - for (i = 0; i < iovcnt; i ++) { + for (i = 0; i < iovcnt; i++) { len += iov[i].iov_len; } /* Fill buffer */ @@ -511,11 +559,16 @@ file_log_helper (rspamd_logger_t *rspamd_log, const struct iovec *iov, gint iovc * Syslog interface for logging */ static void -syslog_log_function (const gchar * log_domain, const gchar *function, GLogLevelFlags log_level, const gchar * message, gboolean forced, gpointer arg) +syslog_log_function (const gchar * log_domain, + const gchar *function, + GLogLevelFlags log_level, + const gchar * message, + gboolean forced, + gpointer arg) { - rspamd_logger_t *rspamd_log = arg; + rspamd_logger_t *rspamd_log = arg; - if (! rspamd_log->enabled) { + if (!rspamd_log->enabled) { return; } if (function == NULL) { @@ -556,20 +609,25 @@ syslog_log_function (const gchar * log_domain, const gchar *function, GLogLevelF * Main file interface for logging */ static void -file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFlags log_level, const gchar * message, gboolean forced, gpointer arg) +file_log_function (const gchar * log_domain, + const gchar *function, + GLogLevelFlags log_level, + const gchar * message, + gboolean forced, + gpointer arg) { - gchar tmpbuf[256], timebuf[32]; - time_t now; - struct tm *tms; - struct iovec iov[4]; - gint r = 0; - guint32 cksum; - size_t mlen; - const gchar *cptype = NULL; - gboolean got_time = FALSE; - rspamd_logger_t *rspamd_log = arg; - - if (! rspamd_log->enabled) { + gchar tmpbuf[256], timebuf[32]; + time_t now; + struct tm *tms; + struct iovec iov[4]; + gint r = 0; + guint32 cksum; + size_t mlen; + const gchar *cptype = NULL; + gboolean got_time = FALSE; + rspamd_logger_t *rspamd_log = arg; + + if (!rspamd_log->enabled) { return; } @@ -591,8 +649,9 @@ file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFla mlen = strlen (message); cksum = rspamd_log_calculate_cksum (message, mlen); if (cksum == rspamd_log->last_line_cksum) { - rspamd_log->repeats ++; - if (rspamd_log->repeats > REPEATS_MIN && rspamd_log->repeats < REPEATS_MAX) { + rspamd_log->repeats++; + if (rspamd_log->repeats > REPEATS_MIN && rspamd_log->repeats < + REPEATS_MAX) { /* Do not log anything */ if (rspamd_log->saved_message == 0) { rspamd_log->saved_message = g_strdup (message); @@ -601,14 +660,32 @@ file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFla return; } else if (rspamd_log->repeats > REPEATS_MAX) { - rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "Last message repeated %ud times", rspamd_log->repeats); + rspamd_snprintf (tmpbuf, + sizeof (tmpbuf), + "Last message repeated %ud times", + rspamd_log->repeats); rspamd_log->repeats = 0; /* It is safe to use temporary buffer here as it is not static */ if (rspamd_log->saved_message) { - file_log_function (log_domain, rspamd_log->saved_function, log_level, rspamd_log->saved_message, forced, arg); - } - file_log_function (log_domain, __FUNCTION__, log_level, tmpbuf, forced, arg); - file_log_function (log_domain, function, log_level, message, forced, arg); + file_log_function (log_domain, + rspamd_log->saved_function, + log_level, + rspamd_log->saved_message, + forced, + arg); + } + file_log_function (log_domain, + __FUNCTION__, + log_level, + tmpbuf, + forced, + arg); + file_log_function (log_domain, + function, + log_level, + message, + forced, + arg); rspamd_log->repeats = REPEATS_MIN + 1; return; } @@ -617,18 +694,36 @@ file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFla /* Reset counter if new message differs from saved message */ rspamd_log->last_line_cksum = cksum; if (rspamd_log->repeats > REPEATS_MIN) { - rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "Last message repeated %ud times", rspamd_log->repeats); + rspamd_snprintf (tmpbuf, + sizeof (tmpbuf), + "Last message repeated %ud times", + rspamd_log->repeats); rspamd_log->repeats = 0; if (rspamd_log->saved_message) { - file_log_function (log_domain, rspamd_log->saved_function, log_level, rspamd_log->saved_message, forced, arg); + file_log_function (log_domain, + rspamd_log->saved_function, + log_level, + rspamd_log->saved_message, + forced, + arg); g_free (rspamd_log->saved_message); g_free (rspamd_log->saved_function); rspamd_log->saved_message = NULL; rspamd_log->saved_function = NULL; - } - file_log_function (log_domain, __FUNCTION__, log_level, tmpbuf, forced, arg); + } + file_log_function (log_domain, + __FUNCTION__, + log_level, + tmpbuf, + forced, + arg); /* It is safe to use temporary buffer here as it is not static */ - file_log_function (log_domain, function, log_level, message, forced, arg); + file_log_function (log_domain, + function, + log_level, + message, + forced, + arg); return; } else { @@ -637,7 +732,7 @@ file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFla } if (rspamd_log->cfg->log_extended) { - if (! got_time) { + if (!got_time) { now = time (NULL); } @@ -665,10 +760,21 @@ file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFla r = 0; } if (function == NULL) { - r += rspamd_snprintf (tmpbuf + r, sizeof (tmpbuf) - r, "%s #%P(%s) ", timebuf, rspamd_log->pid, cptype); + r += rspamd_snprintf (tmpbuf + r, + sizeof (tmpbuf) - r, + "%s #%P(%s) ", + timebuf, + rspamd_log->pid, + cptype); } else { - r += rspamd_snprintf (tmpbuf + r, sizeof (tmpbuf) -r, "%s #%P(%s) %s: ", timebuf, rspamd_log->pid, cptype, function); + r += rspamd_snprintf (tmpbuf + r, + sizeof (tmpbuf) - r, + "%s #%P(%s) %s: ", + timebuf, + rspamd_log->pid, + cptype, + function); } /* Construct IOV for log line */ iov[0].iov_base = tmpbuf; @@ -712,16 +818,17 @@ file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFla */ void rspamd_conditional_debug (rspamd_logger_t *rspamd_log, - rspamd_inet_addr_t *addr, const gchar *function, const gchar *fmt, ...) + rspamd_inet_addr_t *addr, const gchar *function, const gchar *fmt, ...) { - static gchar logbuf[BUFSIZ]; - va_list vp; - u_char *end; + static gchar logbuf[BUFSIZ]; + va_list vp; + u_char *end; - if (rspamd_log->cfg->log_level >= G_LOG_LEVEL_DEBUG || rspamd_log->is_debug) { + if (rspamd_log->cfg->log_level >= G_LOG_LEVEL_DEBUG || + rspamd_log->is_debug) { if (rspamd_log->debug_ip && addr != NULL) { if (addr->af == AF_INET && radix32tree_find (rspamd_log->debug_ip, - ntohl (addr->addr.s4.sin_addr.s_addr)) == RADIX_NO_VALUE) { + ntohl (addr->addr.s4.sin_addr.s_addr)) == RADIX_NO_VALUE) { return; } } @@ -731,21 +838,34 @@ rspamd_conditional_debug (rspamd_logger_t *rspamd_log, *end = '\0'; rspamd_escape_log_string (logbuf); va_end (vp); - rspamd_log->log_func (NULL, function, G_LOG_LEVEL_DEBUG, logbuf, TRUE, rspamd_log); + rspamd_log->log_func (NULL, + function, + G_LOG_LEVEL_DEBUG, + logbuf, + TRUE, + rspamd_log); g_mutex_unlock (rspamd_log->mtx); } -} +} /** * Wrapper for glib logger */ void -rspamd_glib_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg) +rspamd_glib_log_function (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer arg) { - rspamd_logger_t *rspamd_log = arg; + rspamd_logger_t *rspamd_log = arg; if (rspamd_log->enabled) { g_mutex_lock (rspamd_log->mtx); - rspamd_log->log_func (log_domain, NULL, log_level, message, FALSE, rspamd_log); + rspamd_log->log_func (log_domain, + NULL, + log_level, + message, + FALSE, + rspamd_log); g_mutex_unlock (rspamd_log->mtx); } } diff --git a/src/libutil/logger.h b/src/libutil/logger.h index 4b1c74410..078180b86 100644 --- a/src/libutil/logger.h +++ b/src/libutil/logger.h @@ -7,15 +7,18 @@ #include "util.h" -typedef void (*rspamd_log_func_t)(const gchar * log_domain, const gchar *function, - GLogLevelFlags log_level, const gchar * message, - gboolean forced, gpointer arg); +typedef void (*rspamd_log_func_t)(const gchar * log_domain, + const gchar *function, + GLogLevelFlags log_level, const gchar * message, + gboolean forced, gpointer arg); typedef struct rspamd_logger_s rspamd_logger_t; /** * Init logger */ -void rspamd_set_logger (struct rspamd_config *cfg, GQuark ptype, struct rspamd_main *main); +void rspamd_set_logger (struct rspamd_config *cfg, + GQuark ptype, + struct rspamd_main *main); /** * Open log file or initialize other structures */ @@ -55,28 +58,33 @@ void flush_log_buf (rspamd_logger_t *logger); * Log function that is compatible for glib messages */ void rspamd_glib_log_function (const gchar *log_domain, - GLogLevelFlags log_level, const gchar *message, gpointer arg); + GLogLevelFlags log_level, const gchar *message, gpointer arg); /** * Function with variable number of arguments support */ void rspamd_common_log_function (rspamd_logger_t *logger, - GLogLevelFlags log_level, const gchar *function, const gchar *fmt, ...); + GLogLevelFlags log_level, const gchar *function, const gchar *fmt, ...); void rspamd_common_logv (rspamd_logger_t *logger, - GLogLevelFlags log_level, const gchar *function, const gchar *fmt, va_list args); + GLogLevelFlags log_level, + const gchar *function, + const gchar *fmt, + va_list args); /** * Conditional debug function */ void rspamd_conditional_debug (rspamd_logger_t *logger, - rspamd_inet_addr_t *addr, const gchar *function, const gchar *fmt, ...) ; + rspamd_inet_addr_t *addr, const gchar *function, const gchar *fmt, ...); /** * Function with variable number of arguments support that uses static default logger */ -void rspamd_default_log_function (GLogLevelFlags log_level, const gchar *function, - const gchar *fmt, ...); +void rspamd_default_log_function (GLogLevelFlags log_level, + const gchar *function, + const gchar *fmt, + ...); /** * Varargs version of default log function @@ -85,7 +93,10 @@ void rspamd_default_log_function (GLogLevelFlags log_level, const gchar *functio * @param fmt * @param args */ -void rspamd_default_logv (GLogLevelFlags log_level, const gchar *function, const gchar *fmt, va_list args); +void rspamd_default_logv (GLogLevelFlags log_level, + const gchar *function, + const gchar *fmt, + va_list args); /** * Temporary turn on debug @@ -101,17 +112,42 @@ void rspamd_log_nodebug (rspamd_logger_t *logger); /* Logging in postfix style */ #if defined(RSPAMD_MAIN) -#define msg_err(...) rspamd_common_log_function(rspamd_main->logger, G_LOG_LEVEL_CRITICAL, __FUNCTION__, __VA_ARGS__) -#define msg_warn(...) rspamd_common_log_function(rspamd_main->logger, G_LOG_LEVEL_WARNING, __FUNCTION__, __VA_ARGS__) -#define msg_info(...) rspamd_common_log_function(rspamd_main->logger, G_LOG_LEVEL_INFO, __FUNCTION__, __VA_ARGS__) -#define msg_debug(...) rspamd_conditional_debug(rspamd_main->logger, NULL, __FUNCTION__, __VA_ARGS__) -#define debug_task(...) rspamd_conditional_debug(rspamd_main->logger, &task->from_addr, __FUNCTION__, __VA_ARGS__) +#define msg_err(...) rspamd_common_log_function (rspamd_main->logger, \ + G_LOG_LEVEL_CRITICAL, \ + __FUNCTION__, \ + __VA_ARGS__) +#define msg_warn(...) rspamd_common_log_function (rspamd_main->logger, \ + G_LOG_LEVEL_WARNING, \ + __FUNCTION__, \ + __VA_ARGS__) +#define msg_info(...) rspamd_common_log_function (rspamd_main->logger, \ + G_LOG_LEVEL_INFO, \ + __FUNCTION__, \ + __VA_ARGS__) +#define msg_debug(...) rspamd_conditional_debug (rspamd_main->logger, \ + NULL, \ + __FUNCTION__, \ + __VA_ARGS__) +#define debug_task(...) rspamd_conditional_debug (rspamd_main->logger, \ + &task->from_addr, \ + __FUNCTION__, \ + __VA_ARGS__) #else -#define msg_err(...) rspamd_default_log_function(G_LOG_LEVEL_CRITICAL, __FUNCTION__, __VA_ARGS__) -#define msg_warn(...) rspamd_default_log_function(G_LOG_LEVEL_WARNING, __FUNCTION__, __VA_ARGS__) -#define msg_info(...) rspamd_default_log_function(G_LOG_LEVEL_INFO, __FUNCTION__, __VA_ARGS__) -#define msg_debug(...) rspamd_default_log_function(G_LOG_LEVEL_DEBUG, __FUNCTION__, __VA_ARGS__) -#define debug_task(...) rspamd_default_log_function(G_LOG_LEVEL_DEBUG, __FUNCTION__, __VA_ARGS__) +#define msg_err(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \ + __FUNCTION__, \ + __VA_ARGS__) +#define msg_warn(...) rspamd_default_log_function (G_LOG_LEVEL_WARNING, \ + __FUNCTION__, \ + __VA_ARGS__) +#define msg_info(...) rspamd_default_log_function (G_LOG_LEVEL_INFO, \ + __FUNCTION__, \ + __VA_ARGS__) +#define msg_debug(...) rspamd_default_log_function (G_LOG_LEVEL_DEBUG, \ + __FUNCTION__, \ + __VA_ARGS__) +#define debug_task(...) rspamd_default_log_function (G_LOG_LEVEL_DEBUG, \ + __FUNCTION__, \ + __VA_ARGS__) #endif #endif diff --git a/src/libutil/map.c b/src/libutil/map.c index ffe3a1e6f..710dcdebc 100644 --- a/src/libutil/map.c +++ b/src/libutil/map.c @@ -32,27 +32,27 @@ #include "util.h" #include "mem_pool.h" -static const gchar *hash_fill = "1"; +static const gchar *hash_fill = "1"; /* Http reply */ struct http_reply { - gint code; - GHashTable *headers; - gchar *cur_header; - gint parser_state; + gint code; + GHashTable *headers; + gchar *cur_header; + gint parser_state; }; struct http_callback_data { - struct event ev; - struct event_base *ev_base; - struct timeval tv; - struct rspamd_map *map; - struct http_map_data *data; - struct http_reply *reply; - struct map_cb_data cbdata; - - gint state; - gint fd; + struct event ev; + struct event_base *ev_base; + struct timeval tv; + struct rspamd_map *map; + struct http_map_data *data; + struct http_reply *reply; + struct map_cb_data cbdata; + + gint state; + gint fd; }; /* Value in seconds after whitch we would try to do stat on list file */ @@ -65,12 +65,17 @@ struct http_callback_data { * Helper for HTTP connection establishment */ static gint -connect_http (struct rspamd_map *map, struct http_map_data *data, gboolean is_async) +connect_http (struct rspamd_map *map, + struct http_map_data *data, + gboolean is_async) { - gint sock; + gint sock; if ((sock = make_tcp_socket (data->addr, FALSE, is_async)) == -1) { - msg_info ("cannot connect to http server %s: %d, %s", data->host, errno, strerror (errno)); + msg_info ("cannot connect to http server %s: %d, %s", + data->host, + errno, + strerror (errno)); return -1; } @@ -81,17 +86,27 @@ connect_http (struct rspamd_map *map, struct http_map_data *data, gboolean is_as * Write HTTP request */ static void -write_http_request (struct rspamd_map *map, struct http_map_data *data, gint sock) +write_http_request (struct rspamd_map *map, + struct http_map_data *data, + gint sock) { - gchar outbuf[BUFSIZ], datebuf[128]; - gint r; - struct tm *tm; + gchar outbuf[BUFSIZ], datebuf[128]; + gint r; + struct tm *tm; tm = gmtime (&data->last_checked); strftime (datebuf, sizeof (datebuf), "%a, %d %b %Y %H:%M:%S %Z", tm); - r = rspamd_snprintf (outbuf, sizeof (outbuf), "GET %s%s HTTP/1.1" CRLF "Connection: close" CRLF "Host: %s" CRLF, (*data->path == '/') ? "" : "/", data->path, data->host); + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "GET %s%s HTTP/1.1" CRLF "Connection: close" CRLF "Host: %s" CRLF, + (*data->path == '/') ? "" : "/", + data->path, + data->host); if (data->last_checked != 0) { - r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, "If-Modified-Since: %s" CRLF, datebuf); + r += rspamd_snprintf (outbuf + r, + sizeof (outbuf) - r, + "If-Modified-Since: %s" CRLF, + datebuf); } r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, CRLF); @@ -104,16 +119,16 @@ write_http_request (struct rspamd_map *map, struct http_map_data *data, gint soc /** * FSM for parsing HTTP reply */ -static gchar * +static gchar * parse_http_reply (gchar * chunk, gint len, struct http_reply *reply) { - gchar *s, *p, *err_str, *tmp; + gchar *s, *p, *err_str, *tmp; p = chunk; s = chunk; while (p - chunk < len) { switch (reply->parser_state) { - /* Search status code */ + /* Search status code */ case 0: /* Search for status code */ if (*p != ' ') { @@ -131,7 +146,7 @@ parse_http_reply (gchar * chunk, gint len, struct http_reply *reply) continue; } break; - /* Skip to end of line */ + /* Skip to end of line */ case 1: if (*p == '\n') { /* Switch to read header state */ @@ -140,7 +155,7 @@ parse_http_reply (gchar * chunk, gint len, struct http_reply *reply) /* Each skipped symbol is proceeded */ s = ++p; break; - /* Read header value */ + /* Read header value */ case 2: if (*p == ':') { reply->cur_header = g_malloc (p - s + 1); @@ -153,7 +168,7 @@ parse_http_reply (gchar * chunk, gint len, struct http_reply *reply) } p++; break; - /* Skip spaces after header name */ + /* Skip spaces after header name */ case 3: if (*p != ' ') { s = p; @@ -163,13 +178,14 @@ parse_http_reply (gchar * chunk, gint len, struct http_reply *reply) p++; } break; - /* Read header value */ + /* Read header value */ case 4: if (*p == '\r') { if (reply->cur_header != NULL) { tmp = g_malloc (p - s + 1); rspamd_strlcpy (tmp, s, p - s + 1); - g_hash_table_insert (reply->headers, reply->cur_header, tmp); + g_hash_table_insert (reply->headers, reply->cur_header, + tmp); reply->cur_header = NULL; } reply->parser_state = 1; @@ -198,13 +214,14 @@ parse_http_reply (gchar * chunk, gint len, struct http_reply *reply) static gint read_chunk_header (gchar * buf, gint len, struct http_map_data *data) { - gchar chunkbuf[32], *p, *c, *err_str; - gint skip = 0; + gchar chunkbuf[32], *p, *c, *err_str; + gint skip = 0; p = chunkbuf; c = buf; /* Find hex digits */ - while (g_ascii_isxdigit (*c) && p - chunkbuf < (gint)(sizeof (chunkbuf) - 1) && skip < len) { + while (g_ascii_isxdigit (*c) && p - chunkbuf < + (gint)(sizeof (chunkbuf) - 1) && skip < len) { *p++ = *c++; skip++; } @@ -231,11 +248,15 @@ read_chunk_header (gchar * buf, gint len, struct http_map_data *data) /** * Helper callback for reading chunked reply */ -static gboolean -read_http_chunked (gchar * buf, size_t len, struct rspamd_map *map, struct http_map_data *data, struct map_cb_data *cbdata) +static gboolean +read_http_chunked (gchar * buf, + size_t len, + struct rspamd_map *map, + struct http_map_data *data, + struct map_cb_data *cbdata) { - gchar *p = buf, *remain; - gint skip = 0; + gchar *p = buf, *remain; + gint skip = 0; if (data->chunked == 1) { /* Read first chunk data */ @@ -301,14 +322,20 @@ read_http_chunked (gchar * buf, size_t len, struct rspamd_map *map, struct http_ /** * Callback for reading HTTP reply */ -static gboolean -read_http_common (struct rspamd_map *map, struct http_map_data *data, struct http_reply *reply, struct map_cb_data *cbdata, gint fd) +static gboolean +read_http_common (struct rspamd_map *map, + struct http_map_data *data, + struct http_reply *reply, + struct map_cb_data *cbdata, + gint fd) { - gchar *remain, *pos; - ssize_t r; - gchar *te, *date; - - if ((r = read (fd, data->read_buf + data->rlen, sizeof (data->read_buf) - data->rlen)) > 0) { + gchar *remain, *pos; + ssize_t r; + gchar *te, *date; + + if ((r = + read (fd, data->read_buf + data->rlen, sizeof (data->read_buf) - + data->rlen)) > 0) { r += data->rlen; data->rlen = 0; remain = parse_http_reply (data->read_buf, r, reply); @@ -325,7 +352,9 @@ read_http_common (struct rspamd_map *map, struct http_map_data *data, struct htt if (reply->parser_state == 6) { /* If reply header is parsed successfully, try to read further data */ if (reply->code != 200 && reply->code != 304) { - msg_err ("got error reply from server %s, %d", data->host, reply->code); + msg_err ("got error reply from server %s, %d", + data->host, + reply->code); return FALSE; } else if (reply->code == 304) { @@ -335,7 +364,9 @@ read_http_common (struct rspamd_map *map, struct http_map_data *data, struct htt pos = data->read_buf; /* Check for chunked */ if (data->chunked == 0) { - if ((te = g_hash_table_lookup (reply->headers, "Transfer-Encoding")) != NULL) { + if ((te = + g_hash_table_lookup (reply->headers, + "Transfer-Encoding")) != NULL) { if (g_ascii_strcasecmp (te, "chunked") == 0) { data->chunked = 1; } @@ -381,9 +412,9 @@ read_http_common (struct rspamd_map *map, struct http_map_data *data, struct htt static void read_http_sync (struct rspamd_map *map, struct http_map_data *data) { - struct map_cb_data cbdata; - gint fd; - struct http_reply *repl; + struct map_cb_data cbdata; + gint fd; + struct http_reply *repl; if (map->read_callback == NULL || map->fin_callback == NULL) { msg_err ("bad callback for reading map file"); @@ -404,9 +435,12 @@ read_http_sync (struct rspamd_map *map, struct http_map_data *data) repl = g_malloc (sizeof (struct http_reply)); repl->parser_state = 0; repl->code = 404; - repl->headers = g_hash_table_new_full (rspamd_strcase_hash, rspamd_strcase_equal, g_free, g_free); + repl->headers = g_hash_table_new_full (rspamd_strcase_hash, + rspamd_strcase_equal, + g_free, + g_free); - while (read_http_common (map, data, repl, &cbdata, fd)); + while (read_http_common (map, data, repl, &cbdata, fd)) ; close (fd); @@ -426,10 +460,10 @@ read_http_sync (struct rspamd_map *map, struct http_map_data *data) static void read_map_file (struct rspamd_map *map, struct file_map_data *data) { - struct map_cb_data cbdata; - gchar buf[BUFSIZ], *remain; - ssize_t r; - gint fd, rlen; + struct map_cb_data cbdata; + gchar buf[BUFSIZ], *remain; + ssize_t r; + gint fd, rlen; if (map->read_callback == NULL || map->fin_callback == NULL) { msg_err ("bad callback for reading map file"); @@ -437,7 +471,8 @@ read_map_file (struct rspamd_map *map, struct file_map_data *data) } if ((fd = open (data->filename, O_RDONLY)) == -1) { - msg_warn ("cannot open file '%s': %s", data->filename, strerror (errno)); + msg_warn ("cannot open file '%s': %s", data->filename, + strerror (errno)); return; } @@ -467,10 +502,14 @@ read_map_file (struct rspamd_map *map, struct file_map_data *data) /** * FSM for parsing lists */ -gchar * -abstract_parse_kv_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data, insert_func func) +gchar * +abstract_parse_kv_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data, + insert_func func) { - gchar *c, *p, *key = NULL, *value = NULL; + gchar *c, *p, *key = NULL, *value = NULL; p = chunk; c = p; @@ -526,7 +565,7 @@ abstract_parse_kv_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct } } else { - p ++; + p++; } break; case 2: @@ -536,7 +575,7 @@ abstract_parse_kv_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct data->state = 0; } else { - p ++; + p++; } break; case 99: @@ -557,7 +596,7 @@ abstract_parse_kv_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct case 100: /* Skip \r\n and whitespaces */ if (*p == '\r' || *p == '\n' || g_ascii_isspace (*p)) { - p ++; + p++; } else { c = p; @@ -571,10 +610,14 @@ abstract_parse_kv_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct return c; } -gchar * -abstract_parse_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data, insert_func func) +gchar * +abstract_parse_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data, + insert_func func) { - gchar *s, *p, *str, *start; + gchar *s, *p, *str, *start; p = chunk; start = p; @@ -584,7 +627,7 @@ abstract_parse_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct ma while (p - chunk < len) { switch (data->state) { - /* READ_SYMBOL */ + /* READ_SYMBOL */ case 0: if (*p == '#') { /* Got comment */ @@ -623,7 +666,7 @@ abstract_parse_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct ma p++; } break; - /* SKIP_COMMENT */ + /* SKIP_COMMENT */ case 1: /* Skip comment till end of line */ if (*p == '\r' || *p == '\n') { @@ -652,13 +695,13 @@ abstract_parse_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct ma static void radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value) { - radix_tree_t *tree = st; + radix_tree_t *tree = st; - guint32 mask = 0xFFFFFFFF; - guint32 ip; - gchar *token, *ipnet, *err_str, **strv, **cur; - struct in_addr ina; - gint k; + guint32 mask = 0xFFFFFFFF; + guint32 ip; + gchar *token, *ipnet, *err_str, **strv, **cur; + struct in_addr ina; + gint k; /* Split string if there are multiple items inside a single string */ strv = g_strsplit_set ((gchar *)key, " ,;", 0); @@ -677,7 +720,10 @@ radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value) /* Get mask */ k = strtoul (ipnet, &err_str, 10); if (errno != 0) { - msg_warn ("invalid netmask, error detected on symbol: %s, erorr: %s", err_str, strerror (errno)); + msg_warn ( + "invalid netmask, error detected on symbol: %s, erorr: %s", + err_str, + strerror (errno)); k = 32; } else if (k > 32 || k < 0) { @@ -698,10 +744,12 @@ radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value) ip = ntohl ((guint32) ina.s_addr); k = radix32tree_insert (tree, ip, mask, 1); if (k == -1) { - msg_warn ("cannot insert ip to tree: %s, mask %X", inet_ntoa (ina), mask); + msg_warn ("cannot insert ip to tree: %s, mask %X", inet_ntoa ( + ina), mask); } else if (k == 1) { - msg_warn ("ip %s, mask %X, value already exists", inet_ntoa (ina), mask); + msg_warn ("ip %s, mask %X, value already exists", inet_ntoa ( + ina), mask); } cur++; } @@ -710,13 +758,21 @@ radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value) } /* Helpers */ -gchar * -read_host_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +gchar * +read_host_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { if (data->cur_data == NULL) { - data->cur_data = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); + data->cur_data = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); } - return abstract_parse_list (pool, chunk, len, data, (insert_func) g_hash_table_insert); + return abstract_parse_list (pool, + chunk, + len, + data, + (insert_func) g_hash_table_insert); } void @@ -727,13 +783,21 @@ fin_host_list (rspamd_mempool_t * pool, struct map_cb_data *data) } } -gchar * -read_kv_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +gchar * +read_kv_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { if (data->cur_data == NULL) { - data->cur_data = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); + data->cur_data = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); } - return abstract_parse_kv_list (pool, chunk, len, data, (insert_func) g_hash_table_insert); + return abstract_parse_kv_list (pool, + chunk, + len, + data, + (insert_func) g_hash_table_insert); } void @@ -744,13 +808,20 @@ fin_kv_list (rspamd_mempool_t * pool, struct map_cb_data *data) } } -gchar * -read_radix_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +gchar * +read_radix_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { if (data->cur_data == NULL) { data->cur_data = radix_tree_create (); } - return abstract_parse_list (pool, chunk, len, data, (insert_func) radix_tree_insert_helper); + return abstract_parse_list (pool, + chunk, + len, + data, + (insert_func) radix_tree_insert_helper); } void @@ -767,24 +838,28 @@ fin_radix_list (rspamd_mempool_t * pool, struct map_cb_data *data) static void file_callback (gint fd, short what, void *ud) { - struct rspamd_map *map = ud; - struct file_map_data *data = map->map_data; - struct stat st; - gdouble jittered_sec; + struct rspamd_map *map = ud; + struct file_map_data *data = map->map_data; + struct stat st; + gdouble jittered_sec; /* Plan event again with jitter */ evtimer_del (&map->ev); - jittered_sec = (map->cfg->map_timeout + g_random_double () * map->cfg->map_timeout); + jittered_sec = + (map->cfg->map_timeout + g_random_double () * map->cfg->map_timeout); double_to_tv (jittered_sec, &map->tv); evtimer_add (&map->ev, &map->tv); if (g_atomic_int_get (map->locked)) { - msg_info ("don't try to reread map as it is locked by other process, will reread it later"); + msg_info ( + "don't try to reread map as it is locked by other process, will reread it later"); return; } - if (stat (data->filename, &st) != -1 && (st.st_mtime > data->st.st_mtime || data->st.st_mtime == -1)) { + if (stat (data->filename, + &st) != -1 && + (st.st_mtime > data->st.st_mtime || data->st.st_mtime == -1)) { /* File was modified since last check */ memcpy (&data->st, &st, sizeof (struct stat)); } @@ -818,7 +893,7 @@ free_http_cbdata (struct http_callback_data *cbd) static void http_async_callback (gint fd, short what, void *ud) { - struct http_callback_data *cbd = ud; + struct http_callback_data *cbd = ud; /* Begin of connection */ if (what == EV_WRITE) { @@ -826,7 +901,11 @@ http_async_callback (gint fd, short what, void *ud) /* Can write request */ write_http_request (cbd->map, cbd->data, fd); /* Plan reading */ - event_set (&cbd->ev, cbd->fd, EV_READ | EV_PERSIST, http_async_callback, cbd); + event_set (&cbd->ev, + cbd->fd, + EV_READ | EV_PERSIST, + http_async_callback, + cbd); event_base_set (cbd->ev_base, &cbd->ev); cbd->tv.tv_sec = HTTP_READ_TIMEOUT; cbd->tv.tv_usec = 0; @@ -835,7 +914,10 @@ http_async_callback (gint fd, short what, void *ud) cbd->reply = g_malloc (sizeof (struct http_reply)); cbd->reply->parser_state = 0; cbd->reply->code = 404; - cbd->reply->headers = g_hash_table_new_full (rspamd_strcase_hash, rspamd_strcase_equal, g_free, g_free); + cbd->reply->headers = g_hash_table_new_full (rspamd_strcase_hash, + rspamd_strcase_equal, + g_free, + g_free); cbd->cbdata.state = 0; cbd->cbdata.prev_data = *cbd->map->user_data; cbd->cbdata.cur_data = NULL; @@ -857,13 +939,15 @@ http_async_callback (gint fd, short what, void *ud) /* Got reply, parse it */ else if (what == EV_READ) { if (cbd->state >= 1) { - if (!read_http_common (cbd->map, cbd->data, cbd->reply, &cbd->cbdata, cbd->fd)) { + if (!read_http_common (cbd->map, cbd->data, cbd->reply, + &cbd->cbdata, cbd->fd)) { /* Handle Not-Modified in a special way */ if (cbd->reply->code == 304) { if (cbd->data->last_checked == (time_t)-1) { cbd->data->last_checked = time (NULL); } - msg_info ("data is not modified for server %s", cbd->data->host); + msg_info ("data is not modified for server %s", + cbd->data->host); } else if (cbd->cbdata.cur_data != NULL) { /* Destroy old data and start reading request data */ @@ -900,20 +984,22 @@ http_async_callback (gint fd, short what, void *ud) static void http_callback (gint fd, short what, void *ud) { - struct rspamd_map *map = ud; - struct http_map_data *data = map->map_data; - gint sock; - struct http_callback_data *cbd; - gdouble jittered_sec; + struct rspamd_map *map = ud; + struct http_map_data *data = map->map_data; + gint sock; + struct http_callback_data *cbd; + gdouble jittered_sec; /* Plan event again with jitter */ evtimer_del (&map->ev); - jittered_sec = (map->cfg->map_timeout + g_random_double () * map->cfg->map_timeout); + jittered_sec = + (map->cfg->map_timeout + g_random_double () * map->cfg->map_timeout); double_to_tv (jittered_sec, &map->tv); evtimer_add (&map->ev, &map->tv); if (g_atomic_int_get (map->locked)) { - msg_info ("don't try to reread map as it is locked by other process, will reread it later"); + msg_info ( + "don't try to reread map as it is locked by other process, will reread it later"); return; } @@ -945,10 +1031,10 @@ http_callback (gint fd, short what, void *ud) void start_map_watch (struct rspamd_config *cfg, struct event_base *ev_base) { - GList *cur = cfg->maps; - struct rspamd_map *map; - struct file_map_data *fdata; - gdouble jittered_sec; + GList *cur = cfg->maps; + struct rspamd_map *map; + struct file_map_data *fdata; + gdouble jittered_sec; /* First of all do synced read of data */ while (cur) { @@ -964,7 +1050,9 @@ start_map_watch (struct rspamd_config *cfg, struct event_base *ev_base) read_map_file (map, map->map_data); } /* Plan event with jitter */ - jittered_sec = (map->cfg->map_timeout + g_random_double () * map->cfg->map_timeout) / 2.; + jittered_sec = + (map->cfg->map_timeout + g_random_double () * + map->cfg->map_timeout) / 2.; double_to_tv (jittered_sec, &map->tv); evtimer_add (&map->ev, &map->tv); } @@ -974,7 +1062,9 @@ start_map_watch (struct rspamd_config *cfg, struct event_base *ev_base) /* Read initial data */ read_http_sync (map, map->map_data); /* Plan event with jitter */ - jittered_sec = (map->cfg->map_timeout + g_random_double () * map->cfg->map_timeout); + jittered_sec = + (map->cfg->map_timeout + g_random_double () * + map->cfg->map_timeout); double_to_tv (jittered_sec, &map->tv); evtimer_add (&map->ev, &map->tv); } @@ -982,7 +1072,7 @@ start_map_watch (struct rspamd_config *cfg, struct event_base *ev_base) } } -void +void remove_all_maps (struct rspamd_config *cfg) { g_list_free (cfg->maps); @@ -996,13 +1086,15 @@ remove_all_maps (struct rspamd_config *cfg) gboolean check_map_proto (const gchar *map_line, gint *res, const gchar **pos) { - if (g_ascii_strncasecmp (map_line, "http://", sizeof ("http://") - 1) == 0) { + if (g_ascii_strncasecmp (map_line, "http://", + sizeof ("http://") - 1) == 0) { if (res && pos) { *res = MAP_PROTO_HTTP; *pos = map_line + sizeof ("http://") - 1; } } - else if (g_ascii_strncasecmp (map_line, "file://", sizeof ("file://") - 1) == 0) { + else if (g_ascii_strncasecmp (map_line, "file://", sizeof ("file://") - + 1) == 0) { if (res && pos) { *res = MAP_PROTO_FILE; *pos = map_line + sizeof ("file://") - 1; @@ -1022,17 +1114,21 @@ check_map_proto (const gchar *map_line, gint *res, const gchar **pos) } gboolean -add_map (struct rspamd_config *cfg, const gchar *map_line, const gchar *description, - map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data) +add_map (struct rspamd_config *cfg, + const gchar *map_line, + const gchar *description, + map_cb_t read_callback, + map_fin_cb_t fin_callback, + void **user_data) { - struct rspamd_map *new_map; - enum fetch_proto proto; - const gchar *def, *p, *hostend; - struct file_map_data *fdata; - struct http_map_data *hdata; - gchar portbuf[6]; - gint i, s, r; - struct addrinfo hints, *res; + struct rspamd_map *new_map; + enum fetch_proto proto; + const gchar *def, *p, *hostend; + struct file_map_data *fdata; + struct http_map_data *hdata; + gchar portbuf[6]; + gint i, s, r; + struct addrinfo hints, *res; /* First of all detect protocol line */ if (!check_map_proto (map_line, (int *)&proto, &def)) { @@ -1049,7 +1145,8 @@ add_map (struct rspamd_config *cfg, const gchar *map_line, const gchar *descript new_map->protocol = proto; new_map->cfg = cfg; new_map->id = g_random_int (); - new_map->locked = rspamd_mempool_alloc0_shared (cfg->cfg_pool, sizeof (gint)); + new_map->locked = + rspamd_mempool_alloc0_shared (cfg->cfg_pool, sizeof (gint)); if (proto == MAP_PROTO_FILE) { new_map->uri = rspamd_mempool_strdup (cfg->cfg_pool, def); @@ -1059,19 +1156,24 @@ add_map (struct rspamd_config *cfg, const gchar *map_line, const gchar *descript new_map->uri = rspamd_mempool_strdup (cfg->cfg_pool, map_line); } if (description != NULL) { - new_map->description = rspamd_mempool_strdup (cfg->cfg_pool, description); + new_map->description = + rspamd_mempool_strdup (cfg->cfg_pool, description); } /* Now check for each proto separately */ if (proto == MAP_PROTO_FILE) { - fdata = rspamd_mempool_alloc0 (cfg->map_pool, sizeof (struct file_map_data)); + fdata = + rspamd_mempool_alloc0 (cfg->map_pool, + sizeof (struct file_map_data)); if (access (def, R_OK) == -1) { if (errno != ENOENT) { msg_err ("cannot open file '%s': %s", def, strerror (errno)); return FALSE; } - msg_info ("map '%s' is not found, but it can be loaded automatically later", def); + msg_info ( + "map '%s' is not found, but it can be loaded automatically later", + def); /* We still can add this file */ fdata->st.st_mtime = -1; } @@ -1082,7 +1184,9 @@ add_map (struct rspamd_config *cfg, const gchar *map_line, const gchar *descript new_map->map_data = fdata; } else if (proto == MAP_PROTO_HTTP) { - hdata = rspamd_mempool_alloc0 (cfg->map_pool, sizeof (struct http_map_data)); + hdata = + rspamd_mempool_alloc0 (cfg->map_pool, + sizeof (struct http_map_data)); /* Try to search port */ if ((p = strchr (def, ':')) != NULL) { hostend = p; @@ -1125,15 +1229,21 @@ add_map (struct rspamd_config *cfg, const gchar *map_line, const gchar *descript if ((r = getaddrinfo (hdata->host, portbuf, &hints, &res)) == 0) { hdata->addr = res; - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)freeaddrinfo, hdata->addr); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)freeaddrinfo, hdata->addr); } else { - msg_err ("address resolution for %s failed: %s", hdata->host, gai_strerror (r)); + msg_err ("address resolution for %s failed: %s", + hdata->host, + gai_strerror (r)); return FALSE; } /* Now try to connect */ if ((s = make_tcp_socket (hdata->addr, FALSE, FALSE)) == -1) { - msg_info ("cannot connect to http server %s: %d, %s", hdata->host, errno, strerror (errno)); + msg_info ("cannot connect to http server %s: %d, %s", + hdata->host, + errno, + strerror (errno)); return FALSE; } close (s); diff --git a/src/libutil/map.h b/src/libutil/map.h index ddb9882e4..1b5c01f1e 100644 --- a/src/libutil/map.h +++ b/src/libutil/map.h @@ -34,7 +34,7 @@ struct http_map_data { gchar *host; time_t last_checked; gshort chunked; - gchar read_buf[BUFSIZ]; + gchar read_buf[BUFSIZ]; guint32 rlen; guint32 chunk; guint32 chunk_remain; @@ -45,7 +45,8 @@ struct map_cb_data; /** * Callback types */ -typedef gchar* (*map_cb_t)(rspamd_mempool_t *pool, gchar *chunk, gint len, struct map_cb_data *data); +typedef gchar * (*map_cb_t)(rspamd_mempool_t *pool, gchar *chunk, gint len, + struct map_cb_data *data); typedef void (*map_fin_cb_t)(rspamd_mempool_t *pool, struct map_cb_data *data); /** @@ -89,8 +90,12 @@ gboolean check_map_proto (const gchar *map_line, gint *res, const gchar **pos); /** * Add map from line */ -gboolean add_map (struct rspamd_config *cfg, const gchar *map_line, const gchar *description, - map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data); +gboolean add_map (struct rspamd_config *cfg, + const gchar *map_line, + const gchar *description, + map_cb_t read_callback, + map_fin_cb_t fin_callback, + void **user_data); /** * Start watching of maps by adding events to libevent event loop @@ -102,7 +107,8 @@ void start_map_watch (struct rspamd_config *cfg, struct event_base *ev_base); */ void remove_all_maps (struct rspamd_config *cfg); -typedef void (*insert_func) (gpointer st, gconstpointer key, gconstpointer value); +typedef void (*insert_func) (gpointer st, gconstpointer key, + gconstpointer value); /** * Common callbacks for frequent types of lists @@ -111,24 +117,37 @@ typedef void (*insert_func) (gpointer st, gconstpointer key, /** * Radix list is a list like ip/mask */ -gchar* read_radix_list (rspamd_mempool_t *pool, gchar *chunk, gint len, struct map_cb_data *data); +gchar * read_radix_list (rspamd_mempool_t *pool, + gchar *chunk, + gint len, + struct map_cb_data *data); void fin_radix_list (rspamd_mempool_t *pool, struct map_cb_data *data); /** * Host list is an ordinal list of hosts or domains */ -gchar* read_host_list (rspamd_mempool_t *pool, gchar *chunk, gint len, struct map_cb_data *data); +gchar * read_host_list (rspamd_mempool_t *pool, + gchar *chunk, + gint len, + struct map_cb_data *data); void fin_host_list (rspamd_mempool_t *pool, struct map_cb_data *data); /** * Kv list is an ordinal list of keys and values separated by whitespace */ -gchar* read_kv_list (rspamd_mempool_t *pool, gchar *chunk, gint len, struct map_cb_data *data); +gchar * read_kv_list (rspamd_mempool_t *pool, + gchar *chunk, + gint len, + struct map_cb_data *data); void fin_kv_list (rspamd_mempool_t *pool, struct map_cb_data *data); /** * FSM for lists parsing (support comments, blank lines and partial replies) */ -gchar * abstract_parse_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data, insert_func func); +gchar * abstract_parse_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data, + insert_func func); #endif diff --git a/src/libutil/mem_pool.c b/src/libutil/mem_pool.c index 6ace865a0..ddaa5cc85 100644 --- a/src/libutil/mem_pool.c +++ b/src/libutil/mem_pool.c @@ -34,7 +34,7 @@ #define MUTEX_SPIN_COUNT 100 #ifdef _THREAD_SAFE -pthread_mutex_t stat_mtx = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t stat_mtx = PTHREAD_MUTEX_INITIALIZER; # define STAT_LOCK() do { pthread_mutex_lock (&stat_mtx); } while (0) # define STAT_UNLOCK() do { pthread_mutex_unlock (&stat_mtx); } while (0) #else @@ -42,10 +42,10 @@ pthread_mutex_t stat_mtx = PTHREAD_MUTEX_INITIALIZER; # define STAT_UNLOCK() do {} while (0) #endif -#define POOL_MTX_LOCK() do { rspamd_mutex_lock (pool->mtx); } while (0) -#define POOL_MTX_UNLOCK() do { rspamd_mutex_unlock (pool->mtx); } while (0) +#define POOL_MTX_LOCK() do { rspamd_mutex_lock (pool->mtx); } while (0) +#define POOL_MTX_UNLOCK() do { rspamd_mutex_unlock (pool->mtx); } while (0) -/* +/* * This define specify whether we should check all pools for free space for new object * or just begin scan from current (recently attached) pool * If MEMORY_GREEDY is defined, then we scan all pools to find free space (more CPU usage, slower @@ -56,7 +56,7 @@ pthread_mutex_t stat_mtx = PTHREAD_MUTEX_INITIALIZER; #undef MEMORY_GREEDY /* Internal statistic */ -static rspamd_mempool_stat_t *mem_pool_stat = NULL; +static rspamd_mempool_stat_t *mem_pool_stat = NULL; /** * Function that return free space in pool page @@ -68,17 +68,18 @@ pool_chain_free (struct _pool_chain *chain) return (gint)chain->len - (chain->pos - chain->begin + MEM_ALIGNMENT); } -static struct _pool_chain * +static struct _pool_chain * pool_chain_new (gsize size) { - struct _pool_chain *chain; + struct _pool_chain *chain; g_return_val_if_fail (size > 0, NULL); chain = g_slice_alloc (sizeof (struct _pool_chain)); if (chain == NULL) { - msg_err ("cannot allocate %z bytes, aborting", sizeof (struct _pool_chain)); + msg_err ("cannot allocate %z bytes, aborting", + sizeof (struct _pool_chain)); abort (); } @@ -102,34 +103,46 @@ pool_chain_new (gsize size) static struct _pool_chain_shared * pool_chain_new_shared (gsize size) { - struct _pool_chain_shared *chain; - gpointer map; + struct _pool_chain_shared *chain; + gpointer map; #if defined(HAVE_MMAP_ANON) - map = mmap (NULL, size + sizeof (struct _pool_chain_shared), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0); + map = mmap (NULL, + size + sizeof (struct _pool_chain_shared), + PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, + -1, + 0); if (map == MAP_FAILED) { - msg_err ("cannot allocate %z bytes, aborting", size + sizeof (struct _pool_chain)); + msg_err ("cannot allocate %z bytes, aborting", size + + sizeof (struct _pool_chain)); abort (); } chain = (struct _pool_chain_shared *)map; chain->begin = ((guint8 *) chain) + sizeof (struct _pool_chain_shared); #elif defined(HAVE_MMAP_ZERO) - gint fd; + gint fd; fd = open ("/dev/zero", O_RDWR); if (fd == -1) { return NULL; } - map = mmap (NULL, size + sizeof (struct _pool_chain_shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + map = mmap (NULL, + size + sizeof (struct _pool_chain_shared), + PROT_READ | PROT_WRITE, + MAP_SHARED, + fd, + 0); if (map == MAP_FAILED) { - msg_err ("cannot allocate %z bytes, aborting", size + sizeof (struct _pool_chain)); + msg_err ("cannot allocate %z bytes, aborting", size + + sizeof (struct _pool_chain)); abort (); } chain = (struct _pool_chain_shared *)map; chain->begin = ((guint8 *) chain) + sizeof (struct _pool_chain_shared); #else -# error No mmap methods are defined +# error No mmap methods are defined #endif chain->pos = align_ptr (chain->begin, MEM_ALIGNMENT); chain->len = size; @@ -145,46 +158,59 @@ pool_chain_new_shared (gsize size) /** - * Allocate new memory poll + * Allocate new memory poll * @param size size of pool's page * @return new memory pool object */ -rspamd_mempool_t * +rspamd_mempool_t * rspamd_mempool_new (gsize size) { - rspamd_mempool_t *new; - gpointer map; + rspamd_mempool_t *new; + gpointer map; g_return_val_if_fail (size > 0, NULL); /* Allocate statistic structure if it is not allocated before */ if (mem_pool_stat == NULL) { #if defined(HAVE_MMAP_ANON) - map = mmap (NULL, sizeof (rspamd_mempool_stat_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0); + map = mmap (NULL, + sizeof (rspamd_mempool_stat_t), + PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, + -1, + 0); if (map == MAP_FAILED) { - msg_err ("cannot allocate %z bytes, aborting", sizeof (rspamd_mempool_stat_t)); + msg_err ("cannot allocate %z bytes, aborting", + sizeof (rspamd_mempool_stat_t)); abort (); } mem_pool_stat = (rspamd_mempool_stat_t *)map; #elif defined(HAVE_MMAP_ZERO) - gint fd; + gint fd; fd = open ("/dev/zero", O_RDWR); g_assert (fd != -1); - map = mmap (NULL, sizeof (rspamd_mempool_stat_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + map = mmap (NULL, + sizeof (rspamd_mempool_stat_t), + PROT_READ | PROT_WRITE, + MAP_SHARED, + fd, + 0); if (map == MAP_FAILED) { - msg_err ("cannot allocate %z bytes, aborting", sizeof (rspamd_mempool_stat_t)); + msg_err ("cannot allocate %z bytes, aborting", + sizeof (rspamd_mempool_stat_t)); abort (); } mem_pool_stat = (rspamd_mempool_stat_t *)map; #else -# error No mmap methods are defined +# error No mmap methods are defined #endif memset (map, 0, sizeof (rspamd_mempool_stat_t)); } new = g_slice_alloc (sizeof (rspamd_mempool_t)); if (new == NULL) { - msg_err ("cannot allocate %z bytes, aborting", sizeof (rspamd_mempool_t)); + msg_err ("cannot allocate %z bytes, aborting", + sizeof (rspamd_mempool_t)); abort (); } @@ -203,12 +229,12 @@ rspamd_mempool_new (gsize size) return new; } -static void * +static void * memory_pool_alloc_common (rspamd_mempool_t * pool, gsize size, gboolean is_tmp) { - guint8 *tmp; - struct _pool_chain *new, *cur; - gint free; + guint8 *tmp; + struct _pool_chain *new, *cur; + gint free; if (pool) { POOL_MTX_LOCK (); @@ -229,8 +255,8 @@ memory_pool_alloc_common (rspamd_mempool_t * pool, gsize size, gboolean is_tmp) #endif /* Find free space in pool chain */ while (cur != NULL && - (free = pool_chain_free (cur)) < (gint)size && - cur->next != NULL) { + (free = pool_chain_free (cur)) < (gint)size && + cur->next != NULL) { cur = cur->next; } @@ -241,7 +267,8 @@ memory_pool_alloc_common (rspamd_mempool_t * pool, gsize size, gboolean is_tmp) new = pool_chain_new (pool->first_pool->len); } else { - new = pool_chain_new (size + pool->first_pool->len + MEM_ALIGNMENT); + new = pool_chain_new ( + size + pool->first_pool->len + MEM_ALIGNMENT); } /* Connect to pool subsystem */ if (is_tmp) { @@ -257,7 +284,8 @@ memory_pool_alloc_common (rspamd_mempool_t * pool, gsize size, gboolean is_tmp) } else { mem_pool_stat->oversized_chunks++; - new = pool_chain_new (size + pool->first_pool->len + MEM_ALIGNMENT); + new = pool_chain_new ( + size + pool->first_pool->len + MEM_ALIGNMENT); } /* Attach new pool to chain */ cur->next = new; @@ -284,42 +312,42 @@ memory_pool_alloc_common (rspamd_mempool_t * pool, gsize size, gboolean is_tmp) } -void * +void * rspamd_mempool_alloc (rspamd_mempool_t * pool, gsize size) { return memory_pool_alloc_common (pool, size, FALSE); } -void * +void * rspamd_mempool_alloc_tmp (rspamd_mempool_t * pool, gsize size) { return memory_pool_alloc_common (pool, size, TRUE); } -void * +void * rspamd_mempool_alloc0 (rspamd_mempool_t * pool, gsize size) { - void *pointer = rspamd_mempool_alloc (pool, size); + void *pointer = rspamd_mempool_alloc (pool, size); if (pointer) { memset (pointer, 0, size); } return pointer; } -void * +void * rspamd_mempool_alloc0_tmp (rspamd_mempool_t * pool, gsize size) { - void *pointer = rspamd_mempool_alloc_tmp (pool, size); + void *pointer = rspamd_mempool_alloc_tmp (pool, size); if (pointer) { memset (pointer, 0, size); } return pointer; } -void * +void * rspamd_mempool_alloc0_shared (rspamd_mempool_t * pool, gsize size) { - void *pointer = rspamd_mempool_alloc_shared (pool, size); + void *pointer = rspamd_mempool_alloc_shared (pool, size); if (pointer) { memset (pointer, 0, size); } @@ -334,7 +362,7 @@ rspamd_mempool_alloc_shared (rspamd_mempool_t * pool, gsize size) gint free; if (pool) { - g_return_val_if_fail(size > 0, NULL); + g_return_val_if_fail (size > 0, NULL); POOL_MTX_LOCK () ; @@ -346,7 +374,7 @@ rspamd_mempool_alloc_shared (rspamd_mempool_t * pool, gsize size) /* Find free space in pool chain */ while ((free = pool_chain_free ((struct _pool_chain *) cur)) - < (gint) size && cur->next) { + < (gint) size && cur->next) { cur = cur->next; } if (free < (gint) size && cur->next == NULL) { @@ -358,7 +386,7 @@ rspamd_mempool_alloc_shared (rspamd_mempool_t * pool, gsize size) else { mem_pool_stat->oversized_chunks++; new = pool_chain_new_shared ( - size + pool->first_pool->len + MEM_ALIGNMENT); + size + pool->first_pool->len + MEM_ALIGNMENT); } /* Attach new pool to chain */ cur->next = new; @@ -370,7 +398,7 @@ rspamd_mempool_alloc_shared (rspamd_mempool_t * pool, gsize size) ; return new->begin; } - tmp = align_ptr(cur->pos, MEM_ALIGNMENT); + tmp = align_ptr (cur->pos, MEM_ALIGNMENT); cur->pos = tmp + size; POOL_MTX_UNLOCK () ; @@ -380,11 +408,11 @@ rspamd_mempool_alloc_shared (rspamd_mempool_t * pool, gsize size) } -gchar * +gchar * rspamd_mempool_strdup (rspamd_mempool_t * pool, const gchar *src) { - gsize len; - gchar *newstr; + gsize len; + gchar *newstr; if (src == NULL) { return NULL; @@ -397,10 +425,10 @@ rspamd_mempool_strdup (rspamd_mempool_t * pool, const gchar *src) return newstr; } -gchar * +gchar * rspamd_mempool_fstrdup (rspamd_mempool_t * pool, const struct f_str_s *src) { - gchar *newstr; + gchar *newstr; if (src == NULL) { return NULL; @@ -413,11 +441,11 @@ rspamd_mempool_fstrdup (rspamd_mempool_t * pool, const struct f_str_s *src) } -gchar * +gchar * rspamd_mempool_strdup_shared (rspamd_mempool_t * pool, const gchar *src) { - gsize len; - gchar *newstr; + gsize len; + gchar *newstr; if (src == NULL) { return NULL; @@ -434,10 +462,11 @@ rspamd_mempool_strdup_shared (rspamd_mempool_t * pool, const gchar *src) static struct _pool_chain_shared * memory_pool_find_pool (rspamd_mempool_t * pool, void *pointer) { - struct _pool_chain_shared *cur = pool->shared_pool; + struct _pool_chain_shared *cur = pool->shared_pool; while (cur) { - if ((guint8 *) pointer >= cur->begin && (guint8 *) pointer <= (cur->begin + cur->len)) { + if ((guint8 *) pointer >= cur->begin && (guint8 *) pointer <= + (cur->begin + cur->len)) { return cur; } cur = cur->next; @@ -466,19 +495,19 @@ __mutex_spin (rspamd_mempool_mutex_t * mutex) g_atomic_int_set (&mutex->spin, MUTEX_SPIN_COUNT); } #ifdef HAVE_ASM_PAUSE - __asm __volatile ("pause"); + __asm __volatile ("pause"); #elif defined(HAVE_SCHED_YIELD) (void)sched_yield (); #endif #if defined(HAVE_NANOSLEEP) - struct timespec ts; + struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = MUTEX_SLEEP_TIME; /* Spin */ - while (nanosleep (&ts, &ts) == -1 && errno == EINTR); + while (nanosleep (&ts, &ts) == -1 && errno == EINTR) ; #else -# error No methods to spin are defined +# error No methods to spin are defined #endif return 1; } @@ -497,7 +526,7 @@ memory_pool_mutex_spin (rspamd_mempool_mutex_t * mutex) void rspamd_mempool_lock_shared (rspamd_mempool_t * pool, void *pointer) { - struct _pool_chain_shared *chain; + struct _pool_chain_shared *chain; chain = memory_pool_find_pool (pool, pointer); if (chain == NULL) { @@ -512,7 +541,7 @@ rspamd_mempool_lock_shared (rspamd_mempool_t * pool, void *pointer) void rspamd_mempool_unlock_shared (rspamd_mempool_t * pool, void *pointer) { - struct _pool_chain_shared *chain; + struct _pool_chain_shared *chain; chain = memory_pool_find_pool (pool, pointer); if (chain == NULL) { @@ -527,10 +556,13 @@ rspamd_mempool_unlock_shared (rspamd_mempool_t * pool, void *pointer) } void -rspamd_mempool_add_destructor_full (rspamd_mempool_t * pool, rspamd_mempool_destruct_t func, void *data, - const gchar *function, const gchar *line) +rspamd_mempool_add_destructor_full (rspamd_mempool_t * pool, + rspamd_mempool_destruct_t func, + void *data, + const gchar *function, + const gchar *line) { - struct _pool_destructors *cur; + struct _pool_destructors *cur; cur = rspamd_mempool_alloc (pool, sizeof (struct _pool_destructors)); if (cur) { @@ -546,9 +578,12 @@ rspamd_mempool_add_destructor_full (rspamd_mempool_t * pool, rspamd_mempool_dest } void -rspamd_mempool_replace_destructor (rspamd_mempool_t * pool, rspamd_mempool_destruct_t func, void *old_data, void *new_data) +rspamd_mempool_replace_destructor (rspamd_mempool_t * pool, + rspamd_mempool_destruct_t func, + void *old_data, + void *new_data) { - struct _pool_destructors *tmp; + struct _pool_destructors *tmp; tmp = pool->destructors; while (tmp) { @@ -565,9 +600,9 @@ rspamd_mempool_replace_destructor (rspamd_mempool_t * pool, rspamd_mempool_destr void rspamd_mempool_delete (rspamd_mempool_t * pool) { - struct _pool_chain *cur = pool->first_pool, *tmp; - struct _pool_chain_shared *cur_shared = pool->shared_pool, *tmp_shared; - struct _pool_destructors *destructor = pool->destructors; + struct _pool_chain *cur = pool->first_pool, *tmp; + struct _pool_chain_shared *cur_shared = pool->shared_pool, *tmp_shared; + struct _pool_destructors *destructor = pool->destructors; POOL_MTX_LOCK (); /* Call all pool destructors */ @@ -609,7 +644,8 @@ rspamd_mempool_delete (rspamd_mempool_t * pool) mem_pool_stat->chunks_freed++; mem_pool_stat->bytes_allocated -= tmp_shared->len; STAT_UNLOCK (); - munmap ((void *)tmp_shared, tmp_shared->len + sizeof (struct _pool_chain_shared)); + munmap ((void *)tmp_shared, tmp_shared->len + + sizeof (struct _pool_chain_shared)); } if (pool->variables) { g_hash_table_destroy (pool->variables); @@ -622,9 +658,9 @@ rspamd_mempool_delete (rspamd_mempool_t * pool) } void -rspamd_mempool_cleanup_tmp (rspamd_mempool_t* pool) +rspamd_mempool_cleanup_tmp (rspamd_mempool_t * pool) { - struct _pool_chain *cur = pool->first_pool, *tmp; + struct _pool_chain *cur = pool->first_pool, *tmp; POOL_MTX_LOCK (); cur = pool->first_pool_tmp; @@ -677,12 +713,13 @@ rspamd_mempool_suggest_size (void) #endif } -rspamd_mempool_mutex_t * +rspamd_mempool_mutex_t * rspamd_mempool_get_mutex (rspamd_mempool_t * pool) { - rspamd_mempool_mutex_t *res; + rspamd_mempool_mutex_t *res; if (pool != NULL) { - res = rspamd_mempool_alloc_shared (pool, sizeof (rspamd_mempool_mutex_t)); + res = + rspamd_mempool_alloc_shared (pool, sizeof (rspamd_mempool_mutex_t)); res->lock = 0; res->owner = 0; res->spin = MUTEX_SPIN_COUNT; @@ -705,10 +742,10 @@ rspamd_mempool_unlock_mutex (rspamd_mempool_mutex_t * mutex) (void)g_atomic_int_compare_and_exchange (&mutex->lock, 1, 0); } -rspamd_mempool_rwlock_t * +rspamd_mempool_rwlock_t * rspamd_mempool_get_rwlock (rspamd_mempool_t * pool) { - rspamd_mempool_rwlock_t *lock; + rspamd_mempool_rwlock_t *lock; lock = rspamd_mempool_alloc_shared (pool, sizeof (rspamd_mempool_rwlock_t)); lock->__r_lock = rspamd_mempool_get_mutex (pool); @@ -757,14 +794,18 @@ rspamd_mempool_wunlock_rwlock (rspamd_mempool_rwlock_t * lock) rspamd_mempool_unlock_mutex (lock->__w_lock); } -void -rspamd_mempool_set_variable (rspamd_mempool_t *pool, const gchar *name, gpointer value, rspamd_mempool_destruct_t destructor) +void +rspamd_mempool_set_variable (rspamd_mempool_t *pool, + const gchar *name, + gpointer value, + rspamd_mempool_destruct_t destructor) { if (pool->variables == NULL) { pool->variables = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); } - g_hash_table_insert (pool->variables, rspamd_mempool_strdup (pool, name), value); + g_hash_table_insert (pool->variables, rspamd_mempool_strdup (pool, + name), value); if (destructor != NULL) { rspamd_mempool_add_destructor (pool, destructor, value); } diff --git a/src/libutil/mem_pool.h b/src/libutil/mem_pool.h index 17edf2fb2..2a8546ef0 100644 --- a/src/libutil/mem_pool.h +++ b/src/libutil/mem_pool.h @@ -19,10 +19,10 @@ struct f_str_s; #define MEM_ALIGNMENT sizeof(unsigned long) /* platform word */ #define align_ptr(p, a) \ - (guint8 *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1)) + (guint8 *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1)) -/** - * Destructor type definition +/** + * Destructor type definition */ typedef void (*rspamd_mempool_destruct_t)(void *ptr); @@ -39,10 +39,10 @@ typedef struct memory_pool_mutex_s { * Pool page structure */ struct _pool_chain { - guint8 *begin; /**< begin of pool chain block */ - guint8 *pos; /**< current start of free space in block */ - gsize len; /**< length of block */ - struct _pool_chain *next; /**< chain link */ + guint8 *begin; /**< begin of pool chain block */ + guint8 *pos; /**< current start of free space in block */ + gsize len; /**< length of block */ + struct _pool_chain *next; /**< chain link */ }; /** @@ -60,11 +60,11 @@ struct _pool_chain_shared { * Destructors list item structure */ struct _pool_destructors { - rspamd_mempool_destruct_t func; /**< pointer to destructor */ - void *data; /**< data to free */ - const gchar *function; /**< function from which this destructor was added */ - const gchar *loc; /**< line number */ - struct _pool_destructors *prev; /**< chain link */ + rspamd_mempool_destruct_t func; /**< pointer to destructor */ + void *data; /**< data to free */ + const gchar *function; /**< function from which this destructor was added */ + const gchar *loc; /**< line number */ + struct _pool_destructors *prev; /**< chain link */ }; /** @@ -72,51 +72,51 @@ struct _pool_destructors { */ struct rspamd_mutex_s; typedef struct memory_pool_s { - struct _pool_chain *cur_pool; /**< currently used page */ - struct _pool_chain *first_pool; /**< first page */ - struct _pool_chain *cur_pool_tmp; /**< currently used temporary page */ - struct _pool_chain *first_pool_tmp; /**< first temporary page */ - struct _pool_chain_shared *shared_pool; /**< shared chain */ - struct _pool_destructors *destructors; /**< destructors chain */ - GHashTable *variables; /**< private memory pool variables */ - struct rspamd_mutex_s *mtx; /**< threads lock */ + struct _pool_chain *cur_pool; /**< currently used page */ + struct _pool_chain *first_pool; /**< first page */ + struct _pool_chain *cur_pool_tmp; /**< currently used temporary page */ + struct _pool_chain *first_pool_tmp; /**< first temporary page */ + struct _pool_chain_shared *shared_pool; /**< shared chain */ + struct _pool_destructors *destructors; /**< destructors chain */ + GHashTable *variables; /**< private memory pool variables */ + struct rspamd_mutex_s *mtx; /**< threads lock */ } rspamd_mempool_t; /** * Statistics structure */ typedef struct memory_pool_stat_s { - gsize pools_allocated; /**< total number of allocated pools */ - gsize pools_freed; /**< number of freed pools */ - gsize bytes_allocated; /**< bytes that are allocated with pool allocator */ - gsize chunks_allocated; /**< number of chunks that are allocated */ - gsize shared_chunks_allocated; /**< shared chunks allocated */ - gsize chunks_freed; /**< chunks freed */ - gsize oversized_chunks; /**< oversized chunks */ + gsize pools_allocated; /**< total number of allocated pools */ + gsize pools_freed; /**< number of freed pools */ + gsize bytes_allocated; /**< bytes that are allocated with pool allocator */ + gsize chunks_allocated; /**< number of chunks that are allocated */ + gsize shared_chunks_allocated; /**< shared chunks allocated */ + gsize chunks_freed; /**< chunks freed */ + gsize oversized_chunks; /**< oversized chunks */ } rspamd_mempool_stat_t; /** * Rwlock for locking shared memory regions */ typedef struct memory_pool_rwlock_s { - rspamd_mempool_mutex_t *__r_lock; /**< read mutex (private) */ - rspamd_mempool_mutex_t *__w_lock; /**< write mutex (private) */ + rspamd_mempool_mutex_t *__r_lock; /**< read mutex (private) */ + rspamd_mempool_mutex_t *__w_lock; /**< write mutex (private) */ } rspamd_mempool_rwlock_t; /** - * Allocate new memory poll + * Allocate new memory poll * @param size size of pool's page * @return new memory pool object */ -rspamd_mempool_t* rspamd_mempool_new (gsize size); +rspamd_mempool_t * rspamd_mempool_new (gsize size); -/** +/** * Get memory from pool * @param pool memory pool object * @param size bytes to allocate * @return pointer to allocated object */ -void* rspamd_mempool_alloc (rspamd_mempool_t* pool, gsize size); +void * rspamd_mempool_alloc (rspamd_mempool_t * pool, gsize size); /** * Get memory from temporary pool @@ -124,7 +124,7 @@ void* rspamd_mempool_alloc (rspamd_mempool_t* pool, gsize size); * @param size bytes to allocate * @return pointer to allocated object */ -void* rspamd_mempool_alloc_tmp (rspamd_mempool_t* pool, gsize size); +void * rspamd_mempool_alloc_tmp (rspamd_mempool_t * pool, gsize size); /** * Get memory and set it to zero @@ -132,7 +132,7 @@ void* rspamd_mempool_alloc_tmp (rspamd_mempool_t* pool, gsize size); * @param size bytes to allocate * @return pointer to allocated object */ -void* rspamd_mempool_alloc0 (rspamd_mempool_t* pool, gsize size); +void * rspamd_mempool_alloc0 (rspamd_mempool_t * pool, gsize size); /** * Get memory and set it to zero @@ -140,12 +140,12 @@ void* rspamd_mempool_alloc0 (rspamd_mempool_t* pool, gsize size); * @param size bytes to allocate * @return pointer to allocated object */ -void* rspamd_mempool_alloc0_tmp (rspamd_mempool_t* pool, gsize size); +void * rspamd_mempool_alloc0_tmp (rspamd_mempool_t * pool, gsize size); /** * Cleanup temporary data in pool */ -void rspamd_mempool_cleanup_tmp (rspamd_mempool_t* pool); +void rspamd_mempool_cleanup_tmp (rspamd_mempool_t * pool); /** * Make a copy of string in pool @@ -153,7 +153,7 @@ void rspamd_mempool_cleanup_tmp (rspamd_mempool_t* pool); * @param src source string * @return pointer to newly created string that is copy of src */ -gchar* rspamd_mempool_strdup (rspamd_mempool_t* pool, const gchar *src); +gchar * rspamd_mempool_strdup (rspamd_mempool_t * pool, const gchar *src); /** * Make a copy of fixed string in pool as null terminated string @@ -161,16 +161,18 @@ gchar* rspamd_mempool_strdup (rspamd_mempool_t* pool, const gchar *src); * @param src source string * @return pointer to newly created string that is copy of src */ -gchar* rspamd_mempool_fstrdup (rspamd_mempool_t* pool, const struct f_str_s *src); +gchar * rspamd_mempool_fstrdup (rspamd_mempool_t * pool, + const struct f_str_s *src); /** * Allocate piece of shared memory * @param pool memory pool object * @param size bytes to allocate */ -void* rspamd_mempool_alloc_shared (rspamd_mempool_t* pool, gsize size); -void* rspamd_mempool_alloc0_shared (rspamd_mempool_t *pool, gsize size); -gchar* rspamd_mempool_strdup_shared (rspamd_mempool_t* pool, const gchar *src); +void * rspamd_mempool_alloc_shared (rspamd_mempool_t * pool, gsize size); +void * rspamd_mempool_alloc0_shared (rspamd_mempool_t *pool, gsize size); +gchar * rspamd_mempool_strdup_shared (rspamd_mempool_t * pool, + const gchar *src); /** * Lock chunk of shared memory in which pointer is placed @@ -192,12 +194,15 @@ void rspamd_mempool_lock_shared (rspamd_mempool_t *pool, void *pointer); * @param func pointer to function-destructor * @param data pointer to data that would be passed to destructor */ -void rspamd_mempool_add_destructor_full (rspamd_mempool_t *pool, rspamd_mempool_destruct_t func, void *data, - const gchar *function, const gchar *line); +void rspamd_mempool_add_destructor_full (rspamd_mempool_t *pool, + rspamd_mempool_destruct_t func, + void *data, + const gchar *function, + const gchar *line); /* Macros for common usage */ #define rspamd_mempool_add_destructor(pool, func, data) \ - rspamd_mempool_add_destructor_full(pool, func, data, G_STRFUNC, G_STRLOC) + rspamd_mempool_add_destructor_full (pool, func, data, G_STRFUNC, G_STRLOC) /** * Replace destructor callback to pool for specified pointer @@ -207,7 +212,7 @@ void rspamd_mempool_add_destructor_full (rspamd_mempool_t *pool, rspamd_mempool_ * @param new_data pointer to data that would be passed to destructor */ void rspamd_mempool_replace_destructor (rspamd_mempool_t *pool, - rspamd_mempool_destruct_t func, void *old_data, void *new_data); + rspamd_mempool_destruct_t func, void *old_data, void *new_data); /** * Delete pool, free all its chunks and call destructors chain @@ -215,12 +220,12 @@ void rspamd_mempool_replace_destructor (rspamd_mempool_t *pool, */ void rspamd_mempool_delete (rspamd_mempool_t *pool); -/** +/** * Get new mutex from pool (allocated in shared memory) * @param pool memory pool object * @return mutex object */ -rspamd_mempool_mutex_t* rspamd_mempool_get_mutex (rspamd_mempool_t *pool); +rspamd_mempool_mutex_t * rspamd_mempool_get_mutex (rspamd_mempool_t *pool); /** * Lock mutex @@ -239,7 +244,7 @@ void rspamd_mempool_unlock_mutex (rspamd_mempool_mutex_t *mutex); * @param pool memory pool object * @return rwlock object */ -rspamd_mempool_rwlock_t* rspamd_mempool_get_rwlock (rspamd_mempool_t *pool); +rspamd_mempool_rwlock_t * rspamd_mempool_get_rwlock (rspamd_mempool_t *pool); /** * Aquire read lock @@ -290,7 +295,7 @@ gsize rspamd_mempool_suggest_size (void); * @param destructor pointer to function-destructor */ void rspamd_mempool_set_variable (rspamd_mempool_t *pool, const gchar *name, - gpointer value, rspamd_mempool_destruct_t destructor); + gpointer value, rspamd_mempool_destruct_t destructor); /** * Get memory pool variable @@ -298,7 +303,8 @@ void rspamd_mempool_set_variable (rspamd_mempool_t *pool, const gchar *name, * @param name name of variable * @return NULL or pointer to variable data */ -gpointer rspamd_mempool_get_variable (rspamd_mempool_t *pool, const gchar *name); +gpointer rspamd_mempool_get_variable (rspamd_mempool_t *pool, + const gchar *name); #endif diff --git a/src/libutil/printf.c b/src/libutil/printf.c index ba30587fc..2c339d094 100644 --- a/src/libutil/printf.c +++ b/src/libutil/printf.c @@ -90,13 +90,13 @@ rspamd_humanize_number (gchar *buf, gchar *last, gint64 num, gboolean bytes) static gchar * rspamd_sprintf_num (gchar *buf, gchar *last, guint64 ui64, gchar zero, - guint hexadecimal, guint width) + guint hexadecimal, guint width) { - gchar *p, temp[sizeof ("18446744073709551615")]; - size_t len; - guint32 ui32; - static gchar hex[] = "0123456789abcdef"; - static gchar HEX[] = "0123456789ABCDEF"; + gchar *p, temp[sizeof ("18446744073709551615")]; + size_t len; + guint32 ui32; + static gchar hex[] = "0123456789abcdef"; + static gchar HEX[] = "0123456789ABCDEF"; p = temp + sizeof(temp); @@ -220,7 +220,7 @@ rspamd_printf_append_gstring (const gchar *buf, glong buflen, gpointer ud) glong rspamd_fprintf (FILE *f, const gchar *fmt, ...) { - va_list args; + va_list args; glong r; va_start (args, fmt); @@ -233,7 +233,7 @@ rspamd_fprintf (FILE *f, const gchar *fmt, ...) glong rspamd_printf (const gchar *fmt, ...) { - va_list args; + va_list args; glong r; va_start (args, fmt); @@ -246,7 +246,7 @@ rspamd_printf (const gchar *fmt, ...) glong rspamd_log_fprintf (FILE *f, const gchar *fmt, ...) { - va_list args; + va_list args; glong r; va_start (args, fmt); @@ -299,31 +299,34 @@ rspamd_printf_gstring (GString *s, const gchar *fmt, ...) return r; } -#define RSPAMD_PRINTF_APPEND(buf, len) \ - do { \ - wr = func ((buf), (len), apd); \ - if (wr < (__typeof(wr))(len)) { \ - goto oob; \ - } \ - written += wr; \ - fmt ++; \ - buf_start = fmt; \ - } while(0) +#define RSPAMD_PRINTF_APPEND(buf, len) \ + do { \ + wr = func ((buf), (len), apd); \ + if (wr < (__typeof (wr))(len)) { \ + goto oob; \ + } \ + written += wr; \ + fmt++; \ + buf_start = fmt; \ + } while (0) glong -rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar *fmt, va_list args) +rspamd_vprintf_common (rspamd_printf_append_func func, + gpointer apd, + const gchar *fmt, + va_list args) { - gchar zero, numbuf[G_ASCII_DTOSTR_BUF_SIZE], *p, *last, c; - const gchar *buf_start = fmt; - gint d; - long double f, scale; - glong written = 0, wr, slen; - gint64 i64; - guint64 ui64; - guint width, sign, hex, humanize, bytes, frac_width, i; - f_str_t *v; - GString *gs; - gboolean bv; + gchar zero, numbuf[G_ASCII_DTOSTR_BUF_SIZE], *p, *last, c; + const gchar *buf_start = fmt; + gint d; + long double f, scale; + glong written = 0, wr, slen; + gint64 i64; + guint64 ui64; + guint width, sign, hex, humanize, bytes, frac_width, i; + f_str_t *v; + GString *gs; + gboolean bv; while (*fmt) { @@ -360,7 +363,7 @@ rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar } - for ( ;; ) { + for (;; ) { switch (*fmt) { case 'u': @@ -387,12 +390,12 @@ rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar humanize = 1; bytes = 1; sign = 0; - fmt ++; + fmt++; continue; case 'h': humanize = 1; sign = 0; - fmt ++; + fmt++; continue; case '.': fmt++; @@ -482,17 +485,17 @@ rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar case 'l': if (sign) { - i64 = (gint64) va_arg(args, glong); + i64 = (gint64) va_arg (args, glong); } else { - ui64 = (guint64) va_arg(args, gulong); + ui64 = (guint64) va_arg (args, gulong); } break; case 'D': if (sign) { - i64 = (gint64) va_arg(args, gint32); + i64 = (gint64) va_arg (args, gint32); } else { - ui64 = (guint64) va_arg(args, guint32); + ui64 = (guint64) va_arg (args, guint32); } break; @@ -540,9 +543,9 @@ rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar } /* - * (gint64) cast is required for msvc6: - * it can not convert guint64 to double - */ + * (gint64) cast is required for msvc6: + * it can not convert guint64 to double + */ ui64 = (guint64) ((f - (gint64) ui64) * scale); p = rspamd_sprintf_num (p, last, ui64, '0', 0, frac_width); @@ -620,7 +623,7 @@ rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar if (sign) { if (i64 < 0) { *p++ = '-'; - ui64 = (guint64) -i64; + ui64 = (guint64) - i64; } else { ui64 = (guint64) i64; diff --git a/src/libutil/printf.h b/src/libutil/printf.h index bd5c62cb6..aee982e41 100644 --- a/src/libutil/printf.h +++ b/src/libutil/printf.h @@ -62,15 +62,20 @@ * @param ud opaque pointer * @return number of characters written */ -typedef glong (*rspamd_printf_append_func)(const gchar *buf, glong buflen, gpointer ud); +typedef glong (*rspamd_printf_append_func)(const gchar *buf, glong buflen, + gpointer ud); glong rspamd_fprintf (FILE *f, const gchar *fmt, ...); glong rspamd_printf (const gchar *fmt, ...); glong rspamd_log_fprintf (FILE *f, const gchar *fmt, ...); glong rspamd_snprintf (gchar *buf, glong max, const gchar *fmt, ...); -gchar *rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args); +gchar * rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, + va_list args); glong rspamd_printf_gstring (GString *s, const gchar *fmt, ...); -glong rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar *fmt, va_list args); +glong rspamd_vprintf_common (rspamd_printf_append_func func, + gpointer apd, + const gchar *fmt, + va_list args); #endif /* PRINTF_H_ */ diff --git a/src/libutil/radix.c b/src/libutil/radix.c index 7af665331..3cef2b6e4 100644 --- a/src/libutil/radix.c +++ b/src/libutil/radix.c @@ -27,12 +27,12 @@ #include "radix.h" #include "mem_pool.h" -static void *radix_alloc (radix_tree_t * tree); +static void * radix_alloc (radix_tree_t * tree); -radix_tree_t * +radix_tree_t * radix_tree_create (void) { - radix_tree_t *tree; + radix_tree_t *tree; tree = g_malloc (sizeof (radix_tree_t)); if (tree == NULL) { @@ -62,10 +62,14 @@ enum radix_insert_type { }; static uintptr_t -radix32tree_insert_common (radix_tree_t * tree, guint32 key, guint32 mask, uintptr_t value, enum radix_insert_type type) +radix32tree_insert_common (radix_tree_t * tree, + guint32 key, + guint32 mask, + uintptr_t value, + enum radix_insert_type type) { - guint32 bit; - radix_node_t *node, *next; + guint32 bit; + radix_node_t *node, *next; bit = 0x80000000; @@ -92,14 +96,14 @@ radix32tree_insert_common (radix_tree_t * tree, guint32 key, guint32 mask, uintp if (node->value != RADIX_NO_VALUE) { /* Value was found, switch on insert type */ switch (type) { - case RADIX_INSERT: - return 1; - case RADIX_ADD: - node->value += value; - return value; - case RADIX_REPLACE: - node->value = value; - return 1; + case RADIX_INSERT: + return 1; + case RADIX_ADD: + node->value += value; + return value; + case RADIX_REPLACE: + node->value = value; + return 1; } } @@ -137,22 +141,33 @@ radix32tree_insert_common (radix_tree_t * tree, guint32 key, guint32 mask, uintp return 0; } -gint -radix32tree_insert (radix_tree_t *tree, guint32 key, guint32 mask, uintptr_t value) +gint +radix32tree_insert (radix_tree_t *tree, + guint32 key, + guint32 mask, + uintptr_t value) { - return (gint)radix32tree_insert_common (tree, key, mask, value, RADIX_INSERT); + return (gint)radix32tree_insert_common (tree, key, mask, value, + RADIX_INSERT); } -uintptr_t +uintptr_t radix32tree_add (radix_tree_t *tree, guint32 key, guint32 mask, uintptr_t value) { return radix32tree_insert_common (tree, key, mask, value, RADIX_ADD); } -gint -radix32tree_replace (radix_tree_t *tree, guint32 key, guint32 mask, uintptr_t value) +gint +radix32tree_replace (radix_tree_t *tree, + guint32 key, + guint32 mask, + uintptr_t value) { - return (gint)radix32tree_insert_common (tree, key, mask, value, RADIX_REPLACE); + return (gint)radix32tree_insert_common (tree, + key, + mask, + value, + RADIX_REPLACE); } /* @@ -162,14 +177,17 @@ radix32tree_replace (radix_tree_t *tree, guint32 key, guint32 mask, uintptr_t va * 5 words total in stack */ static gboolean -radix_recurse_nodes (radix_node_t *node, radix_tree_traverse_func func, void *user_data, gint level) +radix_recurse_nodes (radix_node_t *node, + radix_tree_traverse_func func, + void *user_data, + gint level) { if (node->left) { if (radix_recurse_nodes (node->left, func, user_data, level + 1)) { return TRUE; } } - + if (node->value != RADIX_NO_VALUE) { if (func (node->key, level, node->value, user_data)) { return TRUE; @@ -186,17 +204,19 @@ radix_recurse_nodes (radix_node_t *node, radix_tree_traverse_func func, void *us } void -radix32tree_traverse (radix_tree_t *tree, radix_tree_traverse_func func, void *user_data) +radix32tree_traverse (radix_tree_t *tree, + radix_tree_traverse_func func, + void *user_data) { - radix_recurse_nodes (tree->root, func, user_data, 0); + radix_recurse_nodes (tree->root, func, user_data, 0); } gint radix32tree_delete (radix_tree_t * tree, guint32 key, guint32 mask) { - guint32 bit; - radix_node_t *node; + guint32 bit; + radix_node_t *node; bit = 0x80000000; node = tree->root; @@ -226,7 +246,7 @@ radix32tree_delete (radix_tree_t * tree, guint32 key, guint32 mask) return -1; } - for (;;) { + for (;; ) { if (node->parent->right == node) { node->parent->right = NULL; @@ -257,9 +277,9 @@ radix32tree_delete (radix_tree_t * tree, guint32 key, guint32 mask) uintptr_t radix32tree_find (radix_tree_t * tree, guint32 key) { - guint32 bit; - uintptr_t value; - radix_node_t *node; + guint32 bit; + uintptr_t value; + radix_node_t *node; bit = 0x80000000; value = RADIX_NO_VALUE; @@ -285,10 +305,10 @@ radix32tree_find (radix_tree_t * tree, guint32 key) } -static void * +static void * radix_alloc (radix_tree_t * tree) { - gchar *p; + gchar *p; p = rspamd_mempool_alloc (tree->pool, sizeof (radix_node_t)); @@ -316,6 +336,6 @@ radix32_tree_find_addr (radix_tree_t *tree, rspamd_inet_addr_t *addr) return radix32tree_find (tree, ntohl (addr->addr.s4.sin_addr.s_addr)); } -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/libutil/radix.h b/src/libutil/radix.h index 88f345e3d..cfdefa25b 100644 --- a/src/libutil/radix.h +++ b/src/libutil/radix.h @@ -7,29 +7,30 @@ #define RADIX_NO_VALUE (uintptr_t)-1 -typedef struct radix_node_s radix_node_t; +typedef struct radix_node_s radix_node_t; struct radix_node_s { - radix_node_t *right; - radix_node_t *left; - radix_node_t *parent; - uintptr_t value; + radix_node_t *right; + radix_node_t *left; + radix_node_t *parent; + uintptr_t value; guint32 key; }; typedef struct { - radix_node_t *root; - size_t size; + radix_node_t *root; + size_t size; rspamd_mempool_t *pool; } radix_tree_t; -typedef gboolean (*radix_tree_traverse_func)(guint32 key, guint32 mask, uintptr_t value, void *user_data); +typedef gboolean (*radix_tree_traverse_func)(guint32 key, guint32 mask, + uintptr_t value, void *user_data); /** * Create new radix tree */ -radix_tree_t *radix_tree_create (void); +radix_tree_t * radix_tree_create (void); /** * Insert value to radix tree @@ -37,7 +38,10 @@ radix_tree_t *radix_tree_create (void); * 0 if operation was successfull * -1 if there was some error */ -gint radix32tree_insert (radix_tree_t *tree, guint32 key, guint32 mask, uintptr_t value); +gint radix32tree_insert (radix_tree_t *tree, + guint32 key, + guint32 mask, + uintptr_t value); /** * Add value to radix tree or insert it if value does not exists @@ -45,7 +49,10 @@ gint radix32tree_insert (radix_tree_t *tree, guint32 key, guint32 mask, uintptr_ * 0 if value was inserted * -1 if there was some error */ -uintptr_t radix32tree_add (radix_tree_t *tree, guint32 key, guint32 mask, uintptr_t value); +uintptr_t radix32tree_add (radix_tree_t *tree, + guint32 key, + guint32 mask, + uintptr_t value); /** * Replace value in radix tree or insert it if value does not exists @@ -53,7 +60,10 @@ uintptr_t radix32tree_add (radix_tree_t *tree, guint32 key, guint32 mask, uintpt * 0 if value was inserted * -1 if there was some error */ -gint radix32tree_replace (radix_tree_t *tree, guint32 key, guint32 mask, uintptr_t value); +gint radix32tree_replace (radix_tree_t *tree, + guint32 key, + guint32 mask, + uintptr_t value); /** * Delete value from radix tree @@ -81,7 +91,9 @@ uintptr_t radix32_tree_find_addr (radix_tree_t *tree, rspamd_inet_addr_t *addr); /** * Traverse via the whole tree calling specified callback */ -void radix32tree_traverse (radix_tree_t *tree, radix_tree_traverse_func func, void *user_data); +void radix32tree_traverse (radix_tree_t *tree, + radix_tree_traverse_func func, + void *user_data); /** * Frees radix tree diff --git a/src/libutil/rrd.c b/src/libutil/rrd.c index a0e21eaed..fa9324dc4 100644 --- a/src/libutil/rrd.c +++ b/src/libutil/rrd.c @@ -58,7 +58,7 @@ rrd_dst_from_string (const gchar *str) /** * Convert numeric presentation of dst to string */ -const gchar* +const gchar * rrd_dst_to_string (enum rrd_dst_type type) { switch (type) { @@ -105,7 +105,7 @@ rrd_cf_from_string (const gchar *str) /** * Convert numeric presentation of cf to string */ -const gchar* +const gchar * rrd_cf_to_string (enum rrd_cf_type type) { switch (type) { @@ -127,7 +127,10 @@ rrd_cf_to_string (enum rrd_cf_type type) } void -rrd_make_default_rra (const gchar *cf_name, gulong pdp_cnt, gulong rows, struct rrd_rra_def *rra) +rrd_make_default_rra (const gchar *cf_name, + gulong pdp_cnt, + gulong rows, + struct rrd_rra_def *rra) { rra->pdp_cnt = pdp_cnt; rra->row_cnt = rows; @@ -139,8 +142,8 @@ rrd_make_default_rra (const gchar *cf_name, gulong pdp_cnt, gulong rows, struct void rrd_make_default_ds (const gchar *name, gulong pdp_step, struct rrd_ds_def *ds) { - rspamd_strlcpy (ds->ds_nam, name, sizeof (ds->ds_nam)); - rspamd_strlcpy (ds->dst, "COUNTER", sizeof (ds->dst)); + rspamd_strlcpy (ds->ds_nam, name, sizeof (ds->ds_nam)); + rspamd_strlcpy (ds->dst, "COUNTER", sizeof (ds->dst)); memset (ds->par, 0, sizeof (ds->par)); ds->par[RRD_DS_mrhb_cnt].lv = pdp_step * 2; ds->par[RRD_DS_min_val].dv = NAN; @@ -153,74 +156,90 @@ rrd_make_default_ds (const gchar *name, gulong pdp_step, struct rrd_ds_def *ds) static gboolean rspamd_rrd_check_file (const gchar *filename, gboolean need_data, GError **err) { - gint fd, i; - struct stat st; - struct rrd_file_head head; - struct rrd_rra_def rra; - gint head_size; + gint fd, i; + struct stat st; + struct rrd_file_head head; + struct rrd_rra_def rra; + gint head_size; fd = open (filename, O_RDWR); if (fd == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd open error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd open error: %s", strerror (errno)); return FALSE; } if (fstat (fd, &st) == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd stat error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd stat error: %s", strerror (errno)); close (fd); return FALSE; } if (st.st_size < (goffset)sizeof (struct rrd_file_head)) { /* We have trimmed file */ - g_set_error (err, rrd_error_quark (), EINVAL, "rrd size is bad: %ud", (guint)st.st_size); + g_set_error (err, rrd_error_quark (), EINVAL, "rrd size is bad: %ud", + (guint)st.st_size); close (fd); return FALSE; } /* Try to read header */ if (read (fd, &head, sizeof (head)) != sizeof (head)) { - g_set_error (err, rrd_error_quark (), errno, "rrd read head error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd read head error: %s", + strerror (errno)); close (fd); return FALSE; } /* Check magic */ if (memcmp (head.cookie, RRD_COOKIE, sizeof (head.cookie)) != 0 || - memcmp (head.version, RRD_VERSION, sizeof (head.version)) != 0 || - head.float_cookie != RRD_FLOAT_COOKIE) { - g_set_error (err, rrd_error_quark (), EINVAL, "rrd head cookies error: %s", strerror (errno)); + memcmp (head.version, RRD_VERSION, sizeof (head.version)) != 0 || + head.float_cookie != RRD_FLOAT_COOKIE) { + g_set_error (err, + rrd_error_quark (), EINVAL, "rrd head cookies error: %s", + strerror (errno)); close (fd); return FALSE; } /* Check for other params */ if (head.ds_cnt <= 0 || head.rra_cnt <= 0) { - g_set_error (err, rrd_error_quark (), EINVAL, "rrd head cookies error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), EINVAL, "rrd head cookies error: %s", + strerror (errno)); close (fd); return FALSE; } /* Now we can calculate the overall size of rrd */ head_size = sizeof (struct rrd_file_head) + - sizeof (struct rrd_ds_def) * head.ds_cnt + - sizeof (struct rrd_rra_def) * head.rra_cnt + - sizeof (struct rrd_live_head) + - sizeof (struct rrd_pdp_prep) * head.ds_cnt + - sizeof (struct rrd_cdp_prep) * head.ds_cnt * head.rra_cnt + - sizeof (struct rrd_rra_ptr) * head.rra_cnt; + sizeof (struct rrd_ds_def) * head.ds_cnt + + sizeof (struct rrd_rra_def) * head.rra_cnt + + sizeof (struct rrd_live_head) + + sizeof (struct rrd_pdp_prep) * head.ds_cnt + + sizeof (struct rrd_cdp_prep) * head.ds_cnt * head.rra_cnt + + sizeof (struct rrd_rra_ptr) * head.rra_cnt; if (st.st_size < (goffset)head_size) { - g_set_error (err, rrd_error_quark (), errno, "rrd file seems to have stripped header: %d", head_size); + g_set_error (err, + rrd_error_quark (), errno, "rrd file seems to have stripped header: %d", + head_size); close (fd); return FALSE; } if (need_data) { /* Now check rra */ - if (lseek (fd, sizeof (struct rrd_ds_def) * head.ds_cnt, SEEK_CUR) == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd head lseek error: %s", strerror (errno)); + if (lseek (fd, sizeof (struct rrd_ds_def) * head.ds_cnt, + SEEK_CUR) == -1) { + g_set_error (err, + rrd_error_quark (), errno, "rrd head lseek error: %s", + strerror (errno)); close (fd); return FALSE; } - for (i = 0; i < (gint)head.rra_cnt; i ++) { + for (i = 0; i < (gint)head.rra_cnt; i++) { if (read (fd, &rra, sizeof (rra)) != sizeof (rra)) { - g_set_error (err, rrd_error_quark (), errno, "rrd read rra error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd read rra error: %s", + strerror (errno)); close (fd); return FALSE; } @@ -228,7 +247,9 @@ rspamd_rrd_check_file (const gchar *filename, gboolean need_data, GError **err) } if (st.st_size != head_size) { - g_set_error (err, rrd_error_quark (), EINVAL, "rrd file seems to have incorrect size: %d, must be %d", (gint)st.st_size, head_size); + g_set_error (err, + rrd_error_quark (), EINVAL, "rrd file seems to have incorrect size: %d, must be %d", + (gint)st.st_size, head_size); close (fd); return FALSE; } @@ -245,7 +266,7 @@ rspamd_rrd_check_file (const gchar *filename, gboolean need_data, GError **err) static void rspamd_rrd_adjust_pointers (struct rspamd_rrd_file *file, gboolean completed) { - guint8 *ptr; + guint8 *ptr; ptr = file->map; file->stat_head = (struct rrd_file_head *)ptr; @@ -259,7 +280,8 @@ rspamd_rrd_adjust_pointers (struct rspamd_rrd_file *file, gboolean completed) file->pdp_prep = (struct rrd_pdp_prep *)ptr; ptr += sizeof (struct rrd_pdp_prep) * file->stat_head->ds_cnt; file->cdp_prep = (struct rrd_cdp_prep *)ptr; - ptr += sizeof (struct rrd_cdp_prep) * file->stat_head->rra_cnt * file->stat_head->ds_cnt; + ptr += sizeof (struct rrd_cdp_prep) * file->stat_head->rra_cnt * + file->stat_head->ds_cnt; file->rra_ptr = (struct rrd_rra_ptr *)ptr; if (completed) { ptr += sizeof (struct rrd_rra_ptr) * file->stat_head->rra_cnt; @@ -277,12 +299,12 @@ rspamd_rrd_adjust_pointers (struct rspamd_rrd_file *file, gboolean completed) * @param err * @return */ -static struct rspamd_rrd_file* +static struct rspamd_rrd_file * rspamd_rrd_open_common (const gchar *filename, gboolean completed, GError **err) { - struct rspamd_rrd_file *new; - gint fd; - struct stat st; + struct rspamd_rrd_file *new; + gint fd; + struct stat st; if (!rspamd_rrd_check_file (filename, completed, err)) { return NULL; @@ -298,20 +320,25 @@ rspamd_rrd_open_common (const gchar *filename, gboolean completed, GError **err) /* Open file */ fd = open (filename, O_RDWR); if (fd == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd open error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd open error: %s", strerror (errno)); return FALSE; } if (fstat (fd, &st) == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd stat error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd stat error: %s", strerror (errno)); close (fd); return FALSE; } /* Mmap file */ new->size = st.st_size; - if ((new->map = mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if ((new->map = + mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + 0)) == MAP_FAILED) { close (fd); - g_set_error (err, rrd_error_quark (), ENOMEM, "mmap failed: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), ENOMEM, "mmap failed: %s", strerror (errno)); g_slice_free1 (sizeof (struct rspamd_rrd_file), new); return NULL; } @@ -335,7 +362,7 @@ rspamd_rrd_open_common (const gchar *filename, gboolean completed, GError **err) * @param err error pointer * @return rrd file structure */ -struct rspamd_rrd_file* +struct rspamd_rrd_file * rspamd_rrd_open (const gchar *filename, GError **err) { return rspamd_rrd_open_common (filename, TRUE, err); @@ -350,25 +377,31 @@ rspamd_rrd_open (const gchar *filename, GError **err) * @param err error pointer * @return TRUE if file has been created */ -struct rspamd_rrd_file* -rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gulong pdp_step, GError **err) +struct rspamd_rrd_file * +rspamd_rrd_create (const gchar *filename, + gulong ds_count, + gulong rra_count, + gulong pdp_step, + GError **err) { - struct rspamd_rrd_file *new; - struct rrd_file_head head; - struct rrd_ds_def ds; - struct rrd_rra_def rra; - struct rrd_live_head lh; - struct rrd_pdp_prep pdp; - struct rrd_cdp_prep cdp; - struct rrd_rra_ptr rra_ptr; - gint fd; - guint i, j; - struct timeval tv; + struct rspamd_rrd_file *new; + struct rrd_file_head head; + struct rrd_ds_def ds; + struct rrd_rra_def rra; + struct rrd_live_head lh; + struct rrd_pdp_prep pdp; + struct rrd_cdp_prep cdp; + struct rrd_rra_ptr rra_ptr; + gint fd; + guint i, j; + struct timeval tv; /* Open file */ fd = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0644); if (fd == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd create error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd create error: %s", + strerror (errno)); return NULL; } @@ -377,13 +410,14 @@ rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gul head.rra_cnt = rra_count; head.ds_cnt = ds_count; head.pdp_step = pdp_step; - memcpy (head.cookie, RRD_COOKIE, sizeof (head.cookie)); + memcpy (head.cookie, RRD_COOKIE, sizeof (head.cookie)); memcpy (head.version, RRD_VERSION, sizeof (head.version)); head.float_cookie = RRD_FLOAT_COOKIE; if (write (fd, &head, sizeof (head)) != sizeof (head)) { close (fd); - g_set_error (err, rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); return NULL; } @@ -391,10 +425,12 @@ rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gul memset (&ds.ds_nam, 0, sizeof (ds.ds_nam)); memcpy (&ds.dst, "COUNTER", sizeof ("COUNTER")); memset (&ds.par, 0, sizeof (ds.par)); - for (i = 0; i < ds_count; i ++) { + for (i = 0; i < ds_count; i++) { if (write (fd, &ds, sizeof (ds)) != sizeof (ds)) { close (fd); - g_set_error (err, rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd write error: %s", + strerror (errno)); return NULL; } } @@ -403,10 +439,12 @@ rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gul memcpy (&rra.cf_nam, "AVERAGE", sizeof ("AVERAGE")); rra.pdp_cnt = 1; memset (&rra.par, 0, sizeof (rra.par)); - for (i = 0; i < rra_count; i ++) { + for (i = 0; i < rra_count; i++) { if (write (fd, &rra, sizeof (rra)) != sizeof (rra)) { close (fd); - g_set_error (err, rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd write error: %s", + strerror (errno)); return NULL; } } @@ -418,7 +456,8 @@ rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gul if (write (fd, &lh, sizeof (lh)) != sizeof (lh)) { close (fd); - g_set_error (err, rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); return NULL; } @@ -427,10 +466,12 @@ rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gul memset (&pdp.scratch, 0, sizeof (pdp.scratch)); pdp.scratch[PDP_val].dv = 0.; pdp.scratch[PDP_unkn_sec_cnt].lv = 0; - for (i = 0; i < ds_count; i ++) { + for (i = 0; i < ds_count; i++) { if (write (fd, &pdp, sizeof (pdp)) != sizeof (pdp)) { close (fd); - g_set_error (err, rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd write error: %s", + strerror (errno)); return NULL; } } @@ -438,12 +479,14 @@ rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gul /* Fill cdp prep */ memset (&cdp.scratch, 0, sizeof (cdp.scratch)); cdp.scratch[CDP_val].dv = NAN; - for (i = 0; i < rra_count; i ++) { + for (i = 0; i < rra_count; i++) { cdp.scratch[CDP_unkn_pdp_cnt].lv = 0; - for (j = 0; j < ds_count; j ++) { + for (j = 0; j < ds_count; j++) { if (write (fd, &cdp, sizeof (cdp)) != sizeof (cdp)) { close (fd); - g_set_error (err, rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd write error: %s", + strerror (errno)); return NULL; } } @@ -451,10 +494,12 @@ rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gul /* Set row pointers */ memset (&rra_ptr, 0, sizeof (rra_ptr)); - for (i = 0; i < rra_count; i ++) { + for (i = 0; i < rra_count; i++) { if (write (fd, &rra_ptr, sizeof (rra_ptr)) != sizeof (rra_ptr)) { close (fd); - g_set_error (err, rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd write error: %s", + strerror (errno)); return NULL; } } @@ -476,8 +521,10 @@ gboolean rspamd_rrd_add_ds (struct rspamd_rrd_file *file, GArray *ds, GError **err) { - if (file == NULL || file->stat_head->ds_cnt * sizeof (struct rrd_ds_def) != ds->len) { - g_set_error (err, rrd_error_quark (), EINVAL, "rrd add ds failed: wrong arguments"); + if (file == NULL || file->stat_head->ds_cnt * sizeof (struct rrd_ds_def) != + ds->len) { + g_set_error (err, + rrd_error_quark (), EINVAL, "rrd add ds failed: wrong arguments"); return FALSE; } @@ -497,8 +544,10 @@ rspamd_rrd_add_ds (struct rspamd_rrd_file *file, GArray *ds, GError **err) gboolean rspamd_rrd_add_rra (struct rspamd_rrd_file *file, GArray *rra, GError **err) { - if (file == NULL || file->stat_head->rra_cnt * sizeof (struct rrd_rra_def) != rra->len) { - g_set_error (err, rrd_error_quark (), EINVAL, "rrd add rra failed: wrong arguments"); + if (file == NULL || file->stat_head->rra_cnt * + sizeof (struct rrd_rra_def) != rra->len) { + g_set_error (err, + rrd_error_quark (), EINVAL, "rrd add rra failed: wrong arguments"); return FALSE; } @@ -517,31 +566,34 @@ rspamd_rrd_add_rra (struct rspamd_rrd_file *file, GArray *rra, GError **err) gboolean rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err) { - gint fd; - guint i; - gint count = 0; - gdouble vbuf[1024]; - struct stat st; + gint fd; + guint i; + gint count = 0; + gdouble vbuf[1024]; + struct stat st; if (file == NULL || file->filename == NULL) { - g_set_error (err, rrd_error_quark (), EINVAL, "rrd add rra failed: wrong arguments"); + g_set_error (err, + rrd_error_quark (), EINVAL, "rrd add rra failed: wrong arguments"); return FALSE; } fd = open (file->filename, O_RDWR); if (fd == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd open error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd open error: %s", strerror (errno)); return FALSE; } if (lseek (fd, 0, SEEK_END) == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd seek error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd seek error: %s", strerror (errno)); close (fd); return FALSE; } /* Adjust CDP */ - for (i = 0; i < file->stat_head->rra_cnt; i ++) { + for (i = 0; i < file->stat_head->rra_cnt; i++) { file->cdp_prep->scratch[CDP_unkn_pdp_cnt].lv = 0; /* Randomize row pointer */ file->rra_ptr->cur_row = g_random_int () % file->rra_def[i].row_cnt; @@ -551,14 +603,17 @@ rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err) munmap (file->map, file->size); /* Write values */ - for (i = 0; i < G_N_ELEMENTS (vbuf); i ++) { + for (i = 0; i < G_N_ELEMENTS (vbuf); i++) { vbuf[i] = NAN; } while (count > 0) { /* Write values in buffered matter */ - if (write (fd, vbuf, MIN ((gint)G_N_ELEMENTS (vbuf), count) * sizeof (gdouble)) == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd write error: %s", strerror (errno)); + if (write (fd, vbuf, + MIN ((gint)G_N_ELEMENTS (vbuf), count) * sizeof (gdouble)) == -1) { + g_set_error (err, + rrd_error_quark (), errno, "rrd write error: %s", + strerror (errno)); close (fd); return FALSE; } @@ -566,16 +621,20 @@ rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err) } if (fstat (fd, &st) == -1) { - g_set_error (err, rrd_error_quark (), errno, "rrd stat error: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), errno, "rrd stat error: %s", strerror (errno)); close (fd); return FALSE; } /* Mmap again */ file->size = st.st_size; - if ((file->map = mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if ((file->map = + mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + 0)) == MAP_FAILED) { close (fd); - g_set_error (err, rrd_error_quark (), ENOMEM, "mmap failed: %s", strerror (errno)); + g_set_error (err, + rrd_error_quark (), ENOMEM, "mmap failed: %s", strerror (errno)); g_slice_free1 (sizeof (struct rspamd_rrd_file), file); return FALSE; } @@ -597,16 +656,20 @@ rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err) * @return */ static gboolean -rspamd_rrd_update_pdp_prep (struct rspamd_rrd_file *file, gdouble *vals, gdouble *pdp_new, gdouble interval) +rspamd_rrd_update_pdp_prep (struct rspamd_rrd_file *file, + gdouble *vals, + gdouble *pdp_new, + gdouble interval) { - guint i; - enum rrd_dst_type type; + guint i; + enum rrd_dst_type type; - for (i = 0; i < file->stat_head->ds_cnt; i ++) { + for (i = 0; i < file->stat_head->ds_cnt; i++) { type = rrd_dst_from_string (file->ds_def[i].dst); if (file->ds_def[i].par[RRD_DS_mrhb_cnt].lv < interval) { - rspamd_strlcpy (file->pdp_prep[i].last_ds, "U", sizeof (file->pdp_prep[i].last_ds)); + rspamd_strlcpy (file->pdp_prep[i].last_ds, "U", + sizeof (file->pdp_prep[i].last_ds)); } if (file->ds_def[i].par[RRD_DS_mrhb_cnt].lv >= interval) { @@ -617,7 +680,8 @@ rspamd_rrd_update_pdp_prep (struct rspamd_rrd_file *file, gdouble *vals, gdouble pdp_new[i] = NAN; } else { - pdp_new[i] = vals[i] - strtod (file->pdp_prep[i].last_ds, NULL); + pdp_new[i] = vals[i] - strtod (file->pdp_prep[i].last_ds, + NULL); } break; case RRD_DST_GAUGE: @@ -635,7 +699,8 @@ rspamd_rrd_update_pdp_prep (struct rspamd_rrd_file *file, gdouble *vals, gdouble } /* Copy value to the last_ds */ if (!isnan (vals[i])) { - rspamd_snprintf (file->pdp_prep[i].last_ds, sizeof (file->pdp_prep[i].last_ds), "%.4f", vals[i]); + rspamd_snprintf (file->pdp_prep[i].last_ds, + sizeof (file->pdp_prep[i].last_ds), "%.4f", vals[i]); } else { file->pdp_prep[i].last_ds[0] = 'U'; @@ -658,15 +723,20 @@ rspamd_rrd_update_pdp_prep (struct rspamd_rrd_file *file, gdouble *vals, gdouble * @param pdp_diff time till last pdp update */ static void -rspamd_rrd_update_pdp_step (struct rspamd_rrd_file *file, gdouble *pdp_new, gdouble *pdp_temp, gdouble interval, - gdouble pre_int, gdouble post_int, gulong pdp_diff) +rspamd_rrd_update_pdp_step (struct rspamd_rrd_file *file, + gdouble *pdp_new, + gdouble *pdp_temp, + gdouble interval, + gdouble pre_int, + gdouble post_int, + gulong pdp_diff) { - guint i; - rrd_value_t *scratch; - gulong heartbeat; + guint i; + rrd_value_t *scratch; + gulong heartbeat; - for (i = 0; i < file->stat_head->ds_cnt; i ++) { + for (i = 0; i < file->stat_head->ds_cnt; i++) { scratch = file->pdp_prep[i].scratch; heartbeat = file->ds_def[i].par[RRD_DS_mrhb_cnt].lv; if (!isnan (pdp_new[i])) { @@ -677,21 +747,22 @@ rspamd_rrd_update_pdp_step (struct rspamd_rrd_file *file, gdouble *pdp_new, gdou pre_int = 0.0; } /* Check interval value for heartbeat for this DS */ - if ((interval > heartbeat) || (file->stat_head->pdp_step / 2.0 < scratch[PDP_unkn_sec_cnt].lv)) { + if ((interval > heartbeat) || + (file->stat_head->pdp_step / 2.0 < scratch[PDP_unkn_sec_cnt].lv)) { pdp_temp[i] = NAN; } else { pdp_temp[i] = scratch[PDP_val].dv / - ((double) (pdp_diff - scratch[PDP_unkn_sec_cnt].lv) - pre_int); + ((double) (pdp_diff - scratch[PDP_unkn_sec_cnt].lv) - pre_int); } - if (isnan (pdp_new[i])) { - scratch[PDP_unkn_sec_cnt].lv = floor (post_int); - scratch[PDP_val].dv = NAN; - } else { - scratch[PDP_unkn_sec_cnt].lv = 0; - scratch[PDP_val].dv = pdp_new[i] / interval * post_int; - } + if (isnan (pdp_new[i])) { + scratch[PDP_unkn_sec_cnt].lv = floor (post_int); + scratch[PDP_val].dv = NAN; + } else { + scratch[PDP_unkn_sec_cnt].lv = 0; + scratch[PDP_val].dv = pdp_new[i] / interval * post_int; + } } } @@ -705,23 +776,28 @@ rspamd_rrd_update_pdp_step (struct rspamd_rrd_file *file, gdouble *pdp_new, gdou * @param pdp_temp temporary pdp points */ static void -rspamd_rrd_update_cdp (struct rspamd_rrd_file *file, gdouble pdp_steps, gdouble pdp_offset, gulong *rra_steps, gulong rra_index, - gdouble *pdp_temp) +rspamd_rrd_update_cdp (struct rspamd_rrd_file *file, + gdouble pdp_steps, + gdouble pdp_offset, + gulong *rra_steps, + gulong rra_index, + gdouble *pdp_temp) { - guint i; - struct rrd_rra_def *rra; - rrd_value_t *scratch; - enum rrd_cf_type cf; - gdouble last_cdp, cur_cdp; - gulong pdp_in_cdp; + guint i; + struct rrd_rra_def *rra; + rrd_value_t *scratch; + enum rrd_cf_type cf; + gdouble last_cdp, cur_cdp; + gulong pdp_in_cdp; rra = &file->rra_def[rra_index]; cf = rrd_cf_from_string (rra->cf_nam); /* Iterate over all DS for this RRA */ - for (i = 0; i < file->stat_head->ds_cnt; i ++) { + for (i = 0; i < file->stat_head->ds_cnt; i++) { /* Get CDP for this RRA and DS */ - scratch = file->cdp_prep[rra_index * file->stat_head->ds_cnt + i].scratch; + scratch = + file->cdp_prep[rra_index * file->stat_head->ds_cnt + i].scratch; if (rra->pdp_cnt > 1) { /* Do we have any CDP to update for this rra ? */ if (rra_steps[rra_index] > 0) { @@ -737,7 +813,8 @@ rspamd_rrd_update_cdp (struct rspamd_rrd_file *file, gdouble pdp_steps, gdouble } /* Check XFF for this rra */ - if (scratch[CDP_unkn_pdp_cnt].lv > rra->pdp_cnt * rra->par[RRA_cdp_xff_val].lv) { + if (scratch[CDP_unkn_pdp_cnt].lv > rra->pdp_cnt * + rra->par[RRA_cdp_xff_val].lv) { /* XFF is reached */ scratch[CDP_primary_val].dv = NAN; } @@ -745,17 +822,26 @@ rspamd_rrd_update_cdp (struct rspamd_rrd_file *file, gdouble pdp_steps, gdouble /* Need to initialize CDP using specified consolidation */ switch (cf) { case RRD_CF_AVERAGE: - last_cdp = isnan (scratch[CDP_val].dv) ? 0.0 : scratch[CDP_val].dv; + last_cdp = + isnan (scratch[CDP_val].dv) ? 0.0 : scratch[CDP_val] + .dv; cur_cdp = isnan (pdp_temp[i]) ? 0.0 : pdp_temp[i]; - scratch[CDP_primary_val].dv = (last_cdp + cur_cdp * pdp_offset) / (rra->pdp_cnt - scratch[CDP_unkn_pdp_cnt].lv); + scratch[CDP_primary_val].dv = + (last_cdp + cur_cdp * + pdp_offset) / + (rra->pdp_cnt - scratch[CDP_unkn_pdp_cnt].lv); break; case RRD_CF_MAXIMUM: - last_cdp = isnan (scratch[CDP_val].dv) ? -INFINITY : scratch[CDP_val].dv; + last_cdp = + isnan (scratch[CDP_val].dv) ? -INFINITY : scratch[ + CDP_val].dv; cur_cdp = isnan (pdp_temp[i]) ? -INFINITY : pdp_temp[i]; scratch[CDP_primary_val].dv = MAX (last_cdp, cur_cdp); break; case RRD_CF_MINIMUM: - last_cdp = isnan (scratch[CDP_val].dv) ? INFINITY : scratch[CDP_val].dv; + last_cdp = + isnan (scratch[CDP_val].dv) ? INFINITY : scratch[ + CDP_val].dv; cur_cdp = isnan (pdp_temp[i]) ? INFINITY : pdp_temp[i]; scratch[CDP_primary_val].dv = MIN (last_cdp, cur_cdp); break; @@ -809,7 +895,8 @@ rspamd_rrd_update_cdp (struct rspamd_rrd_file *file, gdouble pdp_steps, gdouble scratch[CDP_val].dv = pdp_temp[i] * pdp_steps; } else { - scratch[CDP_val].dv = last_cdp + pdp_temp[i] * pdp_steps; + scratch[CDP_val].dv = last_cdp + pdp_temp[i] * + pdp_steps; } break; case RRD_CF_MAXIMUM: @@ -848,26 +935,31 @@ rspamd_rrd_update_cdp (struct rspamd_rrd_file *file, gdouble pdp_steps, gdouble void rspamd_rrd_write_rra (struct rspamd_rrd_file *file, gulong *rra_steps) { - guint i, j, scratch_idx, cdp_idx, k; - struct rrd_rra_def *rra; - gdouble *rra_row; + guint i, j, scratch_idx, cdp_idx, k; + struct rrd_rra_def *rra; + gdouble *rra_row; /* Iterate over all RRA */ - for (i = 0; i < file->stat_head->rra_cnt; i ++) { + for (i = 0; i < file->stat_head->rra_cnt; i++) { rra = &file->rra_def[i]; /* How much steps need to be updated */ - for (j = 0, scratch_idx = CDP_primary_val; j < rra_steps[i]; j ++, scratch_idx = CDP_secondary_val) { + for (j = 0, scratch_idx = CDP_primary_val; + j < rra_steps[i]; + j++, scratch_idx = CDP_secondary_val) { /* Move row ptr */ if (++file->rra_ptr[i].cur_row >= rra->row_cnt) { file->rra_ptr[i].cur_row = 0; } /* Calculate seek */ - rra_row = file->rrd_value + (file->stat_head->ds_cnt * i + file->rra_ptr[i].cur_row); + rra_row = file->rrd_value + + (file->stat_head->ds_cnt * i + file->rra_ptr[i].cur_row); /* Iterate over DS */ - for (k = 0; k < file->stat_head->ds_cnt; k ++) { + for (k = 0; k < file->stat_head->ds_cnt; k++) { cdp_idx = i * file->stat_head->ds_cnt + k; - memcpy (rra_row, &file->cdp_prep[cdp_idx].scratch[scratch_idx].dv, sizeof (gdouble)); - rra_row ++; + memcpy (rra_row, + &file->cdp_prep[cdp_idx].scratch[scratch_idx].dv, + sizeof (gdouble)); + rra_row++; } } } @@ -881,23 +973,28 @@ rspamd_rrd_write_rra (struct rspamd_rrd_file *file, gulong *rra_steps) * @return TRUE if a row has been added */ gboolean -rspamd_rrd_add_record (struct rspamd_rrd_file* file, GArray *points, GError **err) +rspamd_rrd_add_record (struct rspamd_rrd_file * file, + GArray *points, + GError **err) { - gdouble interval, *pdp_new, *pdp_temp, pre_int, post_int; - guint i; - gulong pdp_steps, cur_pdp_count, prev_pdp_step, cur_pdp_step, - prev_pdp_age, cur_pdp_age, *rra_steps, pdp_offset; - struct timeval tv; - - if (file == NULL || file->stat_head->ds_cnt * sizeof (gdouble) != points->len) { - g_set_error (err, rrd_error_quark (), EINVAL, "rrd add points failed: wrong arguments"); + gdouble interval, *pdp_new, *pdp_temp, pre_int, post_int; + guint i; + gulong pdp_steps, cur_pdp_count, prev_pdp_step, cur_pdp_step, + prev_pdp_age, cur_pdp_age, *rra_steps, pdp_offset; + struct timeval tv; + + if (file == NULL || file->stat_head->ds_cnt * sizeof (gdouble) != + points->len) { + g_set_error (err, + rrd_error_quark (), EINVAL, + "rrd add points failed: wrong arguments"); return FALSE; } /* Get interval */ gettimeofday (&tv, NULL); interval = (gdouble)(tv.tv_sec - file->live_head->last_up) + - (gdouble)(tv.tv_usec - file->live_head->last_up_usec) / 1e6f; + (gdouble)(tv.tv_usec - file->live_head->last_up_usec) / 1e6f; /* Update PDP preparation values */ pdp_new = g_malloc (sizeof (gdouble) * file->stat_head->ds_cnt); @@ -905,8 +1002,11 @@ rspamd_rrd_add_record (struct rspamd_rrd_file* file, GArray *points, GError **er /* How much steps need to be updated in each RRA */ rra_steps = g_malloc0 (sizeof (gulong) * file->stat_head->rra_cnt); - if (!rspamd_rrd_update_pdp_prep (file, (gdouble *)points->data, pdp_new, interval)) { - g_set_error (err, rrd_error_quark (), EINVAL, "rrd update pdp failed: wrong arguments"); + if (!rspamd_rrd_update_pdp_prep (file, (gdouble *)points->data, pdp_new, + interval)) { + g_set_error (err, + rrd_error_quark (), EINVAL, + "rrd update pdp failed: wrong arguments"); g_free (pdp_new); g_free (pdp_temp); g_free (rra_steps); @@ -915,7 +1015,7 @@ rspamd_rrd_add_record (struct rspamd_rrd_file* file, GArray *points, GError **er /* Calculate elapsed steps */ /* Age in seconds for previous pdp store */ - prev_pdp_age = file->live_head->last_up % file->stat_head->pdp_step; + prev_pdp_age = file->live_head->last_up % file->stat_head->pdp_step; /* Time in seconds for last pdp update */ prev_pdp_step = file->live_head->last_up - prev_pdp_age; /* Age in seconds from current time to required pdp time */ @@ -924,7 +1024,10 @@ rspamd_rrd_add_record (struct rspamd_rrd_file* file, GArray *points, GError **er cur_pdp_step = tv.tv_sec - cur_pdp_age; if (cur_pdp_step > prev_pdp_step) { - pre_int = (gdouble)(cur_pdp_step - file->live_head->last_up) - ((double)file->live_head->last_up_usec) / 1e6f; + pre_int = + (gdouble)(cur_pdp_step - + file->live_head->last_up) - + ((double)file->live_head->last_up_usec) / 1e6f; post_int = (gdouble)cur_pdp_age + ((double)tv.tv_usec) / 1e6f; } else { @@ -937,10 +1040,11 @@ rspamd_rrd_add_record (struct rspamd_rrd_file* file, GArray *points, GError **er if (pdp_steps == 0) { /* Simple update of pdp prep */ - for (i = 0; i < file->stat_head->ds_cnt; i ++) { + for (i = 0; i < file->stat_head->ds_cnt; i++) { if (isnan (pdp_new[i])) { /* Increment unknown period */ - file->pdp_prep[i].scratch[PDP_unkn_sec_cnt].lv += floor (interval); + file->pdp_prep[i].scratch[PDP_unkn_sec_cnt].lv += floor ( + interval); } else { if (isnan (file->pdp_prep[i].scratch[PDP_val].dv)) { @@ -958,23 +1062,36 @@ rspamd_rrd_add_record (struct rspamd_rrd_file* file, GArray *points, GError **er /* Complex update of PDP, CDP and RRA */ /* Update PDP for this step */ - rspamd_rrd_update_pdp_step (file, pdp_new, pdp_temp, interval, pre_int, post_int, pdp_steps * file->stat_head->pdp_step); + rspamd_rrd_update_pdp_step (file, + pdp_new, + pdp_temp, + interval, + pre_int, + post_int, + pdp_steps * file->stat_head->pdp_step); /* Update CDP points for each RRA*/ - for (i = 0; i < file->stat_head->rra_cnt; i ++) { + for (i = 0; i < file->stat_head->rra_cnt; i++) { /* Calculate pdp offset for this RRA */ - pdp_offset = file->rra_def[i].pdp_cnt - cur_pdp_count % file->rra_def[i].pdp_cnt; + pdp_offset = file->rra_def[i].pdp_cnt - cur_pdp_count % + file->rra_def[i].pdp_cnt; /* How much steps we got for this RRA */ if (pdp_offset <= pdp_steps) { - rra_steps[i] = (pdp_steps - pdp_offset) / file->rra_def[i].pdp_cnt + 1; + rra_steps[i] = + (pdp_steps - pdp_offset) / file->rra_def[i].pdp_cnt + 1; } else { /* This rra have not passed enough pdp steps */ rra_steps[i] = 0; } /* Update this specific CDP */ - rspamd_rrd_update_cdp (file, pdp_steps, pdp_offset, rra_steps, i, pdp_temp); + rspamd_rrd_update_cdp (file, + pdp_steps, + pdp_offset, + rra_steps, + i, + pdp_temp); /* Write RRA */ rspamd_rrd_write_rra (file, rra_steps); } @@ -998,7 +1115,7 @@ rspamd_rrd_add_record (struct rspamd_rrd_file* file, GArray *points, GError **er * @return */ gint -rspamd_rrd_close (struct rspamd_rrd_file* file) +rspamd_rrd_close (struct rspamd_rrd_file * file) { if (file == NULL) { errno = EINVAL; diff --git a/src/libutil/rrd.h b/src/libutil/rrd.h index ff6902894..13ed965ab 100644 --- a/src/libutil/rrd.h +++ b/src/libutil/rrd.h @@ -42,17 +42,17 @@ typedef union { struct rrd_file_head { /* Data Base Identification Section ** */ - gchar cookie[4]; /* RRD */ - gchar version[5]; /* version of the format */ - gdouble float_cookie; /* is it the correct double representation ? */ + gchar cookie[4]; /* RRD */ + gchar version[5]; /* version of the format */ + gdouble float_cookie; /* is it the correct double representation ? */ /* Data Base Structure Definition **** */ gulong ds_cnt; /* how many different ds provid input to the rrd */ gulong rra_cnt; /* how many rras will be maintained in the rrd */ gulong pdp_step; /* pdp interval in seconds */ - rrd_value_t par[10]; /* global parameters ... unused - at the moment */ + rrd_value_t par[10]; /* global parameters ... unused + at the moment */ }; enum rrd_dst_type { @@ -66,9 +66,9 @@ enum rrd_ds_param { RRD_DS_mrhb_cnt = 0, /* minimum required heartbeat */ RRD_DS_min_val, /* the processed input of a ds must */ RRD_DS_max_val, /* be between max_val and min_val - * both can be set to UNKNOWN if you - * do not care. Data outside the limits - * set to UNKNOWN */ + * both can be set to UNKNOWN if you + * do not care. Data outside the limits + * set to UNKNOWN */ RRD_DS_cdef = RRD_DS_mrhb_cnt }; /* pointer to encoded rpn expression only applies to DST_CDEF */ @@ -117,8 +117,8 @@ enum rrd_cf_type { enum rrd_rra_param { RRA_cdp_xff_val = 0, /* what part of the consolidated - * datapoint must be known, to produce a - * valid entry in the rra */ + * datapoint must be known, to produce a + * valid entry in the rra */ /* CF_HWPREDICT: */ RRA_hw_alpha = 1, /* exponential smoothing parameter for the intercept in @@ -161,18 +161,18 @@ enum rrd_rra_param { /* RRA_dependent_rra_idx = 3, */ RRA_window_len = 4, RRA_failure_threshold = 5 - /* For CF_FAILURES, number of violations within the last - * window required to mark a failure. */ + /* For CF_FAILURES, number of violations within the last + * window required to mark a failure. */ }; #define RRD_CF_NAM_SIZE 20 struct rrd_rra_def { - gchar cf_nam[RRD_CF_NAM_SIZE]; /* consolidation function (null term) */ + gchar cf_nam[RRD_CF_NAM_SIZE]; /* consolidation function (null term) */ gulong row_cnt; /* number of entries in the store */ gulong pdp_cnt; /* how many primary data points are - * required for a consolidated data point?*/ + * required for a consolidated data point?*/ rrd_value_t par[MAX_RRA_PAR_EN]; /* index see rra_param_en */ }; @@ -186,17 +186,17 @@ struct rrd_live_head { enum rrd_pdp_param { PDP_unkn_sec_cnt = 0, /* how many seconds of the current - * pdp value is unknown data? */ + * pdp value is unknown data? */ PDP_val }; /* current value of the pdp. this depends on dst */ struct rrd_pdp_prep { gchar last_ds[RRD_LAST_DS_LEN]; /* the last reading from the data - * source. this is stored in ASCII - * to cater for very large counters - * we might encounter in connection - * with SNMP. */ + * source. this is stored in ASCII + * to cater for very large counters + * we might encounter in connection + * with SNMP. */ rrd_value_t scratch[10]; /* contents according to pdp_par_en */ }; @@ -249,9 +249,9 @@ enum rrd_cdp_param { }; struct rrd_cdp_prep { - rrd_value_t scratch[RRD_MAX_CDP_PAR_EN]; - /* contents according to cdp_par_en * - * init state should be NAN */ + rrd_value_t scratch[RRD_MAX_CDP_PAR_EN]; + /* contents according to cdp_par_en * + * init state should be NAN */ }; struct rrd_rra_ptr { @@ -270,7 +270,7 @@ struct rspamd_rrd_file { gdouble *rrd_value; /* list of rrd values */ gchar *filename; - guint8* map; /* mmapped area */ + guint8 * map; /* mmapped area */ gsize size; /* its size */ gboolean finalized; }; @@ -284,7 +284,7 @@ struct rspamd_rrd_file { * @param err error pointer * @return rrd file structure */ -struct rspamd_rrd_file* rspamd_rrd_open (const gchar *filename, GError **err); +struct rspamd_rrd_file * rspamd_rrd_open (const gchar *filename, GError **err); /** * Create basic header for rrd file @@ -295,7 +295,11 @@ struct rspamd_rrd_file* rspamd_rrd_open (const gchar *filename, GError **err); * @param err error pointer * @return TRUE if file has been created */ -struct rspamd_rrd_file* rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gulong pdp_step, GError **err); +struct rspamd_rrd_file * rspamd_rrd_create (const gchar *filename, + gulong ds_count, + gulong rra_count, + gulong pdp_step, + GError **err); /** * Add data sources to rrd file @@ -304,7 +308,9 @@ struct rspamd_rrd_file* rspamd_rrd_create (const gchar *filename, gulong ds_coun * @param err error pointer * @return TRUE if data sources were added */ -gboolean rspamd_rrd_add_ds (struct rspamd_rrd_file* file, GArray *ds, GError **err); +gboolean rspamd_rrd_add_ds (struct rspamd_rrd_file * file, + GArray *ds, + GError **err); /** * Add round robin archives to rrd file @@ -313,7 +319,9 @@ gboolean rspamd_rrd_add_ds (struct rspamd_rrd_file* file, GArray *ds, GError **e * @param err error pointer * @return TRUE if archives were added */ -gboolean rspamd_rrd_add_rra (struct rspamd_rrd_file *file, GArray *rra, GError **err); +gboolean rspamd_rrd_add_rra (struct rspamd_rrd_file *file, + GArray *rra, + GError **err); /** * Finalize rrd file header and initialize all RRA in the file @@ -330,14 +338,16 @@ gboolean rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err); * @param err error pointer * @return TRUE if a row has been added */ -gboolean rspamd_rrd_add_record (struct rspamd_rrd_file* file, GArray *points, GError **err); +gboolean rspamd_rrd_add_record (struct rspamd_rrd_file * file, + GArray *points, + GError **err); /** * Close rrd file * @param file * @return */ -gint rspamd_rrd_close (struct rspamd_rrd_file* file); +gint rspamd_rrd_close (struct rspamd_rrd_file * file); /* * Conversion functions @@ -350,7 +360,7 @@ enum rrd_dst_type rrd_dst_from_string (const gchar *str); /** * Convert numeric presentation of dst to string */ -const gchar* rrd_dst_to_string (enum rrd_dst_type type); +const gchar * rrd_dst_to_string (enum rrd_dst_type type); /** * Convert rrd consolidation function type from string to numeric value */ @@ -358,17 +368,22 @@ enum rrd_cf_type rrd_cf_from_string (const gchar *str); /** * Convert numeric presentation of cf to string */ -const gchar* rrd_cf_to_string (enum rrd_cf_type type); +const gchar * rrd_cf_to_string (enum rrd_cf_type type); /* Default RRA and DS */ /** * Create default RRA */ -void rrd_make_default_rra (const gchar *cf_name, gulong pdp_cnt, gulong rows, struct rrd_rra_def *rra); +void rrd_make_default_rra (const gchar *cf_name, + gulong pdp_cnt, + gulong rows, + struct rrd_rra_def *rra); /** * Create default DS */ -void rrd_make_default_ds (const gchar *name, gulong pdp_step, struct rrd_ds_def *ds); +void rrd_make_default_ds (const gchar *name, + gulong pdp_step, + struct rrd_ds_def *ds); #endif /* RRD_H_ */ diff --git a/src/libutil/trie.c b/src/libutil/trie.c index 394c4e939..8c9e0f600 100644 --- a/src/libutil/trie.c +++ b/src/libutil/trie.c @@ -25,10 +25,10 @@ #include "mem_pool.h" #include "trie.h" -rspamd_trie_t* +rspamd_trie_t * rspamd_trie_create (gboolean icase) { - rspamd_trie_t *new; + rspamd_trie_t *new; new = g_malloc (sizeof (rspamd_trie_t)); @@ -48,20 +48,25 @@ rspamd_trie_create (gboolean icase) * Insert a single character as the specified level of the suffix tree */ static struct rspamd_trie_state * -rspamd_trie_insert_char (rspamd_trie_t *trie, guint depth, struct rspamd_trie_state *pos, gchar c) +rspamd_trie_insert_char (rspamd_trie_t *trie, + guint depth, + struct rspamd_trie_state *pos, + gchar c) { - struct rspamd_trie_match *new_match; - struct rspamd_trie_state *new_pos; + struct rspamd_trie_match *new_match; + struct rspamd_trie_state *new_pos; /* New match is inserted before pos */ - new_match = rspamd_mempool_alloc (trie->pool, sizeof (struct rspamd_trie_match)); + new_match = + rspamd_mempool_alloc (trie->pool, sizeof (struct rspamd_trie_match)); new_match->next = pos->match; new_match->c = c; /* Now set match link */ pos->match = new_match; - new_match->state = rspamd_mempool_alloc (trie->pool, sizeof (struct rspamd_trie_state)); + new_match->state = + rspamd_mempool_alloc (trie->pool, sizeof (struct rspamd_trie_state)); new_pos = new_match->state; new_pos->match = NULL; new_pos->fail = &trie->root; @@ -86,7 +91,7 @@ rspamd_trie_insert_char (rspamd_trie_t *trie, guint depth, struct rspamd_trie_st static inline struct rspamd_trie_match * check_match (struct rspamd_trie_state *s, gchar c) { - struct rspamd_trie_match *match = s->match; + struct rspamd_trie_match *match = s->match; while (match && match->c != c) { match = match->next; @@ -98,11 +103,11 @@ check_match (struct rspamd_trie_state *s, gchar c) void rspamd_trie_insert (rspamd_trie_t *trie, const gchar *pattern, gint pattern_id) { - const guchar *p = pattern; - struct rspamd_trie_state *q, *q1, *r, *cur_node; - struct rspamd_trie_match *m, *n; - guint i, depth = 0; - gchar c; + const guchar *p = pattern; + struct rspamd_trie_state *q, *q1, *r, *cur_node; + struct rspamd_trie_match *m, *n; + guint i, depth = 0; + gchar c; /* Insert pattern to the trie */ @@ -118,8 +123,8 @@ rspamd_trie_insert (rspamd_trie_t *trie, const gchar *pattern, gint pattern_id) else { cur_node = m->state; } - p ++; - depth ++; + p++; + depth++; } cur_node->final = depth; @@ -165,13 +170,16 @@ rspamd_trie_insert (rspamd_trie_t *trie, const gchar *pattern, gint pattern_id) } } -const gchar* -rspamd_trie_lookup (rspamd_trie_t *trie, const gchar *buffer, gsize buflen, gint *matched_id) +const gchar * +rspamd_trie_lookup (rspamd_trie_t *trie, + const gchar *buffer, + gsize buflen, + gint *matched_id) { - const guchar *p = buffer, *prev, *ret; - struct rspamd_trie_state *cur_node; - struct rspamd_trie_match *m = NULL; - gchar c; + const guchar *p = buffer, *prev, *ret; + struct rspamd_trie_state *cur_node; + struct rspamd_trie_match *m = NULL; + gchar c; cur_node = &trie->root; @@ -195,9 +203,9 @@ rspamd_trie_lookup (rspamd_trie_t *trie, const gchar *buffer, gsize buflen, gint /* We have tried the pattern but eventually it was not found */ cur_node = &trie->root; ret = p; - p ++; + p++; prev = p; - buflen --; + buflen--; continue; } @@ -213,9 +221,9 @@ rspamd_trie_lookup (rspamd_trie_t *trie, const gchar *buffer, gsize buflen, gint return (const gchar *) ret; } } - p ++; + p++; prev = p; - buflen --; + buflen--; } return NULL; diff --git a/src/libutil/trie.h b/src/libutil/trie.h index 2792ee4a5..037ffd9ee 100644 --- a/src/libutil/trie.h +++ b/src/libutil/trie.h @@ -58,7 +58,7 @@ typedef struct rspamd_trie_s { /* * Create a new suffix trie */ -rspamd_trie_t* rspamd_trie_create (gboolean icase); +rspamd_trie_t * rspamd_trie_create (gboolean icase); /* * Insert a pattern into the trie @@ -66,7 +66,9 @@ rspamd_trie_t* rspamd_trie_create (gboolean icase); * @param pattern text of element * @param pattern_id id of element */ -void rspamd_trie_insert (rspamd_trie_t *trie, const gchar *pattern, gint pattern_id); +void rspamd_trie_insert (rspamd_trie_t *trie, + const gchar *pattern, + gint pattern_id); /* * Search for a text using suffix trie @@ -76,7 +78,10 @@ void rspamd_trie_insert (rspamd_trie_t *trie, const gchar *pattern, gint pattern * @param mached_id on a successfull search here would be stored id of pattern found * @return Position in a text where pattern was found or NULL if no patterns were found */ -const gchar* rspamd_trie_lookup (rspamd_trie_t *trie, const gchar *buffer, gsize buflen, gint *matched_id); +const gchar * rspamd_trie_lookup (rspamd_trie_t *trie, + const gchar *buffer, + gsize buflen, + gint *matched_id); /* * Deallocate suffix trie diff --git a/src/libutil/upstream.c b/src/libutil/upstream.c index f82d3ba50..ee21a5ec3 100644 --- a/src/libutil/upstream.c +++ b/src/libutil/upstream.c @@ -27,7 +27,7 @@ #ifdef _THREAD_SAFE -pthread_rwlock_t upstream_mtx = PTHREAD_RWLOCK_INITIALIZER; +pthread_rwlock_t upstream_mtx = PTHREAD_RWLOCK_INITIALIZER; # define U_RLOCK() do { pthread_rwlock_rdlock (&upstream_mtx); } while (0) # define U_WLOCK() do { pthread_rwlock_wrlock (&upstream_mtx); } while (0) # define U_UNLOCK() do { pthread_rwlock_unlock (&upstream_mtx); } while (0) @@ -45,49 +45,91 @@ pthread_rwlock_t upstream_mtx = PTHREAD_RWLOCK_INITIALIZER; * Init: 0x0 */ -static const guint32 crc32lookup[256] = { - 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, - 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, - 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, - 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, - 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, - 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, - 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, 0x42b2986cU, - 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, - 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, - 0xcfba9599U, 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, - 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, 0x01db7106U, - 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U, - 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, - 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, - 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, - 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U, - 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, - 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, - 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, - 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, - 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U, - 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, - 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U, 0xe3630b12U, 0x94643b84U, - 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, - 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, - 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, - 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 0xd6d6a3e8U, 0xa1d1937eU, - 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, - 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, - 0x316e8eefU, 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, - 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, 0xb2bd0b28U, - 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU, - 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, - 0x72076785U, 0x05005713U, 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, - 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, - 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U, - 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, - 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, - 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, - 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, - 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U, - 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, +static const guint32 crc32lookup[256] = { + 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, + 0x706af48fU, + 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, + 0x97d2d988U, + 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, + 0x6ab020f2U, + 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, + 0x83d385c7U, + 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, + 0x63066cd9U, + 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, + 0xa2677172U, + 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, + 0x42b2986cU, + 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, + 0xabd13d59U, + 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, + 0x56b3c423U, + 0xcfba9599U, 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, + 0xb10be924U, + 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, + 0x01db7106U, + 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, + 0xe8b8d433U, + 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, + 0x086d3d2dU, + 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, + 0xf262004eU, + 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, + 0x12b7e950U, + 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, + 0xfbd44c65U, + 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, + 0x3dd895d7U, + 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, 0x346ed9fcU, 0xad678846U, + 0xda60b8d0U, + 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, + 0x270241aaU, + 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, + 0xce61e49fU, + 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, + 0x2eb40d81U, + 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, + 0x74b1d29aU, + 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U, 0xe3630b12U, + 0x94643b84U, + 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, + 0x7d079eb1U, + 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, + 0x806567cbU, + 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, + 0x67dd4accU, + 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 0xd6d6a3e8U, + 0xa1d1937eU, + 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, + 0x48b2364bU, + 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, + 0xa867df55U, + 0x316e8eefU, 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, + 0x5268e236U, + 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, + 0xb2bd0b28U, + 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, + 0x5bdeae1dU, + 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, + 0xeb0e363fU, + 0x72076785U, 0x05005713U, 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, + 0x0cb61b38U, + 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, + 0xf1d4e242U, + 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, + 0x18b74777U, + 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, + 0xf862ae69U, + 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, + 0x3903b3c2U, + 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, + 0xd9d65adcU, + 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, + 0x30b5ffe9U, + 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, + 0xcdd70693U, + 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, + 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU }; @@ -95,7 +137,11 @@ static const guint32 crc32lookup[256] = { * Check upstream parameters and mark it whether valid or dead */ static void -check_upstream (struct upstream *up, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors) +check_upstream (struct upstream *up, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors) { if (up->dead) { if (now - up->time >= revive_timeout) { @@ -118,7 +164,7 @@ check_upstream (struct upstream *up, time_t now, time_t error_timeout, time_t re } } -/* +/* * Call this function after failed upstream request */ void @@ -135,7 +181,7 @@ upstream_fail (struct upstream *up, time_t now) } } -/* +/* * Call this function after successfull upstream request */ void @@ -151,15 +197,15 @@ upstream_ok (struct upstream *up, time_t now) up->weight--; } -/* +/* * Mark all upstreams as active. This function is used when all upstreams are marked as inactive */ void revive_all_upstreams (void *ups, size_t members, size_t msize) { - guint i; - struct upstream *cur; - guchar *p; + guint i; + struct upstream *cur; + guchar *p; U_WLOCK (); p = ups; @@ -174,16 +220,22 @@ revive_all_upstreams (void *ups, size_t members, size_t msize) U_UNLOCK (); } -/* +/* * Scan all upstreams for errors and mark upstreams dead or alive depends on conditions, - * return number of alive upstreams + * return number of alive upstreams */ static gint -rescan_upstreams (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors) +rescan_upstreams (void *ups, + size_t members, + size_t msize, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors) { - guint i, alive; - struct upstream *cur; - guchar *p; + guint i, alive; + struct upstream *cur; + guchar *p; /* Recheck all upstreams */ p = ups; @@ -207,18 +259,18 @@ rescan_upstreams (void *ups, size_t members, size_t msize, time_t now, time_t er } /* Return alive upstream by its number */ -static struct upstream * +static struct upstream * get_upstream_by_number (void *ups, size_t members, size_t msize, gint selected) { - guint i; - u_char *p, *c; - struct upstream *cur; + guint i; + u_char *p, *c; + struct upstream *cur; i = 0; p = ups; c = ups; U_RLOCK (); - for (;;) { + for (;; ) { /* Out of range, return NULL */ if (p > c + members * msize) { break; @@ -248,11 +300,11 @@ get_upstream_by_number (void *ups, size_t members, size_t msize, gint selected) /* * Get hash key for specified key (perl hash) */ -static guint32 +static guint32 get_hash_for_key (guint32 hash, const gchar *key, size_t keylen) { - guint32 h, index; - const gchar *end = key + keylen; + guint32 h, index; + const gchar *end = key + keylen; h = ~hash; @@ -277,13 +329,24 @@ get_hash_for_key (guint32 hash, const gchar *key, size_t keylen) /* * Recheck all upstreams and return random active upstream */ -struct upstream * -get_random_upstream (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, - time_t revive_timeout, size_t max_errors) +struct upstream * +get_random_upstream (void *ups, + size_t members, + size_t msize, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors) { - gint alive, selected; - - alive = rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors); + gint alive, selected; + + alive = rescan_upstreams (ups, + members, + msize, + now, + error_timeout, + revive_timeout, + max_errors); selected = rand () % alive; return get_upstream_by_number (ups, members, msize, selected); @@ -292,16 +355,29 @@ get_random_upstream (void *ups, size_t members, size_t msize, time_t now, time_t /* * Return upstream by hash, that is calculated from active upstreams number */ -struct upstream * -get_upstream_by_hash (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, - time_t revive_timeout, size_t max_errors, const gchar *key, size_t keylen) +struct upstream * +get_upstream_by_hash (void *ups, + size_t members, + size_t msize, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors, + const gchar *key, + size_t keylen) { - gint alive, tries = 0, r; - guint32 h = 0, ht; - gchar *p, numbuf[4]; - struct upstream *cur; - - alive = rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors); + gint alive, tries = 0, r; + guint32 h = 0, ht; + gchar *p, numbuf[4]; + struct upstream *cur; + + alive = rescan_upstreams (ups, + members, + msize, + now, + error_timeout, + revive_timeout, + max_errors); if (alive == 0) { return NULL; @@ -313,7 +389,7 @@ get_upstream_by_hash (void *ups, size_t members, size_t msize, time_t now, time_ #endif h %= members; - for (;;) { + for (;; ) { p = (gchar *)ups + msize * h; cur = (struct upstream *)p; if (!cur->dead) { @@ -343,16 +419,27 @@ get_upstream_by_hash (void *ups, size_t members, size_t msize, time_t now, time_ /* * Recheck all upstreams and return upstream in round-robin order according to weight and priority */ -struct upstream * -get_upstream_round_robin (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, - time_t revive_timeout, size_t max_errors) +struct upstream * +get_upstream_round_robin (void *ups, + size_t members, + size_t msize, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors) { - guint max_weight, i; - struct upstream *cur, *selected = NULL; - u_char *p; + guint max_weight, i; + struct upstream *cur, *selected = NULL; + u_char *p; /* Recheck all upstreams */ - (void)rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors); + (void)rescan_upstreams (ups, + members, + msize, + now, + error_timeout, + revive_timeout, + max_errors); p = ups; max_weight = 0; @@ -393,16 +480,27 @@ get_upstream_round_robin (void *ups, size_t members, size_t msize, time_t now, t /* * Recheck all upstreams and return upstream in round-robin order according to only priority (master-slaves) */ -struct upstream * -get_upstream_master_slave (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, - time_t revive_timeout, size_t max_errors) +struct upstream * +get_upstream_master_slave (void *ups, + size_t members, + size_t msize, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors) { - guint max_weight, i; - struct upstream *cur, *selected = NULL; - u_char *p; + guint max_weight, i; + struct upstream *cur, *selected = NULL; + u_char *p; /* Recheck all upstreams */ - (void)rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors); + (void)rescan_upstreams (ups, + members, + msize, + now, + error_timeout, + revive_timeout, + max_errors); p = ups; max_weight = 0; @@ -437,11 +535,14 @@ ketama_sort_cmp (const void *a1, const void *a2) * Add ketama points for specified upstream */ gint -upstream_ketama_add (struct upstream *up, gchar *up_key, size_t keylen, size_t keypoints) +upstream_ketama_add (struct upstream *up, + gchar *up_key, + size_t keylen, + size_t keypoints) { - guint32 h = 0; - gchar tmp[4]; - guint i; + guint32 h = 0; + gchar tmp[4]; + guint i; /* Allocate ketama points array */ if (up->ketama_points == NULL) { @@ -472,16 +573,29 @@ upstream_ketama_add (struct upstream *up, gchar *up_key, size_t keylen, size_t k /* * Return upstream by hash and find nearest ketama point in some server */ -struct upstream * -get_upstream_by_hash_ketama (void *ups, size_t members, size_t msize, - time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors, const gchar *key, size_t keylen) +struct upstream * +get_upstream_by_hash_ketama (void *ups, + size_t members, + size_t msize, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors, + const gchar *key, + size_t keylen) { - guint alive, i; - guint32 h = 0, step, middle, d, min_diff = UINT_MAX; - gchar *p; - struct upstream *cur = NULL, *nearest = NULL; - - alive = rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors); + guint alive, i; + guint32 h = 0, step, middle, d, min_diff = UINT_MAX; + gchar *p; + struct upstream *cur = NULL, *nearest = NULL; + + alive = rescan_upstreams (ups, + members, + msize, + now, + error_timeout, + revive_timeout, + max_errors); if (alive == 0) { return NULL; @@ -520,6 +634,6 @@ get_upstream_by_hash_ketama (void *ups, size_t members, size_t msize, #undef U_LOCK #undef U_UNLOCK -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/libutil/upstream.h b/src/libutil/upstream.h index da0a00013..bc11ebf77 100644 --- a/src/libutil/upstream.h +++ b/src/libutil/upstream.h @@ -8,13 +8,13 @@ * Structure of generic upstream */ struct upstream { - guint errors; /**< Errors for this upstream */ - time_t time; /**< Time of marking */ - guint dead; /**< Dead flag */ - guint priority; /**< Fixed priority */ - gint16 weight; /**< Dynamic weight */ - guint32 *ketama_points; /**< Ketama points array */ - size_t ketama_points_size; /**< Ketama array size */ + guint errors; /**< Errors for this upstream */ + time_t time; /**< Time of marking */ + guint dead; /**< Dead flag */ + guint priority; /**< Fixed priority */ + gint16 weight; /**< Dynamic weight */ + guint32 *ketama_points; /**< Ketama points array */ + size_t ketama_points_size; /**< Ketama array size */ }; /** @@ -43,7 +43,10 @@ void revive_all_upstreams (void *ups, size_t members, size_t msize); /** * Add ketama points for upstream */ -gint upstream_ketama_add (struct upstream *up, gchar *up_key, size_t keylen, size_t keypoints); +gint upstream_ketama_add (struct upstream *up, + gchar *up_key, + size_t keylen, + size_t keypoints); /** * Get a random upstream from array of upstreams @@ -55,9 +58,9 @@ gint upstream_ketama_add (struct upstream *up, gchar *up_key, size_t keylen, siz * @param revive_timeout time during which we counts upstream dead * @param max_errors maximum errors during error_timeout to mark upstream dead */ -struct upstream* get_random_upstream (void *ups, size_t members, size_t msize, - time_t now, time_t error_timeout, - time_t revive_timeout, size_t max_errors); +struct upstream * get_random_upstream (void *ups, size_t members, size_t msize, + time_t now, time_t error_timeout, + time_t revive_timeout, size_t max_errors); /** * Get upstream based on hash from array of upstreams @@ -71,10 +74,10 @@ struct upstream* get_random_upstream (void *ups, size_t members, size_t msize, * @param key key for hashing * @param keylen length of the key */ -struct upstream* get_upstream_by_hash (void *ups, size_t members, size_t msize, - time_t now, time_t error_timeout, - time_t revive_timeout, size_t max_errors, - const gchar *key, size_t keylen); +struct upstream * get_upstream_by_hash (void *ups, size_t members, size_t msize, + time_t now, time_t error_timeout, + time_t revive_timeout, size_t max_errors, + const gchar *key, size_t keylen); /** * Get an upstream from array of upstreams based on its current weight @@ -86,9 +89,13 @@ struct upstream* get_upstream_by_hash (void *ups, size_t members, size_t msize, * @param revive_timeout time during which we counts upstream dead * @param max_errors maximum errors during error_timeout to mark upstream dead */ -struct upstream* get_upstream_round_robin (void *ups, size_t members, size_t msize, - time_t now, time_t error_timeout, - time_t revive_timeout, size_t max_errors); +struct upstream * get_upstream_round_robin (void *ups, + size_t members, + size_t msize, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors); /** * Get upstream based on hash from array of upstreams, this functions is using ketama algorithm @@ -102,9 +109,15 @@ struct upstream* get_upstream_round_robin (void *ups, size_t members, size_t msi * @param key key for hashing * @param keylen length of the key */ -struct upstream* get_upstream_by_hash_ketama (void *ups, size_t members, size_t msize, time_t now, - time_t error_timeout, time_t revive_timeout, size_t max_errors, - const gchar *key, size_t keylen); +struct upstream * get_upstream_by_hash_ketama (void *ups, + size_t members, + size_t msize, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors, + const gchar *key, + size_t keylen); /** * Get an upstream from array of upstreams based on its current priority (not weight) @@ -116,12 +129,16 @@ struct upstream* get_upstream_by_hash_ketama (void *ups, size_t members, size_t * @param revive_timeout time during which we counts upstream dead * @param max_errors maximum errors during error_timeout to mark upstream dead */ -struct upstream* get_upstream_master_slave (void *ups, size_t members, size_t msize, - time_t now, time_t error_timeout, - time_t revive_timeout, size_t max_errors); +struct upstream * get_upstream_master_slave (void *ups, + size_t members, + size_t msize, + time_t now, + time_t error_timeout, + time_t revive_timeout, + size_t max_errors); #endif /* UPSTREAM_H */ -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/libutil/util.c b/src/libutil/util.c index 8d1a6353d..43b492983 100644 --- a/src/libutil/util.c +++ b/src/libutil/util.c @@ -53,7 +53,7 @@ gint make_socket_nonblocking (gint fd) { - gint ofl; + gint ofl; ofl = fcntl (fd, F_GETFL, 0); @@ -67,7 +67,7 @@ make_socket_nonblocking (gint fd) gint make_socket_blocking (gint fd) { - gint ofl; + gint ofl; ofl = fcntl (fd, F_GETFL, 0); @@ -81,8 +81,8 @@ make_socket_blocking (gint fd) gint poll_sync_socket (gint fd, gint timeout, short events) { - gint r; - struct pollfd fds[1]; + gint r; + struct pollfd fds[1]; fds->fd = fd; fds->events = events; @@ -98,10 +98,10 @@ poll_sync_socket (gint fd, gint timeout, short events) static gint make_inet_socket (gint type, struct addrinfo *addr, gboolean is_server, - gboolean async, GList **list) + gboolean async, GList **list) { - gint fd, r, optlen, on = 1, s_error; - struct addrinfo *cur; + gint fd, r, optlen, on = 1, s_error; + struct addrinfo *cur; cur = addr; while (cur) { @@ -123,10 +123,18 @@ make_inet_socket (gint type, struct addrinfo *addr, gboolean is_server, } if (is_server) { - setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint)); + setsockopt (fd, + SOL_SOCKET, + SO_REUSEADDR, + (const void *)&on, + sizeof (gint)); #ifdef HAVE_IPV6_V6ONLY if (cur->ai_family == AF_INET6) { - setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, sizeof (gint)); + setsockopt (fd, + IPPROTO_IPV6, + IPV6_V6ONLY, + (const void *)&on, + sizeof (gint)); } #endif r = bind (fd, cur->ai_addr, cur->ai_addrlen); @@ -137,12 +145,14 @@ make_inet_socket (gint type, struct addrinfo *addr, gboolean is_server, if (r == -1) { if (errno != EINPROGRESS) { - msg_warn ("bind/connect failed: %d, '%s'", errno, strerror (errno)); + msg_warn ("bind/connect failed: %d, '%s'", errno, + strerror (errno)); goto out; } if (!async) { /* Try to poll */ - if (poll_sync_socket (fd, CONNECT_TIMEOUT * 1000, POLLOUT) <= 0) { + if (poll_sync_socket (fd, CONNECT_TIMEOUT * 1000, + POLLOUT) <= 0) { errno = ETIMEDOUT; msg_warn ("bind/connect failed: timeout"); goto out; @@ -196,10 +206,14 @@ make_udp_socket (struct addrinfo *addr, gboolean is_server, gboolean async) } gint -make_unix_socket (const gchar *path, struct sockaddr_un *addr, gint type, gboolean is_server, gboolean async) +make_unix_socket (const gchar *path, + struct sockaddr_un *addr, + gint type, + gboolean is_server, + gboolean async) { - gint fd = -1, s_error, r, optlen, serrno, on = 1; - struct stat st; + gint fd = -1, s_error, r, optlen, serrno, on = 1; + struct stat st; if (path == NULL) return -1; @@ -216,7 +230,10 @@ make_unix_socket (const gchar *path, struct sockaddr_un *addr, gint type, gboole if (lstat (addr->sun_path, &st) != -1) { if (S_ISSOCK (st.st_mode)) { if (unlink (addr->sun_path) == -1) { - msg_warn ("unlink %s failed: %d, '%s'", addr->sun_path, errno, strerror (errno)); + msg_warn ("unlink %s failed: %d, '%s'", + addr->sun_path, + errno, + strerror (errno)); goto out; } } @@ -229,7 +246,10 @@ make_unix_socket (const gchar *path, struct sockaddr_un *addr, gint type, gboole fd = socket (PF_LOCAL, type, 0); if (fd == -1) { - msg_warn ("socket failed %s: %d, '%s'", addr->sun_path, errno, strerror (errno)); + msg_warn ("socket failed %s: %d, '%s'", + addr->sun_path, + errno, + strerror (errno)); return -1; } @@ -239,11 +259,13 @@ make_unix_socket (const gchar *path, struct sockaddr_un *addr, gint type, gboole /* Set close on exec */ if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) { - msg_warn ("fcntl failed %s: %d, '%s'", addr->sun_path, errno, strerror (errno)); + msg_warn ("fcntl failed %s: %d, '%s'", addr->sun_path, errno, + strerror (errno)); goto out; } if (is_server) { - setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint)); + setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, + sizeof (gint)); r = bind (fd, (struct sockaddr *)addr, SUN_LEN (addr)); } else { @@ -252,7 +274,10 @@ make_unix_socket (const gchar *path, struct sockaddr_un *addr, gint type, gboole if (r == -1) { if (errno != EINPROGRESS) { - msg_warn ("bind/connect failed %s: %d, '%s'", addr->sun_path, errno, strerror (errno)); + msg_warn ("bind/connect failed %s: %d, '%s'", + addr->sun_path, + errno, + strerror (errno)); goto out; } if (!async) { @@ -283,7 +308,7 @@ make_unix_socket (const gchar *path, struct sockaddr_un *addr, gint type, gboole return (fd); - out: +out: serrno = errno; if (fd != -1) { close (fd); @@ -302,13 +327,13 @@ make_unix_socket (const gchar *path, struct sockaddr_un *addr, gint type, gboole */ gint make_universal_socket (const gchar *credits, guint16 port, - gint type, gboolean async, gboolean is_server, gboolean try_resolve) + gint type, gboolean async, gboolean is_server, gboolean try_resolve) { - struct sockaddr_un un; - struct stat st; - struct addrinfo hints, *res; - gint r; - gchar portbuf[8]; + struct sockaddr_un un; + struct stat st; + struct addrinfo hints, *res; + gint r; + gchar portbuf[8]; if (*credits == '/') { if (is_server) { @@ -328,7 +353,11 @@ make_universal_socket (const gchar *credits, guint16 port, return -1; } else { - return make_unix_socket (credits, &un, type, is_server, async); + return make_unix_socket (credits, + &un, + type, + is_server, + async); } } } @@ -355,7 +384,9 @@ make_universal_socket (const gchar *credits, guint16 port, return r; } else { - msg_err ("address resolution for %s failed: %s", credits, gai_strerror (r)); + msg_err ("address resolution for %s failed: %s", + credits, + gai_strerror (r)); return FALSE; } } @@ -369,16 +400,16 @@ make_universal_socket (const gchar *credits, guint16 port, * @param is_server make this socket as server socket * @param try_resolve try name resolution for a socket (BLOCKING) */ -GList* +GList * make_universal_sockets_list (const gchar *credits, guint16 port, - gint type, gboolean async, gboolean is_server, gboolean try_resolve) + gint type, gboolean async, gboolean is_server, gboolean try_resolve) { - struct sockaddr_un un; - struct stat st; - struct addrinfo hints, *res; - gint r, fd, serrno; - gchar portbuf[8], **strv, **cur; - GList *result = NULL, *rcur; + struct sockaddr_un un; + struct stat st; + struct addrinfo hints, *res; + gint r, fd, serrno; + gchar portbuf[8], **strv, **cur; + GList *result = NULL, *rcur; strv = g_strsplit_set (credits, ",", -1); if (strv == NULL) { @@ -405,7 +436,11 @@ make_universal_sockets_list (const gchar *credits, guint16 port, goto err; } else { - fd = make_unix_socket (credits, &un, type, is_server, async); + fd = make_unix_socket (credits, + &un, + type, + is_server, + async); } } } @@ -440,11 +475,13 @@ make_universal_sockets_list (const gchar *credits, guint16 port, } } else { - msg_err ("address resolution for %s failed: %s", credits, gai_strerror (r)); + msg_err ("address resolution for %s failed: %s", + credits, + gai_strerror (r)); goto err; } } - cur ++; + cur++; } g_strfreev (strv); @@ -472,12 +509,13 @@ err: gint make_socketpair (gint pair[2]) { - gint r; + gint r; r = socketpair (AF_LOCAL, SOCK_STREAM, 0, pair); if (r == -1) { - msg_warn ("socketpair failed: %d, '%s'", errno, strerror (errno), pair[0], pair[1]); + msg_warn ("socketpair failed: %d, '%s'", errno, strerror ( + errno), pair[0], pair[1]); return -1; } /* Set close on exec */ @@ -501,7 +539,7 @@ out: gint write_pid (struct rspamd_main *main) { - pid_t pid; + pid_t pid; if (main->cfg->pid_file == NULL) { return -1; @@ -519,7 +557,8 @@ write_pid (struct rspamd_main *main) #else if (fchown (main->pfh->pf_fd, 0, 0) == -1) { #endif - msg_err ("cannot chown of pidfile %s to 0:0 user", main->cfg->pid_file); + msg_err ("cannot chown of pidfile %s to 0:0 user", + main->cfg->pid_file); } } @@ -530,13 +569,15 @@ write_pid (struct rspamd_main *main) #ifdef HAVE_SA_SIGINFO void -init_signals (struct sigaction *signals, void (*sig_handler)(gint, siginfo_t *, void *)) +init_signals (struct sigaction *signals, void (*sig_handler)(gint, + siginfo_t *, + void *)) #else void init_signals (struct sigaction *signals, void (*sig_handler)(gint)) #endif { - struct sigaction sigpipe_act; + struct sigaction sigpipe_act; /* Setting up signal handlers */ /* SIGUSR1 - reopen config file */ /* SIGUSR2 - worker is ready for accept */ @@ -559,8 +600,8 @@ init_signals (struct sigaction *signals, void (*sig_handler)(gint)) signals->sa_flags = 0; #endif sigaction (SIGTERM, signals, NULL); - sigaction (SIGINT, signals, NULL); - sigaction (SIGHUP, signals, NULL); + sigaction (SIGINT, signals, NULL); + sigaction (SIGHUP, signals, NULL); sigaction (SIGCHLD, signals, NULL); sigaction (SIGUSR1, signals, NULL); sigaction (SIGUSR2, signals, NULL); @@ -577,8 +618,8 @@ init_signals (struct sigaction *signals, void (*sig_handler)(gint)) static void pass_signal_cb (gpointer key, gpointer value, gpointer ud) { - struct rspamd_worker *cur = value; - gint signo = GPOINTER_TO_INT (ud); + struct rspamd_worker *cur = value; + gint signo = GPOINTER_TO_INT (ud); kill (cur->pid, signo); } @@ -586,7 +627,7 @@ pass_signal_cb (gpointer key, gpointer value, gpointer ud) void pass_signal_worker (GHashTable * workers, gint signo) { - g_hash_table_foreach (workers, pass_signal_cb, GINT_TO_POINTER (signo)); + g_hash_table_foreach (workers, pass_signal_cb, GINT_TO_POINTER (signo)); } void @@ -600,9 +641,9 @@ convert_to_lowercase (gchar *str, guint size) #ifndef HAVE_SETPROCTITLE -static gchar *title_buffer = 0; -static size_t title_buffer_size = 0; -static gchar *title_progname, *title_progname_full; +static gchar *title_buffer = 0; +static size_t title_buffer_size = 0; +static gchar *title_progname, *title_progname_full; gint setproctitle (const gchar *fmt, ...) @@ -614,24 +655,33 @@ setproctitle (const gchar *fmt, ...) memset (title_buffer, '\0', title_buffer_size); - ssize_t written; + ssize_t written; if (fmt) { - ssize_t written2; - va_list ap; + ssize_t written2; + va_list ap; - written = snprintf (title_buffer, title_buffer_size, "%s: ", title_progname); + written = snprintf (title_buffer, + title_buffer_size, + "%s: ", + title_progname); if (written < 0 || (size_t) written >= title_buffer_size) return -1; va_start (ap, fmt); - written2 = vsnprintf (title_buffer + written, title_buffer_size - written, fmt, ap); + written2 = vsnprintf (title_buffer + written, + title_buffer_size - written, + fmt, + ap); va_end (ap); if (written2 < 0 || (size_t) written2 >= title_buffer_size - written) return -1; } else { - written = snprintf (title_buffer, title_buffer_size, "%s", title_progname); + written = snprintf (title_buffer, + title_buffer_size, + "%s", + title_progname); if (written < 0 || (size_t) written >= title_buffer_size) return -1; } @@ -643,9 +693,9 @@ setproctitle (const gchar *fmt, ...) } /* - It has to be _init function, because __attribute__((constructor)) - functions gets called without arguments. -*/ + It has to be _init function, because __attribute__((constructor)) + functions gets called without arguments. + */ gint init_title (gint argc, gchar *argv[], gchar *envp[]) @@ -654,8 +704,8 @@ init_title (gint argc, gchar *argv[], gchar *envp[]) /* XXX: try to handle these OSes too */ return 0; #else - gchar *begin_of_buffer = 0, *end_of_buffer = 0; - gint i; + gchar *begin_of_buffer = 0, *end_of_buffer = 0; + gint i; for (i = 0; i < argc; ++i) { if (!begin_of_buffer) @@ -674,7 +724,7 @@ init_title (gint argc, gchar *argv[], gchar *envp[]) if (!end_of_buffer) return 0; - gchar **new_environ = g_malloc ((i + 1) * sizeof (envp[0])); + gchar **new_environ = g_malloc ((i + 1) * sizeof (envp[0])); if (!new_environ) return 0; @@ -691,7 +741,7 @@ init_title (gint argc, gchar *argv[], gchar *envp[]) if (!title_progname_full) goto cleanup_enomem; - gchar *p = strrchr (title_progname_full, '/'); + gchar *p = strrchr (title_progname_full, '/'); if (p) title_progname = p + 1; @@ -708,7 +758,7 @@ init_title (gint argc, gchar *argv[], gchar *envp[]) return 0; - cleanup_enomem: +cleanup_enomem: for (--i; i >= 0; --i) { g_free (new_environ[i]); } @@ -719,13 +769,13 @@ init_title (gint argc, gchar *argv[], gchar *envp[]) #endif #ifndef HAVE_PIDFILE -extern gchar *__progname; -static gint _rspamd_pidfile_remove (rspamd_pidfh_t *pfh, gint freeit); +extern gchar *__progname; +static gint _rspamd_pidfile_remove (rspamd_pidfh_t *pfh, gint freeit); static gint rspamd_pidfile_verify (rspamd_pidfh_t *pfh) { - struct stat sb; + struct stat sb; if (pfh == NULL || pfh->pf_fd == -1) return (-1); @@ -742,15 +792,15 @@ rspamd_pidfile_verify (rspamd_pidfh_t *pfh) static gint rspamd_pidfile_read (const gchar *path, pid_t * pidptr) { - gchar buf[16], *endptr; - gint error, fd, i; + gchar buf[16], *endptr; + gint error, fd, i; fd = open (path, O_RDONLY); if (fd == -1) return (errno); i = read (fd, buf, sizeof (buf) - 1); - error = errno; /* Remember errno in case close() wants to change it. */ + error = errno; /* Remember errno in case close() wants to change it. */ close (fd); if (i == -1) return error; @@ -765,20 +815,23 @@ rspamd_pidfile_read (const gchar *path, pid_t * pidptr) return 0; } -rspamd_pidfh_t * +rspamd_pidfh_t * rspamd_pidfile_open (const gchar *path, mode_t mode, pid_t * pidptr) { - rspamd_pidfh_t *pfh; - struct stat sb; - gint error, fd, len, count; - struct timespec rqtp; + rspamd_pidfh_t *pfh; + struct stat sb; + gint error, fd, len, count; + struct timespec rqtp; pfh = g_malloc (sizeof (*pfh)); if (pfh == NULL) return NULL; if (path == NULL) - len = snprintf (pfh->pf_path, sizeof (pfh->pf_path), "/var/run/%s.pid", g_get_prgname ()); + len = snprintf (pfh->pf_path, + sizeof (pfh->pf_path), + "/var/run/%s.pid", + g_get_prgname ()); else len = snprintf (pfh->pf_path, sizeof (pfh->pf_path), "%s", path); if (len >= (gint)sizeof (pfh->pf_path)) { @@ -800,7 +853,7 @@ rspamd_pidfile_open (const gchar *path, mode_t mode, pid_t * pidptr) rqtp.tv_sec = 0; rqtp.tv_nsec = 5000000; if (errno == EWOULDBLOCK && pidptr != NULL) { - again: +again: errno = rspamd_pidfile_read (pfh->pf_path, pidptr); if (errno == 0) errno = EEXIST; @@ -837,8 +890,8 @@ rspamd_pidfile_open (const gchar *path, mode_t mode, pid_t * pidptr) gint rspamd_pidfile_write (rspamd_pidfh_t *pfh) { - gchar pidstr[16]; - gint error, fd; + gchar pidstr[16]; + gint error, fd; /* * Check remembered descriptor, so we don't overwrite some other @@ -877,7 +930,7 @@ rspamd_pidfile_write (rspamd_pidfh_t *pfh) gint rspamd_pidfile_close (rspamd_pidfh_t *pfh) { - gint error; + gint error; error = rspamd_pidfile_verify (pfh); if (error != 0) { @@ -898,7 +951,7 @@ rspamd_pidfile_close (rspamd_pidfh_t *pfh) static gint _rspamd_pidfile_remove (rspamd_pidfh_t *pfh, gint freeit) { - gint error; + gint error; error = rspamd_pidfile_verify (pfh); if (error != 0) { @@ -936,12 +989,15 @@ rspamd_pidfile_remove (rspamd_pidfh_t *pfh) #endif /* Replace %r with rcpt value and %f with from value, new string is allocated in pool */ -gchar * -resolve_stat_filename (rspamd_mempool_t * pool, gchar *pattern, gchar *rcpt, gchar *from) +gchar * +resolve_stat_filename (rspamd_mempool_t * pool, + gchar *pattern, + gchar *rcpt, + gchar *from) { - gint need_to_format = 0, len = 0; - gint rcptlen, fromlen; - gchar *c = pattern, *new, *s; + gint need_to_format = 0, len = 0; + gint rcptlen, fromlen; + gchar *c = pattern, *new, *s; if (rcpt) { rcptlen = strlen (rcpt); @@ -1007,39 +1063,43 @@ resolve_stat_filename (rspamd_mempool_t * pool, gchar *pattern, gchar *rcpt, gch } #ifdef HAVE_CLOCK_GETTIME -const gchar * -calculate_check_time (struct timeval *tv, struct timespec *begin, gint resolution, guint32 *scan_time) +const gchar * +calculate_check_time (struct timeval *tv, + struct timespec *begin, + gint resolution, + guint32 *scan_time) #else -const gchar * -calculate_check_time (struct timeval *begin, gint resolution, guint32 *scan_time) +const gchar * +calculate_check_time (struct timeval *begin, gint resolution, + guint32 *scan_time) #endif { - double vdiff, diff; - static gchar res[64]; - static gchar fmt[sizeof ("%.10f ms real, %.10f ms virtual")]; - struct timeval tv_now; + double vdiff, diff; + static gchar res[64]; + static gchar fmt[sizeof ("%.10f ms real, %.10f ms virtual")]; + struct timeval tv_now; if (gettimeofday (&tv_now, NULL) == -1) { msg_warn ("gettimeofday failed: %s", strerror (errno)); } #ifdef HAVE_CLOCK_GETTIME - struct timespec ts; + struct timespec ts; - diff = (tv_now.tv_sec - tv->tv_sec) * 1000. + /* Seconds */ - (tv_now.tv_usec - tv->tv_usec) / 1000.; /* Microseconds */ + diff = (tv_now.tv_sec - tv->tv_sec) * 1000. + /* Seconds */ + (tv_now.tv_usec - tv->tv_usec) / 1000.; /* Microseconds */ #ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts); #elif defined(HAVE_CLOCK_VIRTUAL) - clock_gettime (CLOCK_VIRTUAL, &ts); + clock_gettime (CLOCK_VIRTUAL, &ts); #else - clock_gettime (CLOCK_REALTIME, &ts); + clock_gettime (CLOCK_REALTIME, &ts); #endif - vdiff = (ts.tv_sec - begin->tv_sec) * 1000. + /* Seconds */ - (ts.tv_nsec - begin->tv_nsec) / 1000000.; /* Nanoseconds */ + vdiff = (ts.tv_sec - begin->tv_sec) * 1000. + /* Seconds */ + (ts.tv_nsec - begin->tv_nsec) / 1000000.; /* Nanoseconds */ #else - diff = (tv_now.tv_sec - begin->tv_sec) * 1000. + /* Seconds */ - (tv_now.tv_usec - begin->tv_usec) / 1000.; /* Microseconds */ + diff = (tv_now.tv_sec - begin->tv_sec) * 1000. + /* Seconds */ + (tv_now.tv_usec - begin->tv_usec) / 1000.; /* Microseconds */ vdiff = diff; #endif @@ -1071,9 +1131,9 @@ rspamd_strcase_equal (gconstpointer v, gconstpointer v2) guint rspamd_strcase_hash (gconstpointer key) { - const gchar *p = key; - gchar buf[256]; - guint h = 0, i = 0; + const gchar *p = key; + gchar buf[256]; + guint h = 0, i = 0; while (*p != '\0') { @@ -1096,7 +1156,7 @@ rspamd_strcase_hash (gconstpointer key) guint rspamd_str_hash (gconstpointer key) { - gsize len; + gsize len; len = strlen ((const gchar *)key); @@ -1113,7 +1173,8 @@ gboolean fstr_strcase_equal (gconstpointer v, gconstpointer v2) { const f_str_t *f1 = v, *f2 = v2; - if (f1->len == f2->len && g_ascii_strncasecmp (f1->begin, f2->begin, f1->len) == 0) { + if (f1->len == f2->len && + g_ascii_strncasecmp (f1->begin, f2->begin, f1->len) == 0) { return TRUE; } @@ -1124,11 +1185,11 @@ fstr_strcase_equal (gconstpointer v, gconstpointer v2) guint fstr_strcase_hash (gconstpointer key) { - const f_str_t *f = key; - const gchar *p; - guint h = 0, i = 0; - gchar buf[256]; - + const f_str_t *f = key; + const gchar *p; + guint h = 0, i = 0; + gchar buf[256]; + p = f->begin; while (p - f->begin < (gint)f->len) { buf[i] = g_ascii_tolower (*p); @@ -1151,7 +1212,7 @@ void gperf_profiler_init (struct rspamd_config *cfg, const gchar *descr) { #if defined(WITH_GPERF_TOOLS) - gchar prof_path[PATH_MAX]; + gchar prof_path[PATH_MAX]; if (getenv ("CPUPROFILE")) { @@ -1160,10 +1221,16 @@ gperf_profiler_init (struct rspamd_config *cfg, const gchar *descr) } /* Try to create temp directory for gmon.out and chdir to it */ if (cfg->profile_path == NULL) { - cfg->profile_path = g_strdup_printf ("%s/rspamd-profile", cfg->temp_dir); + cfg->profile_path = + g_strdup_printf ("%s/rspamd-profile", cfg->temp_dir); } - snprintf (prof_path, sizeof (prof_path), "%s-%s.%d", cfg->profile_path, descr, (gint)getpid ()); + snprintf (prof_path, + sizeof (prof_path), + "%s-%s.%d", + cfg->profile_path, + descr, + (gint)getpid ()); if (ProfilerStart (prof_path)) { /* start ITIMER_PROF timer */ ProfilerRegisterThread (); @@ -1177,94 +1244,94 @@ gperf_profiler_init (struct rspamd_config *cfg, const gchar *descr) #ifdef HAVE_FLOCK /* Flock version */ -gboolean +gboolean lock_file (gint fd, gboolean async) { - gint flags; + gint flags; - if (async) { - flags = LOCK_EX | LOCK_NB; - } - else { - flags = LOCK_EX; - } + if (async) { + flags = LOCK_EX | LOCK_NB; + } + else { + flags = LOCK_EX; + } - if (flock (fd, flags) == -1) { - if (async && errno == EAGAIN) { - return FALSE; - } - msg_warn ("lock on file failed: %s", strerror (errno)); - return FALSE; - } + if (flock (fd, flags) == -1) { + if (async && errno == EAGAIN) { + return FALSE; + } + msg_warn ("lock on file failed: %s", strerror (errno)); + return FALSE; + } - return TRUE; + return TRUE; } -gboolean +gboolean unlock_file (gint fd, gboolean async) { - gint flags; + gint flags; - if (async) { - flags = LOCK_UN | LOCK_NB; - } - else { - flags = LOCK_UN; - } + if (async) { + flags = LOCK_UN | LOCK_NB; + } + else { + flags = LOCK_UN; + } - if (flock (fd, flags) == -1) { - if (async && errno == EAGAIN) { - return FALSE; - } - msg_warn ("lock on file failed: %s", strerror (errno)); - return FALSE; - } + if (flock (fd, flags) == -1) { + if (async && errno == EAGAIN) { + return FALSE; + } + msg_warn ("lock on file failed: %s", strerror (errno)); + return FALSE; + } - return TRUE; + return TRUE; } #else /* HAVE_FLOCK */ /* Fctnl version */ -gboolean +gboolean lock_file (gint fd, gboolean async) { - struct flock fl = { - .l_type = F_WRLCK, - .l_whence = SEEK_SET, - .l_start = 0, - .l_len = 0 - }; + struct flock fl = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0 + }; - if (fcntl (fd, async ? F_SETLK : F_SETLKW, &fl) == -1) { - if (async && (errno == EAGAIN || errno == EACCES)) { - return FALSE; - } - msg_warn ("lock on file failed: %s", strerror (errno)); - return FALSE; - } + if (fcntl (fd, async ? F_SETLK : F_SETLKW, &fl) == -1) { + if (async && (errno == EAGAIN || errno == EACCES)) { + return FALSE; + } + msg_warn ("lock on file failed: %s", strerror (errno)); + return FALSE; + } - return TRUE; + return TRUE; } -gboolean +gboolean unlock_file (gint fd, gboolean async) { - struct flock fl = { - .l_type = F_UNLCK, - .l_whence = SEEK_SET, - .l_start = 0, - .l_len = 0 - }; + struct flock fl = { + .l_type = F_UNLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0 + }; - if (fcntl (fd, async ? F_SETLK : F_SETLKW, &fl) == -1) { - if (async && (errno == EAGAIN || errno == EACCES)) { - return FALSE; - } - msg_warn ("lock on file failed: %s", strerror (errno)); - return FALSE; - } + if (fcntl (fd, async ? F_SETLK : F_SETLKW, &fl) == -1) { + if (async && (errno == EAGAIN || errno == EACCES)) { + return FALSE; + } + msg_warn ("lock on file failed: %s", strerror (errno)); + return FALSE; + } - return TRUE; + return TRUE; } #endif /* HAVE_FLOCK */ @@ -1339,14 +1406,14 @@ rspamd_strlcpy_tolower (gchar *dst, const gchar *src, gsize siz) gint compare_email_func (gconstpointer a, gconstpointer b) { - const struct uri *u1 = a, *u2 = b; - gint r; + const struct uri *u1 = a, *u2 = b; + gint r; if (u1->hostlen != u2->hostlen || u1->hostlen == 0) { return u1->hostlen - u2->hostlen; } else { - if ((r = g_ascii_strncasecmp (u1->host, u2->host, u1->hostlen)) == 0){ + if ((r = g_ascii_strncasecmp (u1->host, u2->host, u1->hostlen)) == 0) { if (u1->userlen != u2->userlen || u1->userlen == 0) { return u1->userlen - u2->userlen; } @@ -1365,8 +1432,8 @@ compare_email_func (gconstpointer a, gconstpointer b) gint compare_url_func (gconstpointer a, gconstpointer b) { - const struct uri *u1 = a, *u2 = b; - int r; + const struct uri *u1 = a, *u2 = b; + int r; if (u1->hostlen != u2->hostlen || u1->hostlen == 0) { return u1->hostlen - u2->hostlen; @@ -1388,15 +1455,15 @@ compare_url_func (gconstpointer a, gconstpointer b) gchar * rspamd_strncasestr (const gchar *s, const gchar *find, gint len) { - gchar c, sc; - gsize mlen; + gchar c, sc; + gsize mlen; if ((c = *find++) != 0) { c = g_ascii_tolower (c); mlen = strlen (find); do { do { - if ((sc = *s++) == 0 || len -- == 0) + if ((sc = *s++) == 0 || len-- == 0) return (NULL); } while (g_ascii_tolower (sc) != c); } while (g_ascii_strncasecmp (s, find, mlen) != 0); @@ -1411,16 +1478,16 @@ rspamd_strncasestr (const gchar *s, const gchar *find, gint len) gboolean rspamd_strtol (const gchar *s, gsize len, glong *value) { - const gchar *p = s, *end = s + len; - gchar c; - glong v = 0; - const glong cutoff = G_MAXLONG / 10, cutlim = G_MAXLONG % 10; - gboolean neg; + const gchar *p = s, *end = s + len; + gchar c; + glong v = 0; + const glong cutoff = G_MAXLONG / 10, cutlim = G_MAXLONG % 10; + gboolean neg; /* Case negative values */ if (*p == '-') { neg = TRUE; - p ++; + p++; } else { neg = FALSE; @@ -1444,7 +1511,7 @@ rspamd_strtol (const gchar *s, gsize len, glong *value) else { return FALSE; } - p ++; + p++; } *value = neg ? -(v) : v; @@ -1457,10 +1524,10 @@ rspamd_strtol (const gchar *s, gsize len, glong *value) gboolean rspamd_strtoul (const gchar *s, gsize len, gulong *value) { - const gchar *p = s, *end = s + len; - gchar c; - gulong v = 0; - const gulong cutoff = G_MAXULONG / 10, cutlim = G_MAXULONG % 10; + const gchar *p = s, *end = s + len; + gchar c; + gulong v = 0; + const gulong cutoff = G_MAXULONG / 10, cutlim = G_MAXULONG % 10; /* Some preparations for range errors */ while (p < end) { @@ -1480,7 +1547,7 @@ rspamd_strtoul (const gchar *s, gsize len, gulong *value) else { return FALSE; } - p ++; + p++; } *value = v; @@ -1505,10 +1572,10 @@ rspamd_fallocate (gint fd, off_t offset, off_t len) * Create new mutex * @return mutex or NULL */ -inline rspamd_mutex_t* +inline rspamd_mutex_t * rspamd_mutex_new (void) { - rspamd_mutex_t *new; + rspamd_mutex_t *new; new = g_slice_alloc (sizeof (rspamd_mutex_t)); #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30)) @@ -1561,10 +1628,10 @@ rspamd_mutex_free (rspamd_mutex_t *mtx) * Create new rwlock * @return */ -rspamd_rwlock_t* +rspamd_rwlock_t * rspamd_rwlock_new (void) { - rspamd_rwlock_t *new; + rspamd_rwlock_t *new; new = g_malloc (sizeof (rspamd_rwlock_t)); #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30)) @@ -1651,8 +1718,8 @@ struct rspamd_thread_data { static gpointer rspamd_thread_func (gpointer ud) { - struct rspamd_thread_data *td = ud; - sigset_t s_mask; + struct rspamd_thread_data *td = ud; + sigset_t s_mask; /* Ignore signals in thread */ sigemptyset (&s_mask); @@ -1682,13 +1749,16 @@ rspamd_thread_func (gpointer ud) * @param err error pointer * @return new thread object that can be joined */ -GThread* -rspamd_create_thread (const gchar *name, GThreadFunc func, gpointer data, GError **err) +GThread * +rspamd_create_thread (const gchar *name, + GThreadFunc func, + gpointer data, + GError **err) { - GThread *new; - struct rspamd_thread_data *td; - static gint32 id; - guint r; + GThread *new; + struct rspamd_thread_data *td; + static gint32 id; + guint r; r = strlen (name); td = g_malloc (sizeof (struct rspamd_thread_data)); @@ -1712,15 +1782,15 @@ murmur32_hash (const guint8 *in, gsize len) { - const guint32 c1 = 0xcc9e2d51; - const guint32 c2 = 0x1b873593; + const guint32 c1 = 0xcc9e2d51; + const guint32 c2 = 0x1b873593; - const int nblocks = len / 4; - const guint32 *blocks = (const guint32 *)(in); - const guint8 *tail; - guint32 h = 0; - gint i; - guint32 k; + const int nblocks = len / 4; + const guint32 *blocks = (const guint32 *)(in); + const guint8 *tail; + guint32 h = 0; + gint i; + guint32 k; if (in == NULL || len == 0) { return 0; @@ -1768,15 +1838,15 @@ murmur32_hash (const guint8 *in, gsize len) void murmur128_hash (const guint8 *in, gsize len, guint64 out[]) { - const guint64 c1 = 0x87c37b91114253d5ULL; - const guint64 c2 = 0x4cf5ad432745937fULL; - const gint nblocks = len / 16; - const guint64 *blocks = (const guint64 *)(in); - const guint8 *tail; - guint64 h1 = 0; - guint64 h2 = 0; - int i; - guint64 k1, k2; + const guint64 c1 = 0x87c37b91114253d5ULL; + const guint64 c2 = 0x4cf5ad432745937fULL; + const gint nblocks = len / 16; + const guint64 *blocks = (const guint64 *)(in); + const guint8 *tail; + guint64 h1 = 0; + guint64 h2 = 0; + int i; + guint64 k1, k2; if (in == NULL || len == 0 || out == NULL) { return; @@ -1785,26 +1855,26 @@ murmur128_hash (const guint8 *in, gsize len, guint64 out[]) tail = (const guint8 *)(in + (nblocks * 16)); for (i = 0; i < nblocks; i++) { - k1 = blocks[i*2+0]; - k2 = blocks[i*2+1]; + k1 = blocks[i * 2 + 0]; + k2 = blocks[i * 2 + 1]; k1 *= c1; - k1 = (k1 << 31) | (k1 >> (64 - 31)); + k1 = (k1 << 31) | (k1 >> (64 - 31)); k1 *= c2; h1 ^= k1; h1 = (h1 << 27) | (h1 >> (64 - 27)); h1 += h2; - h1 = h1*5+0x52dce729; + h1 = h1 * 5 + 0x52dce729; k2 *= c2; - k2 = (k2 << 33) | (k2 >> (64 - 33)); + k2 = (k2 << 33) | (k2 >> (64 - 33)); k2 *= c1; h2 ^= k2; h2 = (h2 << 31) | (h2 >> (64 - 31)); h2 += h1; - h2 = h2*5+0x38495ab5; + h2 = h2 * 5 + 0x38495ab5; } k1 = k2 = 0; @@ -1824,7 +1894,7 @@ murmur128_hash (const guint8 *in, gsize len, guint64 out[]) case 9: k2 ^= (guint64)(tail[ 8]) << 0; k2 *= c2; - k2 = (k2 << 33) | (k2 >> (64 - 33)); + k2 = (k2 << 33) | (k2 >> (64 - 33)); k2 *= c1; h2 ^= k2; @@ -1845,7 +1915,7 @@ murmur128_hash (const guint8 *in, gsize len, guint64 out[]) case 1: k1 ^= (guint64)(tail[ 0]) << 0; k1 *= c1; - k1 = (k1 << 31) | (k1 >> (64 - 31)); + k1 = (k1 << 31) | (k1 >> (64 - 31)); k1 *= c2; h1 ^= k1; }; @@ -1888,11 +1958,13 @@ struct hash_copy_callback_data { static void copy_foreach_callback (gpointer key, gpointer value, gpointer ud) { - struct hash_copy_callback_data *cb = ud; - gpointer nkey, nvalue; + struct hash_copy_callback_data *cb = ud; + gpointer nkey, nvalue; nkey = cb->key_copy_func ? cb->key_copy_func (key, cb->ud) : (gpointer)key; - nvalue = cb->value_copy_func ? cb->value_copy_func (value, cb->ud) : (gpointer)value; + nvalue = + cb->value_copy_func ? cb->value_copy_func (value, + cb->ud) : (gpointer)value; g_hash_table_insert (cb->dst, nkey, nvalue); } /** @@ -1903,12 +1975,13 @@ copy_foreach_callback (gpointer key, gpointer value, gpointer ud) * @param value_copy_func function called to copy or modify values (or NULL) * @param ud user data for copy functions */ -void rspamd_hash_table_copy (GHashTable *src, GHashTable *dst, - gpointer (*key_copy_func)(gconstpointer data, gpointer ud), - gpointer (*value_copy_func)(gconstpointer data, gpointer ud), - gpointer ud) +void +rspamd_hash_table_copy (GHashTable *src, GHashTable *dst, + gpointer (*key_copy_func)(gconstpointer data, gpointer ud), + gpointer (*value_copy_func)(gconstpointer data, gpointer ud), + gpointer ud) { - struct hash_copy_callback_data cb; + struct hash_copy_callback_data cb; if (src != NULL && dst != NULL) { cb.key_copy_func = key_copy_func; cb.value_copy_func = value_copy_func; @@ -1927,7 +2000,7 @@ void rspamd_hash_table_copy (GHashTable *src, GHashTable *dst, gpointer rspamd_str_pool_copy (gconstpointer data, gpointer ud) { - rspamd_mempool_t *pool = ud; + rspamd_mempool_t *pool = ud; return data ? rspamd_mempool_strdup (pool, data) : NULL; } @@ -1941,7 +2014,8 @@ parse_ipmask_v4 (const char *line, struct in_addr *ina, int *mask) bzero (ip_buf, sizeof (ip_buf)); if ((pos = strchr (line, '/')) != NULL) { - rspamd_strlcpy (ip_buf, line, MIN ((gsize)(pos - line), sizeof (ip_buf))); + rspamd_strlcpy (ip_buf, line, + MIN ((gsize)(pos - line), sizeof (ip_buf))); rspamd_strlcpy (mask_buf, pos + 1, sizeof (mask_buf)); } else { @@ -1971,7 +2045,8 @@ parse_ipmask_v4 (const char *line, struct in_addr *ina, int *mask) static volatile sig_atomic_t saved_signo[NSIG]; static -void read_pass_tmp_sig_handler (int s) +void +read_pass_tmp_sig_handler (int s) { saved_signo[s] = 1; @@ -1988,7 +2063,8 @@ rspamd_read_passphrase (gchar *buf, gint size, gint rwflag, gpointer key) gint len = 0; gchar pass[BUFSIZ]; - if (readpassphrase ("Enter passphrase: ", buf, size, RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL) { + if (readpassphrase ("Enter passphrase: ", buf, size, RPP_ECHO_OFF | + RPP_REQUIRE_TTY) == NULL) { return 0; } @@ -2014,16 +2090,17 @@ restart: errno = ENOTTY; return 0; } - memcpy(&term, &oterm, sizeof(term)); + memcpy (&term, &oterm, sizeof(term)); term.c_lflag &= ~(ECHO | ECHONL); - (void)tcsetattr(input, TCSAFLUSH, &term); - (void)write (output, "Enter passphrase: ", sizeof ("Enter passphrase: ") - 1); + (void)tcsetattr (input, TCSAFLUSH, &term); + (void)write (output, "Enter passphrase: ", sizeof ("Enter passphrase: ") - + 1); /* Save the current sighandler */ for (i = 0; i < NSIG; i++) { saved_signo[i] = 0; } - sigemptyset(&sa.sa_mask); + sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = read_pass_tmp_sig_handler; (void)sigaction (SIGALRM, &sa, &savealrm); @@ -2050,7 +2127,7 @@ restart: /* Restore terminal state */ if (memcmp (&term, &oterm, sizeof (term)) != 0) { while (tcsetattr (input, TCSAFLUSH, &oterm) == -1 && - errno == EINTR && !saved_signo[SIGTTOU]); + errno == EINTR && !saved_signo[SIGTTOU]) ; } /* Restore signal handlers */ @@ -2069,7 +2146,7 @@ restart: /* Send signals pending */ for (i = 0; i < NSIG; i++) { if (saved_signo[i]) { - kill(getpid(), i); + kill (getpid (), i); switch (i) { case SIGTSTP: case SIGTTIN: @@ -2092,15 +2169,16 @@ rspamd_ip_is_valid (rspamd_inet_addr_t *addr) gboolean ret = FALSE; if (G_LIKELY (addr->af == AF_INET)) { - if (memcmp (&addr->addr.s4.sin_addr, &ip4_any, sizeof (struct in_addr)) != 0 && - memcmp (&addr->addr.s4.sin_addr, &ip4_none, - sizeof (struct in_addr)) != 0) { + if (memcmp (&addr->addr.s4.sin_addr, &ip4_any, + sizeof (struct in_addr)) != 0 && + memcmp (&addr->addr.s4.sin_addr, &ip4_none, + sizeof (struct in_addr)) != 0) { ret = TRUE; } } else if (G_UNLIKELY (addr->af == AF_INET6)) { if (memcmp (&addr->addr.s6.sin6_addr, &ip6_any, - sizeof (struct in6_addr)) != 0) { + sizeof (struct in6_addr)) != 0) { ret = TRUE; } } @@ -2173,7 +2251,9 @@ rspamd_gstring_append_double (double val, void *ud) } void -rspamd_ucl_emit_gstring (ucl_object_t *obj, enum ucl_emitter emit_type, GString *target) +rspamd_ucl_emit_gstring (ucl_object_t *obj, + enum ucl_emitter emit_type, + GString *target) { struct ucl_emitter_functions func = { .ucl_emitter_append_character = rspamd_gstring_append_character, @@ -2214,7 +2294,7 @@ rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t *addr) return (nfd); - out: +out: serrno = errno; close (nfd); errno = serrno; @@ -2243,7 +2323,7 @@ rspamd_parse_inet_address (rspamd_inet_addr_t *target, const char *src) return ret; } -const char* +const char * rspamd_inet_address_to_string (rspamd_inet_addr_t *addr) { static char addr_str[INET6_ADDRSTRLEN + 1]; @@ -2251,10 +2331,10 @@ rspamd_inet_address_to_string (rspamd_inet_addr_t *addr) switch (addr->af) { case AF_INET: return inet_ntop (addr->af, &addr->addr.s4.sin_addr, addr_str, - sizeof (addr_str)); + sizeof (addr_str)); case AF_INET6: return inet_ntop (addr->af, &addr->addr.s6.sin6_addr, addr_str, - sizeof (addr_str)); + sizeof (addr_str)); case AF_UNIX: return addr->addr.su.sun_path; } diff --git a/src/libutil/util.h b/src/libutil/util.h index a142f15fb..16765193f 100644 --- a/src/libutil/util.h +++ b/src/libutil/util.h @@ -44,7 +44,11 @@ gint make_udp_socket (struct addrinfo *, gboolean is_server, gboolean async); /* * Create and bind or connect unix socket */ -gint make_unix_socket (const gchar *, struct sockaddr_un *, gint type, gboolean is_server, gboolean async); +gint make_unix_socket (const gchar *, + struct sockaddr_un *, + gint type, + gboolean is_server, + gboolean async); /** * Make a universal socket @@ -56,7 +60,7 @@ gint make_unix_socket (const gchar *, struct sockaddr_un *, gint type, gboolean * @param try_resolve try name resolution for a socket (BLOCKING) */ gint make_universal_socket (const gchar *credits, guint16 port, gint type, - gboolean async, gboolean is_server, gboolean try_resolve); + gboolean async, gboolean is_server, gboolean try_resolve); /** * Make a universal sockets @@ -67,8 +71,12 @@ gint make_universal_socket (const gchar *credits, guint16 port, gint type, * @param is_server make this socket as server socket * @param try_resolve try name resolution for a socket (BLOCKING) */ -GList* make_universal_sockets_list (const gchar *credits, guint16 port, gint type, - gboolean async, gboolean is_server, gboolean try_resolve); +GList * make_universal_sockets_list (const gchar *credits, + guint16 port, + gint type, + gboolean async, + gboolean is_server, + gboolean try_resolve); /* * Create socketpair */ @@ -97,7 +105,9 @@ gint poll_sync_socket (gint fd, gint timeout, short events); * Init signals */ #ifdef HAVE_SA_SIGINFO -void init_signals (struct sigaction *sa, void (*sig_handler)(gint, siginfo_t *, void *)); +void init_signals (struct sigaction *sa, void (*sig_handler)(gint, + siginfo_t *, + void *)); #else void init_signals (struct sigaction *sa, void (*sig_handler)(gint)); #endif @@ -115,8 +125,8 @@ void convert_to_lowercase (gchar *str, guint size); /* * Process title utility functions */ -gint init_title(gint argc, gchar *argv[], gchar *envp[]); -gint setproctitle(const gchar *fmt, ...); +gint init_title (gint argc, gchar *argv[], gchar *envp[]); +gint setproctitle (const gchar *fmt, ...); #endif #ifndef HAVE_PIDFILE @@ -126,19 +136,21 @@ gint setproctitle(const gchar *fmt, ...); typedef struct rspamd_pidfh_s { gint pf_fd; #ifdef HAVE_PATH_MAX - gchar pf_path[PATH_MAX + 1]; + gchar pf_path[PATH_MAX + 1]; #elif defined(HAVE_MAXPATHLEN) - gchar pf_path[MAXPATHLEN + 1]; + gchar pf_path[MAXPATHLEN + 1]; #else - gchar pf_path[1024 + 1]; + gchar pf_path[1024 + 1]; #endif - dev_t pf_dev; - ino_t pf_ino; + dev_t pf_dev; + ino_t pf_ino; } rspamd_pidfh_t; -rspamd_pidfh_t *rspamd_pidfile_open(const gchar *path, mode_t mode, pid_t *pidptr); -gint rspamd_pidfile_write(rspamd_pidfh_t *pfh); -gint rspamd_pidfile_close(rspamd_pidfh_t *pfh); -gint rspamd_pidfile_remove(rspamd_pidfh_t *pfh); +rspamd_pidfh_t * rspamd_pidfile_open (const gchar *path, + mode_t mode, + pid_t *pidptr); +gint rspamd_pidfile_write (rspamd_pidfh_t *pfh); +gint rspamd_pidfile_close (rspamd_pidfh_t *pfh); +gint rspamd_pidfile_remove (rspamd_pidfh_t *pfh); #else typedef struct pidfh rspamd_pidfh_t; #define rspamd_pidfile_open pidfile_open @@ -150,14 +162,22 @@ typedef struct pidfh rspamd_pidfh_t; /* * Replace %r with rcpt value and %f with from value, new string is allocated in pool */ -gchar* resolve_stat_filename (rspamd_mempool_t *pool, gchar *pattern, gchar *rcpt, gchar *from); +gchar * resolve_stat_filename (rspamd_mempool_t *pool, + gchar *pattern, + gchar *rcpt, + gchar *from); #ifdef HAVE_CLOCK_GETTIME /* * Calculate check time with specified resolution of timer */ -const gchar* calculate_check_time (struct timeval *tv, struct timespec *begin, gint resolution, guint32 *scan_ms); +const gchar * calculate_check_time (struct timeval *tv, + struct timespec *begin, + gint resolution, + guint32 *scan_ms); #else -const gchar* calculate_check_time (struct timeval *begin, gint resolution, guint32 *scan_ms); +const gchar * calculate_check_time (struct timeval *begin, + gint resolution, + guint32 *scan_ms); #endif /* @@ -225,8 +245,12 @@ gsize rspamd_strlcpy_tolower (gchar *dst, const gchar *src, gsize siz); /* * Convert milliseconds to timeval fields */ -#define msec_to_tv(msec, tv) do { (tv)->tv_sec = (msec) / 1000; (tv)->tv_usec = ((msec) - (tv)->tv_sec * 1000) * 1000; } while(0) -#define double_to_tv(dbl, tv) do { (tv)->tv_sec = (int)(dbl); (tv)->tv_usec = ((dbl) - (int)(dbl))*1000*1000; } while(0) +#define msec_to_tv(msec, tv) do { (tv)->tv_sec = (msec) / 1000; (tv)->tv_usec = \ + ((msec) - (tv)->tv_sec * 1000) * 1000; \ +} while (0) +#define double_to_tv(dbl, tv) do { (tv)->tv_sec = (int)(dbl); (tv)->tv_usec = \ + ((dbl) - (int)(dbl)) * 1000 * 1000; \ +} while (0) #define tv_to_msec(tv) (tv)->tv_sec * 1000 + (tv)->tv_usec / 1000 /* Compare two emails for building emails tree */ @@ -238,7 +262,7 @@ gint compare_url_func (gconstpointer a, gconstpointer b); /* * Find string find in string s ignoring case */ -gchar* rspamd_strncasestr (const gchar *s, const gchar *find, gint len); +gchar * rspamd_strncasestr (const gchar *s, const gchar *find, gint len); /* * Try to convert string of length to long @@ -283,7 +307,7 @@ typedef struct rspamd_rwlock_s { * Create new mutex * @return mutex or NULL */ -rspamd_mutex_t* rspamd_mutex_new (void); +rspamd_mutex_t * rspamd_mutex_new (void); /** * Lock mutex @@ -307,7 +331,7 @@ void rspamd_mutex_free (rspamd_mutex_t *mtx); * Create new rwloc * @return */ -rspamd_rwlock_t* rspamd_rwlock_new (void); +rspamd_rwlock_t * rspamd_rwlock_new (void); /** * Lock rwlock for writing @@ -357,7 +381,10 @@ rspamd_cond_wait (GCond *cond, rspamd_mutex_t *mtx) * @param err error pointer * @return new thread object that can be joined */ -GThread* rspamd_create_thread (const gchar *name, GThreadFunc func, gpointer data, GError **err); +GThread * rspamd_create_thread (const gchar *name, + GThreadFunc func, + gpointer data, + GError **err); /** * Return 32bit murmur hash value for specified input @@ -403,9 +430,9 @@ void murmur128_hash (const guint8 *in, gsize len, guint64 out[]); * @param ud user data for copy functions */ void rspamd_hash_table_copy (GHashTable *src, GHashTable *dst, - gpointer (*key_copy_func)(gconstpointer data, gpointer ud), - gpointer (*value_copy_func)(gconstpointer data, gpointer ud), - gpointer ud); + gpointer (*key_copy_func)(gconstpointer data, gpointer ud), + gpointer (*value_copy_func)(gconstpointer data, gpointer ud), + gpointer ud); /** * Utility function to provide mem_pool copy for rspamd_hash_table_copy function @@ -448,7 +475,9 @@ gboolean rspamd_ip_is_valid (rspamd_inet_addr_t *addr); * @param emit_type emitter type * @param target target string */ -void rspamd_ucl_emit_gstring (ucl_object_t *obj, enum ucl_emitter emit_type, GString *target); +void rspamd_ucl_emit_gstring (ucl_object_t *obj, + enum ucl_emitter emit_type, + GString *target); /** * Accept from listening socket filling addr structure @@ -464,14 +493,15 @@ gint rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t *addr); * @param src IP string representation * @return TRUE if addr has been parsed */ -gboolean rspamd_parse_inet_address (rspamd_inet_addr_t *target, const char *src); +gboolean rspamd_parse_inet_address (rspamd_inet_addr_t *target, + const char *src); /** * Returns string representation of inet address * @param addr * @return statically allocated string pointer (not thread safe) */ -const char* rspamd_inet_address_to_string (rspamd_inet_addr_t *addr); +const char * rspamd_inet_address_to_string (rspamd_inet_addr_t *addr); /** * Returns port number for the specified inet address in host byte order diff --git a/src/lmtp.c b/src/lmtp.c index 946f8ca8b..1243b3265 100644 --- a/src/lmtp.c +++ b/src/lmtp.c @@ -32,21 +32,21 @@ #include "url.h" #include "message.h" -static gchar greetingbuf[1024]; -static struct timeval io_tv; +static gchar greetingbuf[1024]; +static struct timeval io_tv; -static gboolean lmtp_write_socket (void *arg); +static gboolean lmtp_write_socket (void *arg); void start_lmtp (struct rspamd_worker *worker); worker_t lmtp_worker = { - "controller", /* Name */ - NULL, /* Init function */ - start_lmtp, /* Start function */ - TRUE, /* Has socket */ - FALSE, /* Non unique */ - FALSE, /* Non threaded */ - TRUE /* Killable */ + "controller", /* Name */ + NULL, /* Init function */ + start_lmtp, /* Start function */ + TRUE, /* Has socket */ + FALSE, /* Non unique */ + FALSE, /* Non threaded */ + TRUE /* Killable */ }; #ifndef HAVE_SA_SIGINFO @@ -71,15 +71,16 @@ sig_handler (gint signo, siginfo_t *info, void *unused) static void sigusr2_handler (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *)arg; + struct rspamd_worker *worker = (struct rspamd_worker *)arg; /* Do not accept new connections, preparing to end worker's process */ - struct timeval tv; + struct timeval tv; tv.tv_sec = SOFT_SHUTDOWN_TIME; tv.tv_usec = 0; event_del (&worker->sig_ev_usr1); event_del (&worker->sig_ev_usr2); event_del (&worker->bind_ev); - msg_info ("lmtp worker's shutdown is pending in %d sec", SOFT_SHUTDOWN_TIME); + msg_info ("lmtp worker's shutdown is pending in %d sec", + SOFT_SHUTDOWN_TIME); event_loopexit (&tv); return; } @@ -90,7 +91,7 @@ sigusr2_handler (gint fd, short what, void *arg) static void sigusr1_handler (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *) arg; + struct rspamd_worker *worker = (struct rspamd_worker *) arg; reopen_log (worker->srv->logger); @@ -103,7 +104,7 @@ sigusr1_handler (gint fd, short what, void *arg) static void rcpt_destruct (void *pointer) { - struct rspamd_task *task = (struct rspamd_task *)pointer; + struct rspamd_task *task = (struct rspamd_task *)pointer; if (task->rcpt) { g_list_free (task->rcpt); @@ -116,9 +117,9 @@ rcpt_destruct (void *pointer) static void free_lmtp_task (struct rspamd_lmtp_proto *lmtp, gboolean is_soft) { - GList *part; - struct mime_part *p; - struct rspamd_task *task = lmtp->task; + GList *part; + struct mime_part *p; + struct rspamd_task *task = lmtp->task; if (lmtp) { debug_task ("free pointer %p", lmtp->task); @@ -145,12 +146,12 @@ free_lmtp_task (struct rspamd_lmtp_proto *lmtp, gboolean is_soft) /* * Callback that is called when there is data to read in buffer */ -static gboolean +static gboolean lmtp_read_socket (f_str_t * in, void *arg) { - struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg; - struct rspamd_task *task = lmtp->task; - ssize_t r; + struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg; + struct rspamd_task *task = lmtp->task; + ssize_t r; switch (task->state) { case READ_COMMAND: @@ -181,7 +182,8 @@ lmtp_read_socket (f_str_t * in, void *arg) } break; default: - debug_task ("invalid state while reading from socket %d", lmtp->task->state); + debug_task ("invalid state while reading from socket %d", + lmtp->task->state); break; } @@ -191,11 +193,11 @@ lmtp_read_socket (f_str_t * in, void *arg) /* * Callback for socket writing */ -static gboolean +static gboolean lmtp_write_socket (void *arg) { - struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg; - struct rspamd_task *task = lmtp->task; + struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg; + struct rspamd_task *task = lmtp->task; switch (lmtp->task->state) { case WRITE_REPLY: @@ -216,7 +218,8 @@ lmtp_write_socket (void *arg) return FALSE; break; default: - debug_task ("invalid state while writing to socket %d", lmtp->task->state); + debug_task ("invalid state while writing to socket %d", + lmtp->task->state); break; } @@ -229,7 +232,7 @@ lmtp_write_socket (void *arg) static void lmtp_err_socket (GError * err, void *arg) { - struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg; + struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg; msg_info ("abnormally closing connection, error: %s", err->message); /* Free buffers */ free_lmtp_task (lmtp, FALSE); @@ -241,14 +244,15 @@ lmtp_err_socket (GError * err, void *arg) static void accept_socket (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *)arg; - union sa_union su; - struct rspamd_task *new_task; - struct rspamd_lmtp_proto *lmtp; - socklen_t addrlen = sizeof (su.ss); - gint nfd; - - if ((nfd = accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) { + struct rspamd_worker *worker = (struct rspamd_worker *)arg; + union sa_union su; + struct rspamd_task *new_task; + struct rspamd_lmtp_proto *lmtp; + socklen_t addrlen = sizeof (su.ss); + gint nfd; + + if ((nfd = + accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) { msg_warn ("accept failed: %s", strerror (errno)); return; } @@ -262,26 +266,38 @@ accept_socket (gint fd, short what, void *arg) new_task->client_addr.s_addr = INADDR_NONE; } else if (su.ss.ss_family == AF_INET) { - msg_info ("accepted connection from %s port %d", inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port)); - memcpy (&new_task->client_addr, &su.s4.sin_addr, sizeof (struct in_addr)); + msg_info ("accepted connection from %s port %d", + inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port)); + memcpy (&new_task->client_addr, &su.s4.sin_addr, + sizeof (struct in_addr)); } new_task->sock = nfd; new_task->cfg = worker->srv->cfg; new_task->task_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); /* Add destructor for recipients list (it would be better to use anonymous function here */ - rspamd_mempool_add_destructor (new_task->task_pool, (rspamd_mempool_destruct_t) rcpt_destruct, new_task); + rspamd_mempool_add_destructor (new_task->task_pool, + (rspamd_mempool_destruct_t) rcpt_destruct, new_task); new_task->results = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); new_task->ev_base = worker->ctx; - rspamd_mempool_add_destructor (new_task->task_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, new_task->results); + rspamd_mempool_add_destructor (new_task->task_pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, new_task->results); worker->srv->stat->connections_count++; lmtp->task = new_task; lmtp->state = LMTP_READ_LHLO; /* Set up dispatcher */ - new_task->dispatcher = rspamd_create_dispatcher (new_task->ev_base, nfd, BUFFER_LINE, lmtp_read_socket, lmtp_write_socket, lmtp_err_socket, &io_tv, (void *)lmtp); + new_task->dispatcher = rspamd_create_dispatcher (new_task->ev_base, + nfd, + BUFFER_LINE, + lmtp_read_socket, + lmtp_write_socket, + lmtp_err_socket, + &io_tv, + (void *)lmtp); new_task->dispatcher->peer_addr = new_task->client_addr.s_addr; - if (! rspamd_dispatcher_write (lmtp->task->dispatcher, greetingbuf, strlen (greetingbuf), FALSE, FALSE)) { + if (!rspamd_dispatcher_write (lmtp->task->dispatcher, greetingbuf, + strlen (greetingbuf), FALSE, FALSE)) { msg_warn ("cannot write greeting"); } } @@ -292,10 +308,10 @@ accept_socket (gint fd, short what, void *arg) void start_lmtp (struct rspamd_worker *worker) { - struct sigaction signals; - gchar *hostbuf; - gsize hostmax; - module_t **mod; + struct sigaction signals; + gchar *hostbuf; + gsize hostmax; + module_t **mod; worker->srv->pid = getpid (); worker->ctx = event_init (); @@ -305,17 +321,23 @@ start_lmtp (struct rspamd_worker *worker) sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL); /* SIGUSR2 handler */ - signal_set (&worker->sig_ev_usr2, SIGUSR2, sigusr2_handler, (void *) worker); + signal_set (&worker->sig_ev_usr2, SIGUSR2, sigusr2_handler, + (void *) worker); event_base_set (worker->ctx, &worker->sig_ev_usr2); signal_add (&worker->sig_ev_usr2, NULL); /* SIGUSR1 handler */ - signal_set (&worker->sig_ev_usr1, SIGUSR1, sigusr1_handler, (void *) worker); + signal_set (&worker->sig_ev_usr1, SIGUSR1, sigusr1_handler, + (void *) worker); event_base_set (worker->ctx, &worker->sig_ev_usr1); signal_add (&worker->sig_ev_usr1, NULL); /* Accept event */ - event_set (&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_socket, (void *)worker); + event_set (&worker->bind_ev, + worker->cf->listen_sock, + EV_READ | EV_PERSIST, + accept_socket, + (void *)worker); event_base_set (worker->ctx, &worker->bind_ev); event_add (&worker->bind_ev, NULL); @@ -323,7 +345,7 @@ start_lmtp (struct rspamd_worker *worker) mod = &modules[0]; while (*mod) { (*mod)->module_config_func (worker->srv->cfg); - mod ++; + mod++; } /* Fill hostname buf */ @@ -331,7 +353,12 @@ start_lmtp (struct rspamd_worker *worker) hostbuf = alloca (hostmax); gethostname (hostbuf, hostmax); hostbuf[hostmax - 1] = '\0'; - rspamd_snprintf (greetingbuf, sizeof (greetingbuf), "%d rspamd version %s LMTP on %s Ready\r\n", LMTP_OK, RVERSION, hostbuf); + rspamd_snprintf (greetingbuf, + sizeof (greetingbuf), + "%d rspamd version %s LMTP on %s Ready\r\n", + LMTP_OK, + RVERSION, + hostbuf); io_tv.tv_sec = 60000; io_tv.tv_usec = 0; @@ -342,6 +369,6 @@ start_lmtp (struct rspamd_worker *worker) exit (EXIT_SUCCESS); } -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/lmtp_proto.c b/src/lmtp_proto.c index 81cd13607..67ca50e22 100644 --- a/src/lmtp_proto.c +++ b/src/lmtp_proto.c @@ -33,51 +33,53 @@ #define OUTBUFSIZ 1000 /* LMTP commands */ -static f_str_t lhlo_command = { +static f_str_t lhlo_command = { .begin = "LHLO", .len = sizeof ("LHLO") - 1 }; -static f_str_t mail_command = { +static f_str_t mail_command = { .begin = "MAIL FROM:", .len = sizeof ("MAIL FROM:") - 1 }; -static f_str_t rcpt_command = { +static f_str_t rcpt_command = { .begin = "RCPT TO:", .len = sizeof ("RCPT TO:") - 1 }; -static f_str_t data_command = { +static f_str_t data_command = { .begin = "DATA", .len = sizeof ("DATA") - 1 }; -static f_str_t data_dot = { +static f_str_t data_dot = { .begin = ".\r\n", .len = sizeof (".\r\n") - 1 }; -static const gchar *mail_regexp = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"; -static GRegex *mail_re = NULL; +static const gchar *mail_regexp = + "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"; +static GRegex *mail_re = NULL; /* - * Extract e-mail from read line + * Extract e-mail from read line * return <> if no valid address detected */ -static gchar * +static gchar * extract_mail (rspamd_mempool_t * pool, f_str_t * line) { - GError *err = NULL; - gchar *match; - GMatchInfo *info; + GError *err = NULL; + gchar *match; + GMatchInfo *info; if (mail_re == NULL) { /* Compile regexp */ mail_re = g_regex_new (mail_regexp, G_REGEX_RAW, 0, &err); } - if (g_regex_match_full (mail_re, line->begin, line->len, 0, 0, &info, NULL) == TRUE) { + if (g_regex_match_full (mail_re, line->begin, line->len, 0, 0, &info, + NULL) == TRUE) { match = rspamd_mempool_strdup (pool, g_match_info_fetch (info, 0)); g_match_info_free (info); } @@ -91,16 +93,18 @@ extract_mail (rspamd_mempool_t * pool, f_str_t * line) static gboolean out_lmtp_reply (struct rspamd_task *task, gint code, gchar *rcode, gchar *msg) { - gchar outbuf[OUTBUFSIZ]; - gint r; + gchar outbuf[OUTBUFSIZ]; + gint r; if (*rcode == '\0') { r = rspamd_snprintf (outbuf, OUTBUFSIZ, "%d %s\r\n", code, msg); } else { - r = rspamd_snprintf (outbuf, OUTBUFSIZ, "%d %s %s\r\n", code, rcode, msg); + r = + rspamd_snprintf (outbuf, OUTBUFSIZ, "%d %s %s\r\n", code, rcode, + msg); } - if (! rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE)) { return FALSE; } return TRUE; @@ -109,16 +113,19 @@ out_lmtp_reply (struct rspamd_task *task, gint code, gchar *rcode, gchar *msg) gint read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) { - gchar *c, *rcpt; - f_str_t fstr; - gint i = 0, l = 0, size; + gchar *c, *rcpt; + f_str_t fstr; + gint i = 0, l = 0, size; switch (lmtp->state) { case LMTP_READ_LHLO: /* Search LHLO line */ if ((i = fstrstri (line, &lhlo_command)) == -1) { msg_info ("LHLO expected but not found"); - (void)out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need LHLO here"); + (void)out_lmtp_reply (lmtp->task, + LMTP_BAD_CMD, + "5.0.0", + "Need LHLO here"); return -1; } else { @@ -129,11 +136,12 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) i++; c++; } - lmtp->task->helo = rspamd_mempool_alloc (lmtp->task->task_pool, line->len - i + 1); + lmtp->task->helo = rspamd_mempool_alloc (lmtp->task->task_pool, + line->len - i + 1); /* Strlcpy makes string null terminated by design */ rspamd_strlcpy (lmtp->task->helo, c, line->len - i + 1); lmtp->state = LMTP_READ_FROM; - if (! out_lmtp_reply (lmtp->task, LMTP_OK, "", "Ok")) { + if (!out_lmtp_reply (lmtp->task, LMTP_OK, "", "Ok")) { return -1; } return 0; @@ -143,7 +151,10 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) /* Search MAIL FROM: line */ if ((i = fstrstri (line, &mail_command)) == -1) { msg_info ("MAIL expected but not found"); - (void)out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need MAIL here"); + (void)out_lmtp_reply (lmtp->task, + LMTP_BAD_CMD, + "5.0.0", + "Need MAIL here"); return -1; } else { @@ -153,7 +164,7 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) fstr.len = line->len - i; lmtp->task->from = extract_mail (lmtp->task->task_pool, &fstr); lmtp->state = LMTP_READ_RCPT; - if (! out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Sender ok")) { + if (!out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Sender ok")) { return -1; } return 0; @@ -163,7 +174,10 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) /* Search RCPT_TO: line */ if ((i = fstrstri (line, &rcpt_command)) == -1) { msg_info ("RCPT expected but not found"); - (void)out_lmtp_reply (lmtp->task, LMTP_NO_RCPT, "5.5.4", "Need RCPT here"); + (void)out_lmtp_reply (lmtp->task, + LMTP_NO_RCPT, + "5.5.4", + "Need RCPT here"); return -1; } else { @@ -175,13 +189,17 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) if (*rcpt == '<' && *(rcpt + 1) == '>') { /* Invalid or empty rcpt not allowed */ msg_info ("bad recipient"); - (void)out_lmtp_reply (lmtp->task, LMTP_NO_RCPT, "5.5.4", "Bad recipient"); + (void)out_lmtp_reply (lmtp->task, + LMTP_NO_RCPT, + "5.5.4", + "Bad recipient"); return -1; } /* Strlcpy makes string null terminated by design */ lmtp->task->rcpt = g_list_prepend (lmtp->task->rcpt, rcpt); lmtp->state = LMTP_READ_DATA; - if (! out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Recipient ok")) { + if (!out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", + "Recipient ok")) { return -1; } return 0; @@ -191,7 +209,10 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) /* Search DATA line */ if ((i = fstrstri (line, &data_command)) == -1) { msg_info ("DATA expected but not found"); - (void)out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need DATA here"); + (void)out_lmtp_reply (lmtp->task, + LMTP_BAD_CMD, + "5.0.0", + "Need DATA here"); return -1; } else { @@ -201,12 +222,14 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) while (g_ascii_isspace (*c++)) { i++; } - rcpt = rspamd_mempool_alloc (lmtp->task->task_pool, line->len - i + 1); + rcpt = rspamd_mempool_alloc (lmtp->task->task_pool, + line->len - i + 1); /* Strlcpy makes string null terminated by design */ rspamd_strlcpy (rcpt, c, line->len - i + 1); lmtp->task->rcpt = g_list_prepend (lmtp->task->rcpt, rcpt); lmtp->state = LMTP_READ_MESSAGE; - if (! out_lmtp_reply (lmtp->task, LMTP_DATA, "", "Enter message, ending with \".\" on a line by itself")) { + if (!out_lmtp_reply (lmtp->task, LMTP_DATA, "", + "Enter message, ending with \".\" on a line by itself")) { return -1; } lmtp->task->msg = fstralloc (lmtp->task->task_pool, BUFSIZ); @@ -231,17 +254,19 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) /* size *= 2 */ size <<= 1; } - lmtp->task->msg = fstrgrow (lmtp->task->task_pool, lmtp->task->msg, size); + lmtp->task->msg = fstrgrow (lmtp->task->task_pool, + lmtp->task->msg, + size); } fstrcat (lmtp->task->msg, line); return 0; } break; case LMTP_READ_DOT: - /* We have some input after reading dot, close connection as we have no currently support of multiply + /* We have some input after reading dot, close connection as we have no currently support of multiply * messages per session */ - if (! out_lmtp_reply (lmtp->task, LMTP_QUIT, "", "Bye")) { + if (!out_lmtp_reply (lmtp->task, LMTP_QUIT, "", "Bye")) { return -1; } return 0; @@ -252,8 +277,8 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) } struct mta_callback_data { - struct rspamd_task *task; - rspamd_io_dispatcher_t *dispatcher; + struct rspamd_task *task; + rspamd_io_dispatcher_t *dispatcher; enum { LMTP_WANT_GREETING, LMTP_WANT_MAIL, @@ -264,18 +289,20 @@ struct mta_callback_data { } state; }; -static gboolean +static gboolean parse_mta_str (f_str_t * in, struct mta_callback_data *cd) { - gint r; - static f_str_t okres1 = { + gint r; + static f_str_t okres1 = { .begin = "250 ", .len = sizeof ("250 ") - 1, } , okres2 = { - .begin = "220 ",.len = sizeof ("220 ") - 1,} + .begin = "220 ",.len = sizeof ("220 ") - 1, + } , datares = { - .begin = "354 ",.len = sizeof ("354 ") - 1,}; + .begin = "354 ",.len = sizeof ("354 ") - 1, + }; switch (cd->state) { case LMTP_WANT_GREETING: @@ -301,12 +328,12 @@ close_mta_connection (struct mta_callback_data *cd, gboolean is_success) { cd->task->state = CLOSING_CONNECTION; if (is_success) { - if (! out_lmtp_reply (cd->task, LMTP_OK, "", "Delivery completed")) { + if (!out_lmtp_reply (cd->task, LMTP_OK, "", "Delivery completed")) { return; } } else { - if (! out_lmtp_reply (cd->task, LMTP_FAILURE, "", "Delivery failure")) { + if (!out_lmtp_reply (cd->task, LMTP_FAILURE, "", "Delivery failure")) { return; } } @@ -316,19 +343,20 @@ close_mta_connection (struct mta_callback_data *cd, gboolean is_success) /* * Callback that is called when there is data to read in buffer */ -static gboolean +static gboolean mta_read_socket (f_str_t * in, void *arg) { - struct mta_callback_data *cd = (struct mta_callback_data *)arg; - gchar outbuf[1024], *hostbuf, *c; - gint hostmax, r; - GList *cur; - static f_str_t contres1 = { + struct mta_callback_data *cd = (struct mta_callback_data *)arg; + gchar outbuf[1024], *hostbuf, *c; + gint hostmax, r; + GList *cur; + static f_str_t contres1 = { .begin = "250-", .len = sizeof ("250-") - 1, } , contres2 = { - .begin = "220-",.len = sizeof ("220-") - 1,}; + .begin = "220-",.len = sizeof ("220-") - 1, + }; if (fstrstr (in, &contres1) != -1 || fstrstr (in, &contres2) != -1) { /* Skip such lines */ @@ -347,12 +375,19 @@ mta_read_socket (f_str_t * in, void *arg) gethostname (hostbuf, hostmax); hostbuf[hostmax - 1] = '\0'; if (cd->task->cfg->deliver_lmtp) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "LHLO %s" CRLF, hostbuf); + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "LHLO %s" CRLF, + hostbuf); } else { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "HELO %s" CRLF, hostbuf); + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "HELO %s" CRLF, + hostbuf); } - if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, + FALSE)) { return FALSE; } cd->state = LMTP_WANT_MAIL; @@ -363,8 +398,12 @@ mta_read_socket (f_str_t * in, void *arg) close_mta_connection (cd, FALSE); return FALSE; } - r = rspamd_snprintf (outbuf, sizeof (outbuf), "MAIL FROM: <%s>" CRLF, cd->task->from); - if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) { + r = rspamd_snprintf (outbuf, + sizeof (outbuf), + "MAIL FROM: <%s>" CRLF, + cd->task->from); + if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, + FALSE)) { return FALSE; } cd->state = LMTP_WANT_RCPT; @@ -378,11 +417,15 @@ mta_read_socket (f_str_t * in, void *arg) cur = g_list_first (cd->task->rcpt); r = 0; while (cur) { - r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, "RCPT TO: <%s>" CRLF, (gchar *)cur->data); + r += rspamd_snprintf (outbuf + r, + sizeof (outbuf) - r, + "RCPT TO: <%s>" CRLF, + (gchar *)cur->data); cur = g_list_next (cur); } - if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, + FALSE)) { return FALSE; } cd->state = LMTP_WANT_DATA; @@ -394,7 +437,8 @@ mta_read_socket (f_str_t * in, void *arg) return FALSE; } r = rspamd_snprintf (outbuf, sizeof (outbuf), "DATA" CRLF); - if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, + FALSE)) { return FALSE; } cd->state = LMTP_WANT_DOT; @@ -407,12 +451,14 @@ mta_read_socket (f_str_t * in, void *arg) } c = g_mime_object_to_string ((GMimeObject *) cd->task->message); r = strlen (c); - if (! rspamd_dispatcher_write (cd->task->dispatcher, c, r, TRUE, TRUE)) { + if (!rspamd_dispatcher_write (cd->task->dispatcher, c, r, TRUE, TRUE)) { return FALSE; } - rspamd_mempool_add_destructor (cd->task->task_pool, (rspamd_mempool_destruct_t) g_free, c); + rspamd_mempool_add_destructor (cd->task->task_pool, + (rspamd_mempool_destruct_t) g_free, c); r = rspamd_snprintf (outbuf, sizeof (outbuf), CRLF "." CRLF); - if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) { + if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, + FALSE)) { return FALSE; } cd->state = LMTP_WANT_CLOSING; @@ -436,7 +482,7 @@ mta_read_socket (f_str_t * in, void *arg) static void mta_err_socket (GError * err, void *arg) { - struct mta_callback_data *cd = (struct mta_callback_data *)arg; + struct mta_callback_data *cd = (struct mta_callback_data *)arg; msg_info ("abnormaly terminating connection with MTA"); close_mta_connection (cd, FALSE); } @@ -447,36 +493,54 @@ mta_err_socket (GError * err, void *arg) static gint lmtp_deliver_mta (struct rspamd_task *task) { - gint sock; - struct sockaddr_un *un; - struct mta_callback_data *cd; + gint sock; + struct sockaddr_un *un; + struct mta_callback_data *cd; if (task->cfg->deliver_family == AF_UNIX) { un = alloca (sizeof (struct sockaddr_un)); - sock = make_unix_socket (task->cfg->deliver_host, un, SOCK_STREAM, FALSE, TRUE); + sock = make_unix_socket (task->cfg->deliver_host, + un, + SOCK_STREAM, + FALSE, + TRUE); } else { - sock = make_universal_socket (task->cfg->deliver_host, task->cfg->deliver_port, - SOCK_STREAM, TRUE, FALSE, TRUE); + sock = make_universal_socket (task->cfg->deliver_host, + task->cfg->deliver_port, + SOCK_STREAM, + TRUE, + FALSE, + TRUE); } if (sock == -1) { - msg_warn ("cannot create socket for %s, %s", task->cfg->deliver_host, strerror (errno)); + msg_warn ("cannot create socket for %s, %s", + task->cfg->deliver_host, + strerror (errno)); } - cd = rspamd_mempool_alloc (task->task_pool, sizeof (struct mta_callback_data)); + cd = rspamd_mempool_alloc (task->task_pool, + sizeof (struct mta_callback_data)); cd->task = task; cd->state = LMTP_WANT_GREETING; - cd->dispatcher = rspamd_create_dispatcher (task->ev_base, sock, BUFFER_LINE, mta_read_socket, NULL, mta_err_socket, NULL, (void *)cd); + cd->dispatcher = rspamd_create_dispatcher (task->ev_base, + sock, + BUFFER_LINE, + mta_read_socket, + NULL, + mta_err_socket, + NULL, + (void *)cd); return 0; } -static gchar * +static gchar * format_lda_args (struct rspamd_task *task) { - gchar *res, *c, *r; - size_t len; - GList *rcpt; - gboolean got_args = FALSE; + gchar *res, *c, *r; + size_t len; + GList *rcpt; + gboolean got_args = FALSE; c = task->cfg->deliver_agent_path; /* Find first arg */ @@ -557,10 +621,10 @@ format_lda_args (struct rspamd_task *task) static gint lmtp_deliver_lda (struct rspamd_task *task) { - gchar *args, **argv; - GMimeStream *stream; - gint rc, ecode, p[2], argc; - pid_t cpid, pid; + gchar *args, **argv; + GMimeStream *stream; + gint rc, ecode, p[2], argc; + pid_t cpid, pid; if ((args = format_lda_args (task)) == NULL) { return -1; @@ -609,7 +673,8 @@ lmtp_deliver_lda (struct rspamd_task *task) close (p[0]); stream = g_mime_stream_fs_new (p[1]); - if (g_mime_object_write_to_stream ((GMimeObject *) task->message, stream) == -1) { + if (g_mime_object_write_to_stream ((GMimeObject *) task->message, + stream) == -1) { g_strfreev (argv); msg_info ("cannot write stream to lda"); return -1; @@ -667,12 +732,13 @@ lmtp_deliver_message (struct rspamd_task *task) gint write_lmtp_reply (struct rspamd_lmtp_proto *lmtp) { - gint r; - struct rspamd_task *task = lmtp->task; + gint r; + struct rspamd_task *task = lmtp->task; debug_task ("writing reply to client"); if (lmtp->task->error_code != 0) { - if (! out_lmtp_reply (lmtp->task, lmtp->task->error_code, "", lmtp->task->last_error)) { + if (!out_lmtp_reply (lmtp->task, lmtp->task->error_code, "", + lmtp->task->last_error)) { return -1; } } @@ -683,7 +749,8 @@ write_lmtp_reply (struct rspamd_lmtp_proto *lmtp) return -1; } else if (r == 0) { - if (! out_lmtp_reply (lmtp->task, LMTP_OK, "", "Delivery completed")) { + if (!out_lmtp_reply (lmtp->task, LMTP_OK, "", + "Delivery completed")) { return -1; } } @@ -695,6 +762,6 @@ write_lmtp_reply (struct rspamd_lmtp_proto *lmtp) return 0; } -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/lua/lua_buffer.c b/src/lua/lua_buffer.c index 37c4fce61..4340a2b1f 100644 --- a/src/lua/lua_buffer.c +++ b/src/lua/lua_buffer.c @@ -25,7 +25,7 @@ #include "buffer.h" /* Public prototypes */ -struct rspamd_io_dispatcher_s *lua_check_io_dispatcher (lua_State * L); +struct rspamd_io_dispatcher_s * lua_check_io_dispatcher (lua_State * L); gint luaopen_io_dispatcher (lua_State * L); /* Lua bindings */ @@ -36,7 +36,7 @@ LUA_FUNCTION_DEF (io_dispatcher, pause); LUA_FUNCTION_DEF (io_dispatcher, restore); LUA_FUNCTION_DEF (io_dispatcher, destroy); -static const struct luaL_reg io_dispatcherlib_m[] = { +static const struct luaL_reg io_dispatcherlib_m[] = { LUA_INTERFACE_DEF (io_dispatcher, set_policy), LUA_INTERFACE_DEF (io_dispatcher, write), LUA_INTERFACE_DEF (io_dispatcher, pause), @@ -46,7 +46,7 @@ static const struct luaL_reg io_dispatcherlib_m[] = { {NULL, NULL} }; -static const struct luaL_reg io_dispatcherlib_f[] = { +static const struct luaL_reg io_dispatcherlib_f[] = { LUA_INTERFACE_DEF (io_dispatcher, create), {NULL, NULL} }; @@ -60,10 +60,10 @@ struct lua_dispatcher_cbdata { gint cbref_err; }; -struct rspamd_io_dispatcher_s * +struct rspamd_io_dispatcher_s * lua_check_io_dispatcher (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{io_dispatcher}"); + void *ud = luaL_checkudata (L, 1, "rspamd{io_dispatcher}"); luaL_argcheck (L, ud != NULL, 1, "'io_dispatcher' expected"); return ud ? *((struct rspamd_io_dispatcher_s **)ud) : NULL; } @@ -71,29 +71,31 @@ lua_check_io_dispatcher (lua_State * L) struct event_base * lua_check_event_base (lua_State *L) { - void *ud = luaL_checkudata (L, 1, "rspamd{ev_base}"); + void *ud = luaL_checkudata (L, 1, "rspamd{ev_base}"); luaL_argcheck (L, ud != NULL, 1, "'ev_base' expected"); return ud ? *((struct event_base **)ud) : NULL; } /* Dispatcher callbacks */ -static gboolean +static gboolean lua_io_read_cb (f_str_t * in, void *arg) { - struct lua_dispatcher_cbdata *cbdata = arg; - gboolean res; - rspamd_io_dispatcher_t **pdispatcher; + struct lua_dispatcher_cbdata *cbdata = arg; + gboolean res; + rspamd_io_dispatcher_t **pdispatcher; /* callback (dispatcher, data) */ lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref_read); - pdispatcher = lua_newuserdata (cbdata->L, sizeof (struct rspamd_io_dispatcher_s *)); + pdispatcher = + lua_newuserdata (cbdata->L, sizeof (struct rspamd_io_dispatcher_s *)); lua_setclass (cbdata->L, "rspamd{io_dispatcher}", -1); *pdispatcher = cbdata->d; lua_pushlstring (cbdata->L, in->begin, in->len); if (lua_pcall (cbdata->L, 2, 1, 0) != 0) { - msg_info ("call to session finalizer failed: %s", lua_tostring (cbdata->L, -1)); + msg_info ("call to session finalizer failed: %s", + lua_tostring (cbdata->L, -1)); } res = lua_toboolean (cbdata->L, -1); @@ -102,23 +104,26 @@ lua_io_read_cb (f_str_t * in, void *arg) return res; } -static gboolean +static gboolean lua_io_write_cb (void *arg) { - struct lua_dispatcher_cbdata *cbdata = arg; - gboolean res = FALSE; - rspamd_io_dispatcher_t **pdispatcher; + struct lua_dispatcher_cbdata *cbdata = arg; + gboolean res = FALSE; + rspamd_io_dispatcher_t **pdispatcher; if (cbdata->cbref_write) { lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref_read); /* callback (dispatcher) */ - pdispatcher = lua_newuserdata (cbdata->L, sizeof (struct rspamd_io_dispatcher_s *)); + pdispatcher = + lua_newuserdata (cbdata->L, + sizeof (struct rspamd_io_dispatcher_s *)); lua_setclass (cbdata->L, "rspamd{io_dispatcher}", -1); *pdispatcher = cbdata->d; if (lua_pcall (cbdata->L, 1, 1, 0) != 0) { - msg_info ("call to session finalizer failed: %s", lua_tostring (cbdata->L, -1)); + msg_info ("call to session finalizer failed: %s", + lua_tostring (cbdata->L, -1)); } res = lua_toboolean (cbdata->L, -1); @@ -131,18 +136,20 @@ lua_io_write_cb (void *arg) static void lua_io_err_cb (GError * err, void *arg) { - struct lua_dispatcher_cbdata *cbdata = arg; - rspamd_io_dispatcher_t **pdispatcher; + struct lua_dispatcher_cbdata *cbdata = arg; + rspamd_io_dispatcher_t **pdispatcher; /* callback (dispatcher, err) */ lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref_err); - pdispatcher = lua_newuserdata (cbdata->L, sizeof (struct rspamd_io_dispatcher_s *)); + pdispatcher = + lua_newuserdata (cbdata->L, sizeof (struct rspamd_io_dispatcher_s *)); lua_setclass (cbdata->L, "rspamd{io_dispatcher}", -1); *pdispatcher = cbdata->d; lua_pushstring (cbdata->L, err->message); if (lua_pcall (cbdata->L, 2, 0, 0) != 0) { - msg_info ("call to session finalizer failed: %s", lua_tostring (cbdata->L, -1)); + msg_info ("call to session finalizer failed: %s", + lua_tostring (cbdata->L, -1)); } /* Unref callbacks */ @@ -162,11 +169,11 @@ lua_io_err_cb (GError * err, void *arg) static int lua_io_dispatcher_create (lua_State *L) { - struct rspamd_io_dispatcher_s *io_dispatcher, **pdispatcher; - gint fd; - struct lua_dispatcher_cbdata *cbdata; - struct timeval tv = {0, 0}; - double tv_num, tmp; + struct rspamd_io_dispatcher_s *io_dispatcher, **pdispatcher; + gint fd; + struct lua_dispatcher_cbdata *cbdata; + struct timeval tv = {0, 0}; + double tv_num, tmp; if (lua_gettop (L) >= 5 && lua_isfunction (L, 3) && lua_isfunction (L, 5)) { cbdata = g_slice_alloc0 (sizeof (struct lua_dispatcher_cbdata)); @@ -193,20 +200,36 @@ lua_io_dispatcher_create (lua_State *L) tv_num = lua_tonumber (L, 6); tv.tv_sec = trunc (tv_num); tv.tv_usec = modf (tv_num, &tmp) * 1000.; - io_dispatcher = rspamd_create_dispatcher (cbdata->base, fd, BUFFER_LINE, lua_io_read_cb, lua_io_write_cb, lua_io_err_cb, &tv, cbdata); + io_dispatcher = rspamd_create_dispatcher (cbdata->base, + fd, + BUFFER_LINE, + lua_io_read_cb, + lua_io_write_cb, + lua_io_err_cb, + &tv, + cbdata); } else { - io_dispatcher = rspamd_create_dispatcher (cbdata->base, fd, BUFFER_LINE, lua_io_read_cb, lua_io_write_cb, lua_io_err_cb, NULL, cbdata); + io_dispatcher = rspamd_create_dispatcher (cbdata->base, + fd, + BUFFER_LINE, + lua_io_read_cb, + lua_io_write_cb, + lua_io_err_cb, + NULL, + cbdata); } cbdata->d = io_dispatcher; /* Push result */ - pdispatcher = lua_newuserdata (L, sizeof (struct rspamd_io_dispatcher_s *)); + pdispatcher = + lua_newuserdata (L, sizeof (struct rspamd_io_dispatcher_s *)); lua_setclass (L, "rspamd{io_dispatcher}", -1); *pdispatcher = io_dispatcher; } else { - msg_err ("invalid number of arguments to io_dispatcher.create: %d", lua_gettop (L)); + msg_err ("invalid number of arguments to io_dispatcher.create: %d", + lua_gettop (L)); lua_pushnil (L); } @@ -216,8 +239,8 @@ lua_io_dispatcher_create (lua_State *L) static int lua_io_dispatcher_set_policy (lua_State *L) { - struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); - gint policy, limit = -1; + struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); + gint policy, limit = -1; if (io_dispatcher) { policy = lua_tonumber (L, 2); @@ -242,14 +265,15 @@ lua_io_dispatcher_set_policy (lua_State *L) static int lua_io_dispatcher_write (lua_State *L) { - struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); - gboolean delayed = FALSE, res; - const gchar *data; - size_t len; + struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); + gboolean delayed = FALSE, res; + const gchar *data; + size_t len; if (io_dispatcher) { if (lua_gettop (L) < 2) { - msg_err ("invalid number of arguments to io_dispatcher.create: %d", lua_gettop (L)); + msg_err ("invalid number of arguments to io_dispatcher.create: %d", + lua_gettop (L)); lua_pushboolean (L, FALSE); } else { @@ -257,7 +281,11 @@ lua_io_dispatcher_write (lua_State *L) if (lua_gettop (L) > 2) { delayed = lua_toboolean (L, 3); } - res = rspamd_dispatcher_write (io_dispatcher, (void *)data, len, delayed, FALSE); + res = rspamd_dispatcher_write (io_dispatcher, + (void *)data, + len, + delayed, + FALSE); lua_pushboolean (L, res); } } @@ -271,7 +299,7 @@ lua_io_dispatcher_write (lua_State *L) static int lua_io_dispatcher_pause (lua_State *L) { - struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); + struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); if (io_dispatcher) { rspamd_dispatcher_pause (io_dispatcher); @@ -287,7 +315,7 @@ lua_io_dispatcher_pause (lua_State *L) static int lua_io_dispatcher_restore (lua_State *L) { - struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); + struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); if (io_dispatcher) { rspamd_dispatcher_restore (io_dispatcher); @@ -303,7 +331,7 @@ lua_io_dispatcher_restore (lua_State *L) static int lua_io_dispatcher_destroy (lua_State *L) { - struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); + struct rspamd_io_dispatcher_s *io_dispatcher = lua_check_io_dispatcher (L); if (io_dispatcher) { rspamd_remove_dispatcher (io_dispatcher); @@ -329,16 +357,16 @@ luaopen_io_dispatcher (lua_State * L) lua_pushstring (L, "rspamd{io_dispatcher}"); lua_rawset (L, -3); - luaL_register (L, NULL, io_dispatcherlib_m); + luaL_register (L, NULL, io_dispatcherlib_m); luaL_register (L, "rspamd_io_dispatcher", io_dispatcherlib_f); - lua_pop(L, 1); /* remove metatable from stack */ + lua_pop (L, 1); /* remove metatable from stack */ /* Simple event class */ lua_newclass (L, "rspamd{ev_base}", null_reg); luaL_register (L, "rspamd_ev_base", null_reg); - lua_pop(L, 1); /* remove metatable from stack */ + lua_pop (L, 1); /* remove metatable from stack */ /* Set buffer types globals */ lua_pushnumber (L, BUFFER_LINE); @@ -347,5 +375,5 @@ luaopen_io_dispatcher (lua_State * L) lua_setglobal (L, "IO_BUFFER_CHARACTER"); lua_pushnumber (L, BUFFER_ANY); lua_setglobal (L, "IO_BUFFER_ANY"); - return 1; + return 1; } diff --git a/src/lua/lua_cdb.c b/src/lua/lua_cdb.c index 6832dfe59..0b0821dd0 100644 --- a/src/lua/lua_cdb.c +++ b/src/lua/lua_cdb.c @@ -31,22 +31,22 @@ LUA_FUNCTION_DEF (cdb, lookup); LUA_FUNCTION_DEF (cdb, get_name); LUA_FUNCTION_DEF (cdb, destroy); -static const struct luaL_reg cdblib_m[] = { +static const struct luaL_reg cdblib_m[] = { LUA_INTERFACE_DEF (cdb, lookup), LUA_INTERFACE_DEF (cdb, get_name), {"__tostring", lua_class_tostring}, {"__gc", lua_cdb_destroy}, {NULL, NULL} }; -static const struct luaL_reg cdblib_f[] = { +static const struct luaL_reg cdblib_f[] = { LUA_INTERFACE_DEF (cdb, create), {NULL, NULL} }; -static struct cdb * +static struct cdb * lua_check_cdb (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{cdb}"); + void *ud = luaL_checkudata (L, 1, "rspamd{cdb}"); luaL_argcheck (L, ud != NULL, 1, "'cdb' expected"); return ud ? *((struct cdb **)ud) : NULL; @@ -55,9 +55,9 @@ lua_check_cdb (lua_State * L) static gint lua_cdb_create (lua_State *L) { - struct cdb *cdb, **pcdb; - const gchar *filename; - gint fd; + struct cdb *cdb, **pcdb; + const gchar *filename; + gint fd; filename = luaL_checkstring (L, 1); /* If file begins with cdb://, just skip it */ @@ -79,7 +79,7 @@ lua_cdb_create (lua_State *L) lua_pushnil (L); } else { - pcdb = lua_newuserdata (L, sizeof (struct cdb*)); + pcdb = lua_newuserdata (L, sizeof (struct cdb *)); lua_setclass (L, "rspamd{cdb}", -1); *pcdb = cdb; } @@ -91,7 +91,7 @@ lua_cdb_create (lua_State *L) static gint lua_cdb_get_name (lua_State *L) { - struct cdb *cdb = lua_check_cdb (L); + struct cdb *cdb = lua_check_cdb (L); lua_pushstring (L, cdb->filename); return 1; @@ -100,11 +100,11 @@ lua_cdb_get_name (lua_State *L) static gint lua_cdb_lookup (lua_State *L) { - struct cdb *cdb = lua_check_cdb (L); - const gchar *what; - gchar *value; - gsize vlen; - gint64 vpos; + struct cdb *cdb = lua_check_cdb (L); + const gchar *what; + gchar *value; + gsize vlen; + gint64 vpos; /* * XXX: this code is placed here because event_loop is called inside workers, so start @@ -134,7 +134,7 @@ lua_cdb_lookup (lua_State *L) static gint lua_cdb_destroy (lua_State *L) { - struct cdb *cdb = lua_check_cdb (L); + struct cdb *cdb = lua_check_cdb (L); if (cdb) { cdb_free (cdb); @@ -158,7 +158,7 @@ luaopen_cdb (lua_State * L) lua_pushstring (L, "rspamd{cdb}"); lua_rawset (L, -3); - luaL_register (L, NULL, cdblib_m); + luaL_register (L, NULL, cdblib_m); luaL_register (L, "cdb", cdblib_f); lua_pop (L, 1); /* remove metatable from stack */ diff --git a/src/lua/lua_cfg_file.c b/src/lua/lua_cfg_file.c index 83ac4545c..c17a85c6a 100644 --- a/src/lua/lua_cfg_file.c +++ b/src/lua/lua_cfg_file.c @@ -29,19 +29,19 @@ #include <sys/utsname.h> #endif -/* - * This is implementation of lua routines to handle config file params +/* + * This is implementation of lua routines to handle config file params */ /* Process a single item in 'metrics' table */ static void lua_process_metric (lua_State *L, const gchar *name, struct rspamd_config *cfg) { - GList *metric_list; - gchar *symbol, *old_desc; - const gchar *desc; - struct metric *metric; - gdouble *score, *old_score; + GList *metric_list; + gchar *symbol, *old_desc; + const gchar *desc; + struct metric *metric; + gdouble *score, *old_score; /* Get module opt structure */ if ((metric = g_hash_table_lookup (cfg->metrics, name)) == NULL) { @@ -50,16 +50,18 @@ lua_process_metric (lua_State *L, const gchar *name, struct rspamd_config *cfg) } /* Now iterate throught module table */ - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) { /* key - -2, value - -1 */ - symbol = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, -2)); + symbol = + rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, -2)); if (symbol != NULL) { if (lua_istable (L, -1)) { /* We got a table, so extract individual attributes */ lua_pushstring (L, "weight"); lua_gettable (L, -2); if (lua_isnumber (L, -1)) { - score = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (double)); + score = + rspamd_mempool_alloc (cfg->cfg_pool, sizeof (double)); *score = lua_tonumber (L, -1); } else { @@ -71,15 +73,19 @@ lua_process_metric (lua_State *L, const gchar *name, struct rspamd_config *cfg) lua_gettable (L, -2); if (lua_isstring (L, -1)) { desc = lua_tostring (L, -1); - old_desc = g_hash_table_lookup (metric->descriptions, symbol); + old_desc = + g_hash_table_lookup (metric->descriptions, symbol); if (old_desc) { - msg_info ("replacing description for symbol %s", symbol); + msg_info ("replacing description for symbol %s", + symbol); g_hash_table_replace (metric->descriptions, - symbol, rspamd_mempool_strdup (cfg->cfg_pool, desc)); + symbol, + rspamd_mempool_strdup (cfg->cfg_pool, desc)); } else { g_hash_table_insert (metric->descriptions, - symbol, rspamd_mempool_strdup (cfg->cfg_pool, desc)); + symbol, + rspamd_mempool_strdup (cfg->cfg_pool, desc)); } } lua_pop (L, 1); @@ -94,17 +100,23 @@ lua_process_metric (lua_State *L, const gchar *name, struct rspamd_config *cfg) continue; } /* Insert symbol */ - if ((old_score = g_hash_table_lookup (metric->symbols, symbol)) != NULL) { - msg_info ("replacing weight for symbol %s: %.2f -> %.2f", symbol, *old_score, *score); + if ((old_score = + g_hash_table_lookup (metric->symbols, symbol)) != NULL) { + msg_info ("replacing weight for symbol %s: %.2f -> %.2f", + symbol, + *old_score, + *score); g_hash_table_replace (metric->symbols, symbol, score); } else { g_hash_table_insert (metric->symbols, symbol, score); } - if ((metric_list = g_hash_table_lookup (cfg->metrics_symbols, symbol)) == NULL) { + if ((metric_list = + g_hash_table_lookup (cfg->metrics_symbols, symbol)) == NULL) { metric_list = g_list_prepend (NULL, metric); - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)g_list_free, metric_list); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)g_list_free, metric_list); g_hash_table_insert (cfg->metrics_symbols, symbol, metric_list); } else { @@ -121,26 +133,30 @@ lua_process_metric (lua_State *L, const gchar *name, struct rspamd_config *cfg) void lua_post_load_config (struct rspamd_config *cfg) { - lua_State *L = cfg->lua_state; - const gchar *name, *val; - gchar *sym; - struct expression *expr, *old_expr; - ucl_object_t *obj; - gsize keylen; + lua_State *L = cfg->lua_state; + const gchar *name, *val; + gchar *sym; + struct expression *expr, *old_expr; + ucl_object_t *obj; + gsize keylen; /* First check all module options that may be overriden in 'config' global */ lua_getglobal (L, "config"); if (lua_istable (L, -1)) { /* Iterate */ - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) { /* 'key' is at index -2 and 'value' is at index -1 */ /* Key must be a string and value must be a table */ name = luaL_checklstring (L, -2, &keylen); if (name != NULL && lua_istable (L, -1)) { obj = ucl_object_lua_import (L, lua_gettop (L)); if (obj != NULL) { - ucl_object_insert_key_merged (cfg->rcl_obj, obj, name, keylen, true); + ucl_object_insert_key_merged (cfg->rcl_obj, + obj, + name, + keylen, + true); } } } @@ -151,7 +167,7 @@ lua_post_load_config (struct rspamd_config *cfg) if (lua_istable (L, -1)) { /* Iterate */ - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) { /* 'key' is at index -2 and 'value' is at index -1 */ /* Key must be a string and value must be a table */ name = luaL_checkstring (L, -2); @@ -166,19 +182,23 @@ lua_post_load_config (struct rspamd_config *cfg) if (lua_istable (L, -1)) { /* Iterate */ - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) { /* 'key' is at index -2 and 'value' is at index -1 */ /* Key must be a string and value must be a table */ name = luaL_checkstring (L, -2); if (name != NULL && lua_isstring (L, -1)) { val = lua_tostring (L, -1); - sym = rspamd_mempool_strdup(cfg->cfg_pool, name); - if ((expr = parse_expression (cfg->cfg_pool, rspamd_mempool_strdup(cfg->cfg_pool, val))) == NULL) { + sym = rspamd_mempool_strdup (cfg->cfg_pool, name); + if ((expr = + parse_expression (cfg->cfg_pool, + rspamd_mempool_strdup (cfg->cfg_pool, val))) == NULL) { msg_err ("cannot parse composite expression: %s", val); continue; } /* Now check hash table for this composite */ - if ((old_expr = g_hash_table_lookup (cfg->composite_symbols, name)) != NULL) { + if ((old_expr = + g_hash_table_lookup (cfg->composite_symbols, + name)) != NULL) { msg_info ("replacing composite symbol %s", name); g_hash_table_replace (cfg->composite_symbols, sym, expr); } @@ -193,10 +213,14 @@ lua_post_load_config (struct rspamd_config *cfg) /* Handle lua dynamic config param */ gboolean -lua_handle_param (struct rspamd_task *task, gchar *mname, gchar *optname, enum lua_var_type expected_type, gpointer *res) +lua_handle_param (struct rspamd_task *task, + gchar *mname, + gchar *optname, + enum lua_var_type expected_type, + gpointer *res) { /* xxx: Adopt this for rcl */ - + /* Option not found */ *res = NULL; return FALSE; @@ -206,12 +230,12 @@ lua_handle_param (struct rspamd_task *task, gchar *mname, gchar *optname, enum l gboolean lua_check_condition (struct rspamd_config *cfg, const gchar *condition) { - lua_State *L = cfg->lua_state; - gchar *hostbuf, *condbuf; - gsize hostlen; - gboolean res; + lua_State *L = cfg->lua_state; + gchar *hostbuf, *condbuf; + gsize hostlen; + gboolean res; #ifdef HAVE_SYS_UTSNAME_H - struct utsname uts; + struct utsname uts; #endif /* Set some globals for condition */ @@ -250,12 +274,12 @@ lua_check_condition (struct rspamd_config *cfg, const gchar *condition) /* Rspamd paths */ lua_newtable (L); - lua_set_table_index (L, "confdir", RSPAMD_CONFDIR); - lua_set_table_index (L, "rundir", RSPAMD_RUNDIR); - lua_set_table_index (L, "dbdir", RSPAMD_DBDIR); - lua_set_table_index (L, "logdir", RSPAMD_LOGDIR); + lua_set_table_index (L, "confdir", RSPAMD_CONFDIR); + lua_set_table_index (L, "rundir", RSPAMD_RUNDIR); + lua_set_table_index (L, "dbdir", RSPAMD_DBDIR); + lua_set_table_index (L, "logdir", RSPAMD_LOGDIR); lua_set_table_index (L, "pluginsdir", RSPAMD_PLUGINSDIR); - lua_set_table_index (L, "prefix", RSPAMD_PREFIX); + lua_set_table_index (L, "prefix", RSPAMD_PREFIX); lua_setglobal (L, "rspamd_paths"); /* Make fake string */ @@ -271,10 +295,11 @@ lua_check_condition (struct rspamd_config *cfg, const gchar *condition) } /* Get global variable res to get result */ lua_getglobal (L, FAKE_RES_VAR); - if (! lua_isboolean (L, -1)) { - msg_err ("bad string evaluated: %s, type: %s", condbuf, lua_typename (L, lua_type (L, -1))); + if (!lua_isboolean (L, -1)) { + msg_err ("bad string evaluated: %s, type: %s", condbuf, + lua_typename (L, lua_type (L, -1))); g_free (condbuf); - return FALSE; + return FALSE; } res = lua_toboolean (L, -1); diff --git a/src/lua/lua_classifier.c b/src/lua/lua_classifier.c index d227fc5da..ecd3cf9fc 100644 --- a/src/lua/lua_classifier.c +++ b/src/lua/lua_classifier.c @@ -33,7 +33,7 @@ LUA_FUNCTION_DEF (classifier, register_post_callback); LUA_FUNCTION_DEF (classifier, get_statfiles); LUA_FUNCTION_DEF (classifier, get_statfile_by_label); -static const struct luaL_reg classifierlib_m[] = { +static const struct luaL_reg classifierlib_m[] = { LUA_INTERFACE_DEF (classifier, register_pre_callback), LUA_INTERFACE_DEF (classifier, register_post_callback), LUA_INTERFACE_DEF (classifier, get_statfiles), @@ -50,7 +50,7 @@ LUA_FUNCTION_DEF (statfile, get_size); LUA_FUNCTION_DEF (statfile, is_spam); LUA_FUNCTION_DEF (statfile, get_param); -static const struct luaL_reg statfilelib_m[] = { +static const struct luaL_reg statfilelib_m[] = { LUA_INTERFACE_DEF (statfile, get_symbol), LUA_INTERFACE_DEF (statfile, get_label), LUA_INTERFACE_DEF (statfile, get_path), @@ -66,27 +66,30 @@ struct classifier_callback_data { const gchar *name; }; -static struct rspamd_statfile_config* lua_check_statfile (lua_State * L); +static struct rspamd_statfile_config * lua_check_statfile (lua_State * L); /* Classifier implementation */ -static struct rspamd_classifier_config * +static struct rspamd_classifier_config * lua_check_classifier (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{classifier}"); + void *ud = luaL_checkudata (L, 1, "rspamd{classifier}"); luaL_argcheck (L, ud != NULL, 1, "'classifier' expected"); return ud ? *((struct rspamd_classifier_config **)ud) : NULL; } static GList * -call_classifier_pre_callback (struct rspamd_classifier_config *ccf, struct rspamd_task *task, - lua_State *L, gboolean is_learn, gboolean is_spam) +call_classifier_pre_callback (struct rspamd_classifier_config *ccf, + struct rspamd_task *task, + lua_State *L, + gboolean is_learn, + gboolean is_spam) { - struct rspamd_classifier_config **pccf; - struct rspamd_task **ptask; - struct rspamd_statfile_config **pst; - GList *res = NULL; + struct rspamd_classifier_config **pccf; + struct rspamd_task **ptask; + struct rspamd_statfile_config **pst; + GList *res = NULL; pccf = lua_newuserdata (L, sizeof (struct rspamd_classifier_config *)); lua_setclass (L, "rspamd{classifier}", -1); @@ -100,12 +103,13 @@ call_classifier_pre_callback (struct rspamd_classifier_config *ccf, struct rspam lua_pushboolean (L, is_spam); if (lua_pcall (L, 4, 1, 0) != 0) { - msg_warn ("error running pre classifier callback %s", lua_tostring (L, -1)); + msg_warn ("error running pre classifier callback %s", + lua_tostring (L, -1)); } else { if (lua_istable (L, -1)) { lua_pushnil (L); - while(lua_next (L, -2)) { + while (lua_next (L, -2)) { pst = luaL_checkudata (L, -1, "rspamd{statfile}"); if (pst) { res = g_list_prepend (res, *pst); @@ -120,10 +124,13 @@ call_classifier_pre_callback (struct rspamd_classifier_config *ccf, struct rspam /* Return list of statfiles that should be checked for this message */ GList * -call_classifier_pre_callbacks (struct rspamd_classifier_config *ccf, struct rspamd_task *task, - gboolean is_learn, gboolean is_spam, lua_State *L) +call_classifier_pre_callbacks (struct rspamd_classifier_config *ccf, + struct rspamd_task *task, + gboolean is_learn, + gboolean is_spam, + lua_State *L) { - GList *res = NULL, *cur; + GList *res = NULL, *cur; struct classifier_callback_data *cd; @@ -133,7 +140,9 @@ call_classifier_pre_callbacks (struct rspamd_classifier_config *ccf, struct rspa cd = cur->data; lua_getglobal (L, cd->name); - res = g_list_concat (res, call_classifier_pre_callback (ccf, task, L, is_learn, is_spam)); + res = + g_list_concat (res, + call_classifier_pre_callback (ccf, task, L, is_learn, is_spam)); cur = g_list_next (cur); } @@ -146,7 +155,11 @@ call_classifier_pre_callbacks (struct rspamd_classifier_config *ccf, struct rspa lua_gettable (L, -2); /* Function is now on top */ if (lua_isfunction (L, -1)) { - res = call_classifier_pre_callback (ccf, task, L, is_learn, is_spam); + res = call_classifier_pre_callback (ccf, + task, + L, + is_learn, + is_spam); } lua_pop (L, 1); } @@ -158,13 +171,16 @@ call_classifier_pre_callbacks (struct rspamd_classifier_config *ccf, struct rspa /* Return result mark for statfile */ double -call_classifier_post_callbacks (struct rspamd_classifier_config *ccf, struct rspamd_task *task, double in, lua_State *L) +call_classifier_post_callbacks (struct rspamd_classifier_config *ccf, + struct rspamd_task *task, + double in, + lua_State *L) { struct classifier_callback_data *cd; - struct rspamd_classifier_config **pccf; - struct rspamd_task **ptask; - double out = in; - GList *cur; + struct rspamd_classifier_config **pccf; + struct rspamd_task **ptask; + double out = in; + GList *cur; /* Go throught all callbacks and call them, appending results to list */ cur = g_list_first (ccf->pre_callbacks); @@ -183,7 +199,8 @@ call_classifier_post_callbacks (struct rspamd_classifier_config *ccf, struct rsp lua_pushnumber (L, out); if (lua_pcall (L, 3, 1, 0) != 0) { - msg_warn ("error running function %s: %s", cd->name, lua_tostring (L, -1)); + msg_warn ("error running function %s: %s", cd->name, + lua_tostring (L, -1)); } else { if (lua_isnumber (L, 1)) { @@ -202,9 +219,9 @@ call_classifier_post_callbacks (struct rspamd_classifier_config *ccf, struct rsp static gint lua_classifier_register_pre_callback (lua_State *L) { - struct rspamd_classifier_config *ccf = lua_check_classifier (L); + struct rspamd_classifier_config *ccf = lua_check_classifier (L); struct classifier_callback_data *cd; - const gchar *name; + const gchar *name; if (ccf) { name = luaL_checkstring (L, 2); @@ -223,9 +240,9 @@ lua_classifier_register_pre_callback (lua_State *L) static gint lua_classifier_register_post_callback (lua_State *L) { - struct rspamd_classifier_config *ccf = lua_check_classifier (L); + struct rspamd_classifier_config *ccf = lua_check_classifier (L); struct classifier_callback_data *cd; - const gchar *name; + const gchar *name; if (ccf) { name = luaL_checkstring (L, 2); @@ -244,10 +261,10 @@ lua_classifier_register_post_callback (lua_State *L) static gint lua_classifier_get_statfiles (lua_State *L) { - struct rspamd_classifier_config *ccf = lua_check_classifier (L); - GList *cur; - struct rspamd_statfile_config *st, **pst; - gint i; + struct rspamd_classifier_config *ccf = lua_check_classifier (L); + GList *cur; + struct rspamd_statfile_config *st, **pst; + gint i; if (ccf) { lua_newtable (L); @@ -274,11 +291,11 @@ lua_classifier_get_statfiles (lua_State *L) static gint lua_classifier_get_statfile_by_label (lua_State *L) { - struct rspamd_classifier_config *ccf = lua_check_classifier (L); - struct rspamd_statfile_config *st, **pst; - const gchar *label; - GList *cur; - gint i; + struct rspamd_classifier_config *ccf = lua_check_classifier (L); + struct rspamd_statfile_config *st, **pst; + const gchar *label; + GList *cur; + gint i; label = luaL_checkstring (L, 2); if (ccf && label) { @@ -288,7 +305,9 @@ lua_classifier_get_statfile_by_label (lua_State *L) i = 1; while (cur) { st = cur->data; - pst = lua_newuserdata (L, sizeof (struct rspamd_statfile_config *)); + pst = + lua_newuserdata (L, + sizeof (struct rspamd_statfile_config *)); lua_setclass (L, "rspamd{statfile}", -1); *pst = st; lua_rawseti (L, -2, i++); @@ -305,7 +324,7 @@ lua_classifier_get_statfile_by_label (lua_State *L) static gint lua_statfile_get_symbol (lua_State *L) { - struct rspamd_statfile_config *st = lua_check_statfile (L); + struct rspamd_statfile_config *st = lua_check_statfile (L); if (st != NULL) { lua_pushstring (L, st->symbol); @@ -320,7 +339,7 @@ lua_statfile_get_symbol (lua_State *L) static gint lua_statfile_get_label (lua_State *L) { - struct rspamd_statfile_config *st = lua_check_statfile (L); + struct rspamd_statfile_config *st = lua_check_statfile (L); if (st != NULL && st->label != NULL) { lua_pushstring (L, st->label); @@ -335,7 +354,7 @@ lua_statfile_get_label (lua_State *L) static gint lua_statfile_get_path (lua_State *L) { - struct rspamd_statfile_config *st = lua_check_statfile (L); + struct rspamd_statfile_config *st = lua_check_statfile (L); if (st != NULL) { lua_pushstring (L, st->path); @@ -350,7 +369,7 @@ lua_statfile_get_path (lua_State *L) static gint lua_statfile_get_size (lua_State *L) { - struct rspamd_statfile_config *st = lua_check_statfile (L); + struct rspamd_statfile_config *st = lua_check_statfile (L); if (st != NULL) { lua_pushinteger (L, st->size); @@ -365,7 +384,7 @@ lua_statfile_get_size (lua_State *L) static gint lua_statfile_is_spam (lua_State *L) { - struct rspamd_statfile_config *st = lua_check_statfile (L); + struct rspamd_statfile_config *st = lua_check_statfile (L); if (st != NULL) { lua_pushboolean (L, st->is_spam); @@ -380,9 +399,9 @@ lua_statfile_is_spam (lua_State *L) static gint lua_statfile_get_param (lua_State *L) { - struct rspamd_statfile_config *st = lua_check_statfile (L); - const gchar *param; - const ucl_object_t *value; + struct rspamd_statfile_config *st = lua_check_statfile (L); + const gchar *param; + const ucl_object_t *value; param = luaL_checkstring (L, 2); @@ -398,10 +417,10 @@ lua_statfile_get_param (lua_State *L) return 1; } -static struct rspamd_statfile_config * +static struct rspamd_statfile_config * lua_check_statfile (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{statfile}"); + void *ud = luaL_checkudata (L, 1, "rspamd{statfile}"); luaL_argcheck (L, ud != NULL, 1, "'statfile' expected"); return ud ? *((struct rspamd_statfile_config **)ud) : NULL; } diff --git a/src/lua/lua_common.c b/src/lua/lua_common.c index ea1e43010..6600bfc35 100644 --- a/src/lua/lua_common.c +++ b/src/lua/lua_common.c @@ -28,7 +28,7 @@ /* Lua module init function */ #define MODULE_INIT_FUNC "module_init" -const luaL_reg null_reg[] = { +const luaL_reg null_reg[] = { {"__tostring", lua_class_tostring}, {NULL, NULL} }; @@ -39,7 +39,7 @@ LUA_FUNCTION_DEF (logger, warn); LUA_FUNCTION_DEF (logger, info); LUA_FUNCTION_DEF (logger, debug); -static const struct luaL_reg loggerlib_f[] = { +static const struct luaL_reg loggerlib_f[] = { LUA_INTERFACE_DEF (logger, err), LUA_INTERFACE_DEF (logger, warn), LUA_INTERFACE_DEF (logger, info), @@ -57,16 +57,18 @@ static const struct luaL_reg loggerlib_f[] = { * @param func table of class methods */ void -lua_newclass (lua_State * L, const gchar *classname, const struct luaL_reg *methods) +lua_newclass (lua_State * L, + const gchar *classname, + const struct luaL_reg *methods) { - luaL_newmetatable (L, classname); /* mt */ + luaL_newmetatable (L, classname); /* mt */ lua_pushstring (L, "__index"); - lua_pushvalue (L, -2); /* pushes the metatable */ - lua_settable (L, -3); /* metatable.__index = metatable */ + lua_pushvalue (L, -2); /* pushes the metatable */ + lua_settable (L, -3); /* metatable.__index = metatable */ - lua_pushstring (L, "class"); /* mt,"__index",it,"class" */ - lua_pushstring (L, classname); /* mt,"__index",it,"class",classname */ - lua_rawset (L, -3); /* mt,"__index",it */ + lua_pushstring (L, "class"); /* mt,"__index",it,"class" */ + lua_pushstring (L, classname); /* mt,"__index",it,"class",classname */ + lua_rawset (L, -3); /* mt,"__index",it */ luaL_register (L, NULL, methods); } @@ -74,7 +76,11 @@ lua_newclass (lua_State * L, const gchar *classname, const struct luaL_reg *meth * Create and register new class with static methods and store metatable on top of the stack */ void -lua_newclass_full (lua_State *L, const gchar *classname, const gchar *static_name, const struct luaL_reg *methods, const struct luaL_reg *func) +lua_newclass_full (lua_State *L, + const gchar *classname, + const gchar *static_name, + const struct luaL_reg *methods, + const struct luaL_reg *func) { lua_newclass (L, classname, methods); luaL_register (L, static_name, func); @@ -83,7 +89,7 @@ lua_newclass_full (lua_State *L, const gchar *classname, const gchar *static_nam gint lua_class_tostring (lua_State * L) { - gchar buf[32]; + gchar buf[32]; if (!lua_getmetatable (L, 1)) { goto error; @@ -107,7 +113,7 @@ lua_class_tostring (lua_State * L) return 1; - error: +error: lua_pushstring (L, "invalid object passed to 'lua_common.c:__tostring'"); lua_error (L); return 1; @@ -157,31 +163,48 @@ lua_get_table_index_str (lua_State *L, const gchar *index) static void lua_common_log (GLogLevelFlags level, lua_State *L, const gchar *msg) { - lua_Debug d; - gchar func_buf[128], *p; + lua_Debug d; + gchar func_buf[128], *p; if (lua_getstack (L, 1, &d) == 1) { - (void)lua_getinfo(L, "Sl", &d); + (void)lua_getinfo (L, "Sl", &d); if ((p = strrchr (d.short_src, '/')) == NULL) { p = d.short_src; } else { - p ++; + p++; } - rspamd_snprintf (func_buf, sizeof (func_buf), "%s:%d", p, d.currentline); + rspamd_snprintf (func_buf, sizeof (func_buf), "%s:%d", p, + d.currentline); if (level == G_LOG_LEVEL_DEBUG) { - rspamd_conditional_debug (rspamd_main->logger, NULL, func_buf, "%s", msg); + rspamd_conditional_debug (rspamd_main->logger, + NULL, + func_buf, + "%s", + msg); } else { - rspamd_common_log_function (rspamd_main->logger, level, func_buf, "%s", msg); + rspamd_common_log_function (rspamd_main->logger, + level, + func_buf, + "%s", + msg); } } else { if (level == G_LOG_LEVEL_DEBUG) { - rspamd_conditional_debug (rspamd_main->logger, NULL, __FUNCTION__, "%s", msg); + rspamd_conditional_debug (rspamd_main->logger, + NULL, + __FUNCTION__, + "%s", + msg); } else { - rspamd_common_log_function (rspamd_main->logger, level, __FUNCTION__, "%s", msg); + rspamd_common_log_function (rspamd_main->logger, + level, + __FUNCTION__, + "%s", + msg); } } } @@ -190,7 +213,7 @@ lua_common_log (GLogLevelFlags level, lua_State *L, const gchar *msg) static gint lua_logger_err (lua_State * L) { - const gchar *msg; + const gchar *msg; msg = luaL_checkstring (L, 1); lua_common_log (G_LOG_LEVEL_CRITICAL, L, msg); return 1; @@ -199,7 +222,7 @@ lua_logger_err (lua_State * L) static gint lua_logger_warn (lua_State * L) { - const gchar *msg; + const gchar *msg; msg = luaL_checkstring (L, 1); lua_common_log (G_LOG_LEVEL_WARNING, L, msg); return 1; @@ -208,7 +231,7 @@ lua_logger_warn (lua_State * L) static gint lua_logger_info (lua_State * L) { - const gchar *msg; + const gchar *msg; msg = luaL_checkstring (L, 1); lua_common_log (G_LOG_LEVEL_INFO, L, msg); return 1; @@ -217,7 +240,7 @@ lua_logger_info (lua_State * L) static gint lua_logger_debug (lua_State * L) { - const gchar *msg; + const gchar *msg; msg = luaL_checkstring (L, 1); lua_common_log (G_LOG_LEVEL_DEBUG, L, msg); return 1; @@ -250,11 +273,11 @@ luaopen_logger (lua_State * L) static void lua_add_actions_global (lua_State *L) { - gint i; + gint i; lua_newtable (L); - for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i ++) { + for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i++) { lua_pushstring (L, str_action_metric (i)); lua_pushinteger (L, i); lua_settable (L, -3); @@ -266,7 +289,7 @@ lua_add_actions_global (lua_State *L) lua_State * init_lua (struct rspamd_config *cfg) { - lua_State *L; + lua_State *L; L = luaL_newstate (); luaL_openlibs (L); @@ -306,10 +329,10 @@ init_lua (struct rspamd_config *cfg) /** * Initialize new locked lua_State structure */ -struct lua_locked_state* +struct lua_locked_state * init_lua_locked (struct rspamd_config *cfg) { - struct lua_locked_state *new; + struct lua_locked_state *new; new = g_slice_alloc (sizeof (struct lua_locked_state)); new->L = init_lua (cfg); @@ -337,18 +360,19 @@ free_lua_locked (struct lua_locked_state *st) gboolean init_lua_filters (struct rspamd_config *cfg) { - struct rspamd_config **pcfg; - GList *cur, *tmp; - struct script_module *module; - struct rspamd_statfile_config *st; - lua_State *L = cfg->lua_state; + struct rspamd_config **pcfg; + GList *cur, *tmp; + struct script_module *module; + struct rspamd_statfile_config *st; + lua_State *L = cfg->lua_state; cur = g_list_first (cfg->script_modules); while (cur) { module = cur->data; if (module->path) { if (luaL_loadfile (L, module->path) != 0) { - msg_info ("load of %s failed: %s", module->path, lua_tostring (L, -1)); + msg_info ("load of %s failed: %s", module->path, + lua_tostring (L, -1)); cur = g_list_next (cur); return FALSE; } @@ -361,12 +385,15 @@ init_lua_filters (struct rspamd_config *cfg) /* do the call (0 arguments, N result) */ if (lua_pcall (L, 0, LUA_MULTRET, 0) != 0) { - msg_info ("init of %s failed: %s", module->path, lua_tostring (L, -1)); + msg_info ("init of %s failed: %s", module->path, + lua_tostring (L, -1)); return FALSE; } if (lua_gettop (L) != 0) { if (lua_tonumber (L, -1) == -1) { - msg_info ("%s returned -1 that indicates configuration error", module->path); + msg_info ( + "%s returned -1 that indicates configuration error", + module->path); return FALSE; } lua_pop (L, lua_gettop (L)); @@ -374,24 +401,24 @@ init_lua_filters (struct rspamd_config *cfg) } cur = g_list_next (cur); } - /* Init statfiles normalizers */ - cur = g_list_first (cfg->statfiles); - while (cur) { - st = cur->data; - if (st->normalizer == lua_normalizer_func) { - tmp = st->normalizer_data; - if (tmp && (tmp = g_list_next (tmp))) { - if (tmp->data) { - /* Code must be loaded from data */ - if (luaL_loadstring (L, tmp->data) != 0) { - msg_info ("cannot load normalizer code %s", tmp->data); - return FALSE; - } - } - } - } - cur = g_list_next (cur); - } + /* Init statfiles normalizers */ + cur = g_list_first (cfg->statfiles); + while (cur) { + st = cur->data; + if (st->normalizer == lua_normalizer_func) { + tmp = st->normalizer_data; + if (tmp && (tmp = g_list_next (tmp))) { + if (tmp->data) { + /* Code must be loaded from data */ + if (luaL_loadstring (L, tmp->data) != 0) { + msg_info ("cannot load normalizer code %s", tmp->data); + return FALSE; + } + } + } + } + cur = g_list_next (cur); + } /* Assign state */ cfg->lua_state = L; @@ -403,9 +430,9 @@ init_lua_filters (struct rspamd_config *cfg) gint lua_call_filter (const gchar *function, struct rspamd_task *task) { - gint result; - struct rspamd_task **ptask; - lua_State *L = task->cfg->lua_state; + gint result; + struct rspamd_task **ptask; + lua_State *L = task->cfg->lua_state; lua_getglobal (L, function); ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); @@ -421,17 +448,20 @@ lua_call_filter (const gchar *function, struct rspamd_task *task) msg_info ("function %s must return a number", function); } result = lua_tonumber (L, -1); - lua_pop (L, 1); /* pop returned value */ + lua_pop (L, 1); /* pop returned value */ return result; } gint -lua_call_chain_filter (const gchar *function, struct rspamd_task *task, gint *marks, guint number) +lua_call_chain_filter (const gchar *function, + struct rspamd_task *task, + gint *marks, + guint number) { - gint result; - guint i; - lua_State *L = task->cfg->lua_state; + gint result; + guint i; + lua_State *L = task->cfg->lua_state; lua_getglobal (L, function); @@ -447,46 +477,46 @@ lua_call_chain_filter (const gchar *function, struct rspamd_task *task, gint *ma msg_info ("function %s must return a number", function); } result = lua_tonumber (L, -1); - lua_pop (L, 1); /* pop returned value */ + lua_pop (L, 1); /* pop returned value */ return result; } /* Call custom lua function in rspamd expression */ -gboolean +gboolean lua_call_expression_func (gpointer lua_data, - struct rspamd_task *task, GList *args, gboolean *res) + struct rspamd_task *task, GList *args, gboolean *res) { - lua_State *L = task->cfg->lua_state; - struct rspamd_task **ptask; - GList *cur; - struct expression_argument *arg; - int nargs = 1, pop = 0; + lua_State *L = task->cfg->lua_state; + struct rspamd_task **ptask; + GList *cur; + struct expression_argument *arg; + int nargs = 1, pop = 0; lua_rawgeti (L, LUA_REGISTRYINDEX, GPOINTER_TO_INT (lua_data)); /* Now we got function in top of stack */ ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); lua_setclass (L, "rspamd{task}", -1); *ptask = task; - + /* Now push all arguments */ cur = args; while (cur) { arg = get_function_arg (cur->data, task, FALSE); if (arg) { switch (arg->type) { - case EXPRESSION_ARGUMENT_NORMAL: - lua_pushstring (L, (const gchar *)arg->data); - break; - case EXPRESSION_ARGUMENT_BOOL: - lua_pushboolean (L, (gboolean) GPOINTER_TO_SIZE (arg->data)); - break; - default: - msg_err ("cannot pass custom params to lua function"); - return FALSE; + case EXPRESSION_ARGUMENT_NORMAL: + lua_pushstring (L, (const gchar *)arg->data); + break; + case EXPRESSION_ARGUMENT_BOOL: + lua_pushboolean (L, (gboolean) GPOINTER_TO_SIZE (arg->data)); + break; + default: + msg_err ("cannot pass custom params to lua function"); + return FALSE; } } - nargs ++; + nargs++; cur = g_list_next (cur); } @@ -494,7 +524,7 @@ lua_call_expression_func (gpointer lua_data, msg_info ("call to lua function failed: %s", lua_tostring (L, -1)); return FALSE; } - pop ++; + pop++; if (!lua_isboolean (L, -1)) { lua_pop (L, pop); @@ -512,18 +542,19 @@ lua_call_expression_func (gpointer lua_data, * LUA custom consolidation function */ struct consolidation_callback_data { - struct rspamd_task *task; - double score; - const gchar *func; + struct rspamd_task *task; + double score; + const gchar *func; }; static void lua_consolidation_callback (gpointer key, gpointer value, gpointer arg) { - double res; - struct symbol *s = (struct symbol *)value; - struct consolidation_callback_data *data = (struct consolidation_callback_data *)arg; - lua_State *L = data->task->cfg->lua_state; + double res; + struct symbol *s = (struct symbol *)value; + struct consolidation_callback_data *data = + (struct consolidation_callback_data *)arg; + lua_State *L = data->task->cfg->lua_state; lua_getglobal (L, data->func); @@ -538,15 +569,17 @@ lua_consolidation_callback (gpointer key, gpointer value, gpointer arg) msg_info ("function %s must return a number", data->func); } res = lua_tonumber (L, -1); - lua_pop (L, 1); /* pop returned value */ + lua_pop (L, 1); /* pop returned value */ data->score += res; } double -lua_consolidation_func (struct rspamd_task *task, const gchar *metric_name, const gchar *function_name) +lua_consolidation_func (struct rspamd_task *task, + const gchar *metric_name, + const gchar *function_name) { - struct metric_result *metric_res; - double res = 0.; + struct metric_result *metric_res; + double res = 0.; struct consolidation_callback_data data = { task, 0, function_name }; if (function_name == NULL) { @@ -558,28 +591,29 @@ lua_consolidation_func (struct rspamd_task *task, const gchar *metric_name, cons return res; } - g_hash_table_foreach (metric_res->symbols, lua_consolidation_callback, &data); + g_hash_table_foreach (metric_res->symbols, lua_consolidation_callback, + &data); return data.score; } -double +double lua_normalizer_func (struct rspamd_config *cfg, long double score, void *params) { - GList *p = params; - long double res = score; - lua_State *L = cfg->lua_state; - - /* Call specified function and put input score on stack */ - if (!p->data) { - msg_info ("bad function name while calling normalizer"); - return score; - } + GList *p = params; + long double res = score; + lua_State *L = cfg->lua_state; + + /* Call specified function and put input score on stack */ + if (!p->data) { + msg_info ("bad function name while calling normalizer"); + return score; + } - lua_getglobal (L, p->data); - lua_pushnumber (L, score); + lua_getglobal (L, p->data); + lua_pushnumber (L, score); - if (lua_pcall (L, 1, 1, 0) != 0) { + if (lua_pcall (L, 1, 1, 0) != 0) { msg_info ("call to %s failed", p->data); } @@ -590,16 +624,16 @@ lua_normalizer_func (struct rspamd_config *cfg, long double score, void *params) res = lua_tonumber (L, -1); lua_pop (L, 1); - return res; + return res; } void lua_dumpstack (lua_State *L) { - gint i, t, r = 0; - gint top = lua_gettop (L); - gchar buf[BUFSIZ]; + gint i, t, r = 0; + gint top = lua_gettop (L); + gchar buf[BUFSIZ]; r += rspamd_snprintf (buf + r, sizeof (buf) - r, "lua stack: "); for (i = 1; i <= top; i++) { /* repeat for each level */ @@ -607,19 +641,29 @@ lua_dumpstack (lua_State *L) switch (t) { case LUA_TSTRING: /* strings */ - r += rspamd_snprintf (buf + r, sizeof (buf) - r, "str: %s", lua_tostring(L, i)); + r += rspamd_snprintf (buf + r, + sizeof (buf) - r, + "str: %s", + lua_tostring (L, i)); break; case LUA_TBOOLEAN: /* booleans */ - r += rspamd_snprintf (buf + r, sizeof (buf) - r,lua_toboolean (L, i) ? "bool: true" : "bool: false"); + r += rspamd_snprintf (buf + r, sizeof (buf) - r,lua_toboolean (L, + i) ? "bool: true" : "bool: false"); break; case LUA_TNUMBER: /* numbers */ - r += rspamd_snprintf (buf + r, sizeof (buf) - r, "number: %.2f", lua_tonumber (L, i)); + r += rspamd_snprintf (buf + r, + sizeof (buf) - r, + "number: %.2f", + lua_tonumber (L, i)); break; default: /* other values */ - r += rspamd_snprintf (buf + r, sizeof (buf) - r, "type: %s", lua_typename (L, t)); + r += rspamd_snprintf (buf + r, + sizeof (buf) - r, + "type: %s", + lua_typename (L, t)); break; } @@ -633,7 +677,7 @@ lua_dumpstack (lua_State *L) gpointer lua_check_class (lua_State *L, gint index, const gchar *name) { - gpointer p; + gpointer p; if (lua_type (L, index) == LUA_TUSERDATA) { p = lua_touserdata (L, index); @@ -655,6 +699,6 @@ int rspamd_lua_typerror (lua_State *L, int narg, const char *tname) { const char *msg = lua_pushfstring (L, "%s expected, got %s", tname, - luaL_typename(L, narg)); + luaL_typename (L, narg)); return luaL_argerror (L, narg, msg); } diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h index ca0ab6d28..a9f0d399a 100644 --- a/src/lua/lua_common.h +++ b/src/lua/lua_common.h @@ -13,17 +13,17 @@ #include <lualib.h> #ifndef lua_open -#define lua_open() luaL_newstate() +#define lua_open() luaL_newstate () #endif #ifndef luaL_reg -#define luaL_reg luaL_Reg +#define luaL_reg luaL_Reg #endif #define LUA_ENUM(L, name, val) \ - lua_pushlstring(L, #name, sizeof(#name)-1); \ - lua_pushnumber(L, val); \ - lua_settable(L, -3); + lua_pushlstring (L, # name, sizeof(# name) - 1); \ + lua_pushnumber (L, val); \ + lua_settable (L, -3); #if LUA_VERSION_NUM > 501 static inline void @@ -32,17 +32,18 @@ luaL_register (lua_State *L, const gchar *name, const struct luaL_reg *methods) if (name != NULL) { lua_newtable (L); } - luaL_setfuncs (L, methods, 0); - if (name != NULL) { - lua_pushvalue (L, -1); - lua_setglobal (L, name); - } + luaL_setfuncs (L, methods, 0); + if (name != NULL) { + lua_pushvalue (L, -1); + lua_setglobal (L, name); + } } #endif /* Interface definitions */ -#define LUA_FUNCTION_DEF(class, name) static gint lua_##class##_##name(lua_State *L) -#define LUA_INTERFACE_DEF(class, name) { #name, lua_##class##_##name } +#define LUA_FUNCTION_DEF(class, name) static gint lua_ ## class ## _ ## name ( \ + lua_State * L) +#define LUA_INTERFACE_DEF(class, name) { # name, lua_ ## class ## _ ## name } extern const luaL_reg null_reg[]; @@ -59,12 +60,18 @@ struct lua_locked_state { /** * Create and register new class */ -void lua_newclass (lua_State *L, const gchar *classname, const struct luaL_reg *methods); +void lua_newclass (lua_State *L, + const gchar *classname, + const struct luaL_reg *methods); /** * Create and register new class with static methods */ -void lua_newclass_full (lua_State *L, const gchar *classname, const gchar *static_name, const struct luaL_reg *methods, const struct luaL_reg *func); +void lua_newclass_full (lua_State *L, + const gchar *classname, + const gchar *static_name, + const struct luaL_reg *methods, + const struct luaL_reg *func); /** * Set class name for object at @param objidx position @@ -94,7 +101,7 @@ gpointer lua_check_class (lua_State *L, gint index, const gchar *name); /** * Initialize lua and bindings */ -lua_State* init_lua (struct rspamd_config *cfg); +lua_State * init_lua (struct rspamd_config *cfg); /** * Load and initialize lua plugins @@ -104,7 +111,7 @@ gboolean init_lua_filters (struct rspamd_config *cfg); /** * Initialize new locked lua_State structure */ -struct lua_locked_state* init_lua_locked (struct rspamd_config *cfg); +struct lua_locked_state * init_lua_locked (struct rspamd_config *cfg); /** * Free locked state structure */ @@ -163,29 +170,54 @@ gint luaopen_rsa (lua_State * L); gint luaopen_ip (lua_State * L); gint lua_call_filter (const gchar *function, struct rspamd_task *task); -gint lua_call_chain_filter (const gchar *function, struct rspamd_task *task, gint *marks, guint number); -double lua_consolidation_func (struct rspamd_task *task, const gchar *metric_name, const gchar *function_name); -gboolean lua_call_expression_func (gpointer lua_data, struct rspamd_task *task, GList *args, gboolean *res); +gint lua_call_chain_filter (const gchar *function, + struct rspamd_task *task, + gint *marks, + guint number); +double lua_consolidation_func (struct rspamd_task *task, + const gchar *metric_name, + const gchar *function_name); +gboolean lua_call_expression_func (gpointer lua_data, + struct rspamd_task *task, + GList *args, + gboolean *res); void lua_call_post_filters (struct rspamd_task *task); void lua_call_pre_filters (struct rspamd_task *task); void add_luabuf (const gchar *line); /* Classify functions */ -GList *call_classifier_pre_callbacks (struct rspamd_classifier_config *ccf, struct rspamd_task *task, gboolean is_learn, gboolean is_spam, lua_State *L); -double call_classifier_post_callbacks (struct rspamd_classifier_config *ccf, struct rspamd_task *task, double in, lua_State *L); - -double lua_normalizer_func (struct rspamd_config *cfg, long double score, void *params); +GList * call_classifier_pre_callbacks (struct rspamd_classifier_config *ccf, + struct rspamd_task *task, + gboolean is_learn, + gboolean is_spam, + lua_State *L); +double call_classifier_post_callbacks (struct rspamd_classifier_config *ccf, + struct rspamd_task *task, + double in, + lua_State *L); + +double lua_normalizer_func (struct rspamd_config *cfg, + long double score, + void *params); /* Config file functions */ void lua_post_load_config (struct rspamd_config *cfg); -void lua_process_element (struct rspamd_config *cfg, const gchar *name, - const gchar *module_name, struct rspamd_module_opt *opt, gint idx, gboolean allow_meta); -gboolean lua_handle_param (struct rspamd_task *task, gchar *mname, gchar *optname, - enum lua_var_type expected_type, gpointer *res); -gboolean lua_check_condition (struct rspamd_config *cfg, const gchar *condition); +void lua_process_element (struct rspamd_config *cfg, + const gchar *name, + const gchar *module_name, + struct rspamd_module_opt *opt, + gint idx, + gboolean allow_meta); +gboolean lua_handle_param (struct rspamd_task *task, + gchar *mname, + gchar *optname, + enum lua_var_type expected_type, + gpointer *res); +gboolean lua_check_condition (struct rspamd_config *cfg, + const gchar *condition); void lua_dumpstack (lua_State *L); -struct memory_pool_s *lua_check_mempool (lua_State * L); +struct memory_pool_s * lua_check_mempool (lua_State * L); #endif /* WITH_LUA */ diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c index 162c7b842..cd9512991 100644 --- a/src/lua/lua_config.c +++ b/src/lua/lua_config.c @@ -51,7 +51,7 @@ LUA_FUNCTION_DEF (config, register_post_filter); LUA_FUNCTION_DEF (config, register_module_option); LUA_FUNCTION_DEF (config, get_api_version); -static const struct luaL_reg configlib_m[] = { +static const struct luaL_reg configlib_m[] = { LUA_INTERFACE_DEF (config, get_module_opt), LUA_INTERFACE_DEF (config, get_mempool), LUA_INTERFACE_DEF (config, get_all_opt), @@ -78,7 +78,7 @@ static const struct luaL_reg configlib_m[] = { /* Radix tree */ LUA_FUNCTION_DEF (radix, get_key); -static const struct luaL_reg radixlib_m[] = { +static const struct luaL_reg radixlib_m[] = { LUA_INTERFACE_DEF (radix, get_key), {"__tostring", lua_class_tostring}, {NULL, NULL} @@ -87,7 +87,7 @@ static const struct luaL_reg radixlib_m[] = { /* Hash table */ LUA_FUNCTION_DEF (hash_table, get_key); -static const struct luaL_reg hashlib_m[] = { +static const struct luaL_reg hashlib_m[] = { LUA_INTERFACE_DEF (hash_table, get_key), {"__tostring", lua_class_tostring}, {NULL, NULL} @@ -99,46 +99,46 @@ LUA_FUNCTION_DEF (trie, add_pattern); LUA_FUNCTION_DEF (trie, search_text); LUA_FUNCTION_DEF (trie, search_task); -static const struct luaL_reg trielib_m[] = { +static const struct luaL_reg trielib_m[] = { LUA_INTERFACE_DEF (trie, add_pattern), LUA_INTERFACE_DEF (trie, search_text), LUA_INTERFACE_DEF (trie, search_task), {"__tostring", lua_class_tostring}, {NULL, NULL} }; -static const struct luaL_reg trielib_f[] = { +static const struct luaL_reg trielib_f[] = { LUA_INTERFACE_DEF (trie, create), {NULL, NULL} }; -static struct rspamd_config * +static struct rspamd_config * lua_check_config (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{config}"); + void *ud = luaL_checkudata (L, 1, "rspamd{config}"); luaL_argcheck (L, ud != NULL, 1, "'config' expected"); return ud ? *((struct rspamd_config **)ud) : NULL; } -static radix_tree_t * +static radix_tree_t * lua_check_radix (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{radix}"); + void *ud = luaL_checkudata (L, 1, "rspamd{radix}"); luaL_argcheck (L, ud != NULL, 1, "'radix' expected"); return ud ? **((radix_tree_t ***)ud) : NULL; } -static GHashTable * +static GHashTable * lua_check_hash_table (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{hash_table}"); + void *ud = luaL_checkudata (L, 1, "rspamd{hash_table}"); luaL_argcheck (L, ud != NULL, 1, "'hash_table' expected"); return ud ? **((GHashTable ***)ud) : NULL; } -static rspamd_trie_t * +static rspamd_trie_t * lua_check_trie (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{trie}"); + void *ud = luaL_checkudata (L, 1, "rspamd{trie}"); luaL_argcheck (L, ud != NULL, 1, "'trie' expected"); return ud ? *((rspamd_trie_t **)ud) : NULL; @@ -155,9 +155,9 @@ lua_config_get_api_version (lua_State *L) static gint lua_config_get_module_opt (lua_State * L) { - struct rspamd_config *cfg = lua_check_config (L); - const gchar *mname, *optname; - const ucl_object_t *obj; + struct rspamd_config *cfg = lua_check_config (L); + const gchar *mname, *optname; + const ucl_object_t *obj; if (cfg) { mname = luaL_checkstring (L, 2); @@ -177,8 +177,8 @@ lua_config_get_module_opt (lua_State * L) static int lua_config_get_mempool (lua_State * L) { - rspamd_mempool_t **ppool; - struct rspamd_config *cfg = lua_check_config (L); + rspamd_mempool_t **ppool; + struct rspamd_config *cfg = lua_check_config (L); if (cfg != NULL) { ppool = lua_newuserdata (L, sizeof (rspamd_mempool_t *)); @@ -191,9 +191,9 @@ lua_config_get_mempool (lua_State * L) static gint lua_config_get_all_opt (lua_State * L) { - struct rspamd_config *cfg = lua_check_config (L); - const gchar *mname; - const ucl_object_t *obj; + struct rspamd_config *cfg = lua_check_config (L); + const gchar *mname; + const ucl_object_t *obj; if (cfg) { mname = luaL_checkstring (L, 2); @@ -213,10 +213,10 @@ lua_config_get_all_opt (lua_State * L) static gint lua_config_get_classifier (lua_State * L) { - struct rspamd_config *cfg = lua_check_config (L); - struct rspamd_classifier_config *clc = NULL, **pclc = NULL; - const gchar *name; - GList *cur; + struct rspamd_config *cfg = lua_check_config (L); + struct rspamd_classifier_config *clc = NULL, **pclc = NULL; + const gchar *name; + GList *cur; if (cfg) { name = luaL_checkstring (L, 2); @@ -231,7 +231,8 @@ lua_config_get_classifier (lua_State * L) cur = g_list_next (cur); } if (pclc) { - pclc = lua_newuserdata (L, sizeof (struct rspamd_classifier_config *)); + pclc = lua_newuserdata (L, + sizeof (struct rspamd_classifier_config *)); lua_setclass (L, "rspamd{classifier}", -1); *pclc = clc; return 1; @@ -245,12 +246,12 @@ lua_config_get_classifier (lua_State * L) struct lua_callback_data { union { - gchar *name; - gint ref; + gchar *name; + gint ref; } callback; - gboolean cb_is_ref; - lua_State *L; - gchar *symbol; + gboolean cb_is_ref; + lua_State *L; + gchar *symbol; }; /* @@ -259,7 +260,7 @@ struct lua_callback_data { static void lua_destroy_cfg_symbol (gpointer ud) { - struct lua_callback_data *cd = ud; + struct lua_callback_data *cd = ud; /* Unref callback */ if (cd->cb_is_ref) { @@ -268,14 +269,16 @@ lua_destroy_cfg_symbol (gpointer ud) } static gboolean -lua_config_function_callback (struct rspamd_task *task, GList *args, void *user_data) +lua_config_function_callback (struct rspamd_task *task, + GList *args, + void *user_data) { - struct lua_callback_data *cd = user_data; - struct rspamd_task **ptask; - gint i = 1; - struct expression_argument *arg; - GList *cur; - gboolean res = FALSE; + struct lua_callback_data *cd = user_data; + struct rspamd_task **ptask; + gint i = 1; + struct expression_argument *arg; + GList *cur; + gboolean res = FALSE; if (cd->cb_is_ref) { lua_rawgeti (cd->L, LUA_REGISTRYINDEX, cd->callback.ref); @@ -292,13 +295,15 @@ lua_config_function_callback (struct rspamd_task *task, GList *args, void *user_ arg = get_function_arg (cur->data, task, TRUE); lua_pushstring (cd->L, (const gchar *)arg->data); cur = g_list_next (cur); - i ++; + i++; } if (lua_pcall (cd->L, i, 1, 0) != 0) { - msg_info ("error processing symbol %s: call to %s failed: %s", cd->symbol, - cd->cb_is_ref ? "local function" : - cd->callback.name, lua_tostring (cd->L, -1)); + msg_info ("error processing symbol %s: call to %s failed: %s", + cd->symbol, + cd->cb_is_ref ? "local function" : + cd->callback.name, + lua_tostring (cd->L, -1)); } else { if (lua_isboolean (cd->L, 1)) { @@ -313,16 +318,19 @@ lua_config_function_callback (struct rspamd_task *task, GList *args, void *user_ static gint lua_config_register_function (lua_State *L) { - struct rspamd_config *cfg = lua_check_config (L); - gchar *name; - struct lua_callback_data *cd; - + struct rspamd_config *cfg = lua_check_config (L); + gchar *name; + struct lua_callback_data *cd; + if (cfg) { name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); - cd = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct lua_callback_data)); + cd = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct lua_callback_data)); if (lua_type (L, 3) == LUA_TSTRING) { - cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 3)); + cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, + luaL_checkstring (L, 3)); cd->cb_is_ref = FALSE; } else { @@ -334,9 +342,12 @@ lua_config_register_function (lua_State *L) if (name) { cd->L = L; cd->symbol = name; - register_expression_function (name, lua_config_function_callback, cd); + register_expression_function (name, lua_config_function_callback, + cd); } - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, cd); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, + cd); } return 1; } @@ -350,9 +361,9 @@ lua_config_register_module_option (lua_State *L) void lua_call_post_filters (struct rspamd_task *task) { - struct lua_callback_data *cd; - struct rspamd_task **ptask; - GList *cur; + struct lua_callback_data *cd; + struct rspamd_task **ptask; + GList *cur; cur = task->cfg->post_filters; while (cur) { @@ -368,8 +379,10 @@ lua_call_post_filters (struct rspamd_task *task) *ptask = task; if (lua_pcall (cd->L, 1, 0, 0) != 0) { - msg_info ("call to %s failed: %s", cd->cb_is_ref ? "local function" : - cd->callback.name, lua_tostring (cd->L, -1)); + msg_info ("call to %s failed: %s", + cd->cb_is_ref ? "local function" : + cd->callback.name, + lua_tostring (cd->L, -1)); } cur = g_list_next (cur); } @@ -378,13 +391,16 @@ lua_call_post_filters (struct rspamd_task *task) static gint lua_config_register_post_filter (lua_State *L) { - struct rspamd_config *cfg = lua_check_config (L); - struct lua_callback_data *cd; + struct rspamd_config *cfg = lua_check_config (L); + struct lua_callback_data *cd; if (cfg) { - cd = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct lua_callback_data)); + cd = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct lua_callback_data)); if (lua_type (L, 2) == LUA_TSTRING) { - cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); + cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, + luaL_checkstring (L, 2)); cd->cb_is_ref = FALSE; } else { @@ -395,7 +411,9 @@ lua_config_register_post_filter (lua_State *L) } cd->L = L; cfg->post_filters = g_list_prepend (cfg->post_filters, cd); - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, cd); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, + cd); } return 1; } @@ -403,9 +421,9 @@ lua_config_register_post_filter (lua_State *L) void lua_call_pre_filters (struct rspamd_task *task) { - struct lua_callback_data *cd; - struct rspamd_task **ptask; - GList *cur; + struct lua_callback_data *cd; + struct rspamd_task **ptask; + GList *cur; cur = task->cfg->pre_filters; while (cur) { @@ -421,8 +439,10 @@ lua_call_pre_filters (struct rspamd_task *task) *ptask = task; if (lua_pcall (cd->L, 1, 0, 0) != 0) { - msg_info ("call to %s failed: %s", cd->cb_is_ref ? "local function" : - cd->callback.name, lua_tostring (cd->L, -1)); + msg_info ("call to %s failed: %s", + cd->cb_is_ref ? "local function" : + cd->callback.name, + lua_tostring (cd->L, -1)); } cur = g_list_next (cur); } @@ -431,13 +451,16 @@ lua_call_pre_filters (struct rspamd_task *task) static gint lua_config_register_pre_filter (lua_State *L) { - struct rspamd_config *cfg = lua_check_config (L); - struct lua_callback_data *cd; + struct rspamd_config *cfg = lua_check_config (L); + struct lua_callback_data *cd; if (cfg) { - cd = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct lua_callback_data)); + cd = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct lua_callback_data)); if (lua_type (L, 2) == LUA_TSTRING) { - cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); + cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, + luaL_checkstring (L, 2)); cd->cb_is_ref = FALSE; } else { @@ -448,7 +471,9 @@ lua_config_register_pre_filter (lua_State *L) } cd->L = L; cfg->pre_filters = g_list_prepend (cfg->pre_filters, cd); - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, cd); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, + cd); } return 1; } @@ -456,16 +481,17 @@ lua_config_register_pre_filter (lua_State *L) static gint lua_config_add_radix_map (lua_State *L) { - struct rspamd_config *cfg = lua_check_config (L); - const gchar *map_line, *description; - radix_tree_t **r, ***ud; + struct rspamd_config *cfg = lua_check_config (L); + const gchar *map_line, *description; + radix_tree_t **r, ***ud; if (cfg) { map_line = luaL_checkstring (L, 2); description = lua_tostring (L, 3); r = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (radix_tree_t *)); *r = radix_tree_create (); - if (!add_map (cfg, map_line, description, read_radix_list, fin_radix_list, (void **)r)) { + if (!add_map (cfg, map_line, description, read_radix_list, + fin_radix_list, (void **)r)) { msg_warn ("invalid radix map %s", map_line); radix_tree_free (*r); lua_pushnil (L); @@ -486,22 +512,25 @@ lua_config_add_radix_map (lua_State *L) static gint lua_config_add_hash_map (lua_State *L) { - struct rspamd_config *cfg = lua_check_config (L); - const gchar *map_line, *description; - GHashTable **r, ***ud; + struct rspamd_config *cfg = lua_check_config (L); + const gchar *map_line, *description; + GHashTable **r, ***ud; if (cfg) { map_line = luaL_checkstring (L, 2); description = lua_tostring (L, 3); r = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (GHashTable *)); *r = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); - if (!add_map (cfg, map_line, description, read_host_list, fin_host_list, (void **)r)) { + if (!add_map (cfg, map_line, description, read_host_list, fin_host_list, + (void **)r)) { msg_warn ("invalid hash map %s", map_line); g_hash_table_destroy (*r); lua_pushnil (L); return 1; } - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)g_hash_table_destroy, *r); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)g_hash_table_destroy, + *r); ud = lua_newuserdata (L, sizeof (GHashTable *)); *ud = r; lua_setclass (L, "rspamd{hash_table}", -1); @@ -517,22 +546,25 @@ lua_config_add_hash_map (lua_State *L) static gint lua_config_add_kv_map (lua_State *L) { - struct rspamd_config *cfg = lua_check_config (L); - const gchar *map_line, *description; - GHashTable **r, ***ud; + struct rspamd_config *cfg = lua_check_config (L); + const gchar *map_line, *description; + GHashTable **r, ***ud; if (cfg) { map_line = luaL_checkstring (L, 2); description = lua_tostring (L, 3); r = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (GHashTable *)); *r = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); - if (!add_map (cfg, map_line, description, read_kv_list, fin_kv_list, (void **)r)) { + if (!add_map (cfg, map_line, description, read_kv_list, fin_kv_list, + (void **)r)) { msg_warn ("invalid hash map %s", map_line); g_hash_table_destroy (*r); lua_pushnil (L); return 1; } - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)g_hash_table_destroy, *r); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)g_hash_table_destroy, + *r); ud = lua_newuserdata (L, sizeof (GHashTable *)); *ud = r; lua_setclass (L, "rspamd{hash_table}", -1); @@ -553,7 +585,7 @@ struct lua_map_callback_data { static gchar * lua_map_read (rspamd_mempool_t *pool, gchar *chunk, gint len, - struct map_cb_data *data) + struct map_cb_data *data) { struct lua_map_callback_data *cbdata, *old; @@ -605,7 +637,7 @@ lua_map_fin (rspamd_mempool_t * pool, struct map_cb_data *data) if (lua_pcall (cbdata->L, 1, 0, 0) != 0) { msg_info ("call to %s failed: %s", "local function", - lua_tostring (cbdata->L, -1)); + lua_tostring (cbdata->L, -1)); } } } @@ -613,9 +645,9 @@ lua_map_fin (rspamd_mempool_t * pool, struct map_cb_data *data) static gint lua_config_add_map (lua_State *L) { - struct rspamd_config *cfg = lua_check_config (L); - const gchar *map_line, *description; - struct lua_map_callback_data *cbdata, **pcbdata; + struct rspamd_config *cfg = lua_check_config (L); + const gchar *map_line, *description; + struct lua_map_callback_data *cbdata, **pcbdata; if (cfg) { map_line = luaL_checkstring (L, 2); @@ -631,7 +663,7 @@ lua_config_add_map (lua_State *L) pcbdata = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (cbdata)); *pcbdata = cbdata; if (!add_map (cfg, map_line, description, lua_map_read, lua_map_fin, - (void **)pcbdata)) { + (void **)pcbdata)) { msg_warn ("invalid hash map %s", map_line); lua_pushboolean (L, false); } @@ -657,8 +689,8 @@ lua_config_add_map (lua_State *L) static void lua_metric_symbol_callback (struct rspamd_task *task, gpointer ud) { - struct lua_callback_data *cd = ud; - struct rspamd_task **ptask; + struct lua_callback_data *cd = ud; + struct rspamd_task **ptask; if (cd->cb_is_ref) { lua_rawgeti (cd->L, LUA_REGISTRYINDEX, cd->callback.ref); @@ -672,24 +704,27 @@ lua_metric_symbol_callback (struct rspamd_task *task, gpointer ud) if (lua_pcall (cd->L, 1, 0, 0) != 0) { msg_info ("call to %s failed: %s", cd->cb_is_ref ? "local function" : - cd->callback.name, lua_tostring (cd->L, -1)); + cd->callback.name, lua_tostring (cd->L, -1)); } } static gint lua_config_register_symbol (lua_State * L) { - struct rspamd_config *cfg = lua_check_config (L); - gchar *name; - double weight; - struct lua_callback_data *cd; + struct rspamd_config *cfg = lua_check_config (L); + gchar *name; + double weight; + struct lua_callback_data *cd; if (cfg) { name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); weight = luaL_checknumber (L, 3); - cd = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct lua_callback_data)); + cd = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct lua_callback_data)); if (lua_type (L, 4) == LUA_TSTRING) { - cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 4)); + cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, + luaL_checkstring (L, 4)); cd->cb_is_ref = FALSE; } else { @@ -701,9 +736,15 @@ lua_config_register_symbol (lua_State * L) if (name) { cd->symbol = name; cd->L = L; - register_symbol (&cfg->cache, name, weight, lua_metric_symbol_callback, cd); + register_symbol (&cfg->cache, + name, + weight, + lua_metric_symbol_callback, + cd); } - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, cd); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, + cd); } return 0; } @@ -711,20 +752,23 @@ lua_config_register_symbol (lua_State * L) static gint lua_config_register_symbols (lua_State *L) { - struct rspamd_config *cfg = lua_check_config (L); - struct lua_callback_data *cd; - gint i, top; - gchar *sym; - gdouble weight = 1.0; + struct rspamd_config *cfg = lua_check_config (L); + struct lua_callback_data *cd; + gint i, top; + gchar *sym; + gdouble weight = 1.0; if (lua_gettop (L) < 3) { msg_err ("not enough arguments to register a function"); return 0; } if (cfg) { - cd = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct lua_callback_data)); + cd = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct lua_callback_data)); if (lua_type (L, 2) == LUA_TSTRING) { - cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); + cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, + luaL_checkstring (L, 2)); cd->cb_is_ref = FALSE; } else { @@ -743,9 +787,15 @@ lua_config_register_symbols (lua_State *L) sym = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, top)); cd->symbol = sym; cd->L = L; - register_symbol (&cfg->cache, sym, weight, lua_metric_symbol_callback, cd); - for (i = top; i < lua_gettop (L); i ++) { - sym = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, i + 1)); + register_symbol (&cfg->cache, + sym, + weight, + lua_metric_symbol_callback, + cd); + for (i = top; i < lua_gettop (L); i++) { + sym = + rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, + i + 1)); register_virtual_symbol (&cfg->cache, sym, weight); } } @@ -756,9 +806,9 @@ lua_config_register_symbols (lua_State *L) static gint lua_config_register_virtual_symbol (lua_State * L) { - struct rspamd_config *cfg = lua_check_config (L); - gchar *name; - double weight; + struct rspamd_config *cfg = lua_check_config (L); + gchar *name; + double weight; if (cfg) { name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); @@ -773,17 +823,20 @@ lua_config_register_virtual_symbol (lua_State * L) static gint lua_config_register_callback_symbol (lua_State * L) { - struct rspamd_config *cfg = lua_check_config (L); - gchar *name; - double weight; - struct lua_callback_data *cd; + struct rspamd_config *cfg = lua_check_config (L); + gchar *name; + double weight; + struct lua_callback_data *cd; if (cfg) { name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); weight = luaL_checknumber (L, 3); - cd = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct lua_callback_data)); + cd = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct lua_callback_data)); if (lua_type (L, 4) == LUA_TSTRING) { - cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 4)); + cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, + luaL_checkstring (L, 4)); cd->cb_is_ref = FALSE; } else { @@ -795,9 +848,15 @@ lua_config_register_callback_symbol (lua_State * L) if (name) { cd->symbol = name; cd->L = L; - register_callback_symbol (&cfg->cache, name, weight, lua_metric_symbol_callback, cd); + register_callback_symbol (&cfg->cache, + name, + weight, + lua_metric_symbol_callback, + cd); } - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, cd); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, + cd); } return 0; } @@ -805,19 +864,22 @@ lua_config_register_callback_symbol (lua_State * L) static gint lua_config_register_callback_symbol_priority (lua_State * L) { - struct rspamd_config *cfg = lua_check_config (L); - gchar *name; - double weight; - gint priority; - struct lua_callback_data *cd; + struct rspamd_config *cfg = lua_check_config (L); + gchar *name; + double weight; + gint priority; + struct lua_callback_data *cd; if (cfg) { name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); weight = luaL_checknumber (L, 3); priority = luaL_checknumber (L, 4); - cd = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct lua_callback_data)); + cd = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct lua_callback_data)); if (lua_type (L, 5) == LUA_TSTRING) { - cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 5)); + cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, + luaL_checkstring (L, 5)); cd->cb_is_ref = FALSE; } else { @@ -830,9 +892,16 @@ lua_config_register_callback_symbol_priority (lua_State * L) if (name) { cd->L = L; cd->symbol = name; - register_callback_symbol_priority (&cfg->cache, name, weight, priority, lua_metric_symbol_callback, cd); + register_callback_symbol_priority (&cfg->cache, + name, + weight, + priority, + lua_metric_symbol_callback, + cd); } - rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, cd); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, + cd); } return 0; @@ -843,8 +912,8 @@ lua_config_register_callback_symbol_priority (lua_State * L) static gint lua_radix_get_key (lua_State * L) { - radix_tree_t *radix = lua_check_radix (L); - guint32 key; + radix_tree_t *radix = lua_check_radix (L); + guint32 key; if (radix) { key = luaL_checkint (L, 2); @@ -862,8 +931,8 @@ lua_radix_get_key (lua_State * L) static gint lua_hash_table_get_key (lua_State * L) { - GHashTable *tbl = lua_check_hash_table (L); - const gchar *key, *value; + GHashTable *tbl = lua_check_hash_table (L); + const gchar *key, *value; if (tbl) { key = luaL_checkstring (L, 2); @@ -882,8 +951,8 @@ lua_hash_table_get_key (lua_State * L) static gint lua_trie_create (lua_State *L) { - rspamd_trie_t *trie, **ptrie; - gboolean icase = FALSE; + rspamd_trie_t *trie, **ptrie; + gboolean icase = FALSE; if (lua_gettop (L) == 1) { icase = lua_toboolean (L, 1); @@ -901,12 +970,12 @@ lua_trie_create (lua_State *L) static gint lua_trie_add_pattern (lua_State *L) { - rspamd_trie_t *trie = lua_check_trie (L); - const gchar *pattern; - gint id; + rspamd_trie_t *trie = lua_check_trie (L); + const gchar *pattern; + gint id; if (trie) { - pattern = luaL_checkstring (L, 2); + pattern = luaL_checkstring (L, 2); id = luaL_checknumber (L, 3); if (pattern != NULL) { @@ -923,11 +992,11 @@ lua_trie_add_pattern (lua_State *L) static gint lua_trie_search_text (lua_State *L) { - rspamd_trie_t *trie = lua_check_trie (L); - const gchar *text, *pos; - gint id, i = 1; - gsize len; - gboolean found = FALSE; + rspamd_trie_t *trie = lua_check_trie (L); + const gchar *text, *pos; + gint id, i = 1; + gsize len; + gboolean found = FALSE; if (trie) { text = luaL_checkstring (L, 2); @@ -935,11 +1004,12 @@ lua_trie_search_text (lua_State *L) if (text) { lua_newtable (L); pos = text; - while (pos < text + len && (pos = rspamd_trie_lookup (trie, pos, len, &id)) != NULL) { + while (pos < text + len && + (pos = rspamd_trie_lookup (trie, pos, len, &id)) != NULL) { lua_pushinteger (L, i); lua_pushinteger (L, id); lua_settable (L, -3); - i ++; + i++; found = TRUE; break; } @@ -958,14 +1028,14 @@ lua_trie_search_text (lua_State *L) static gint lua_trie_search_task (lua_State *L) { - rspamd_trie_t *trie = lua_check_trie (L); - struct rspamd_task *task; - struct mime_text_part *part; - GList *cur; - const gchar *pos, *end; - gint id, i = 1; - void *ud; - gboolean found = FALSE; + rspamd_trie_t *trie = lua_check_trie (L); + struct rspamd_task *task; + struct mime_text_part *part; + GList *cur; + const gchar *pos, *end; + gint id, i = 1; + void *ud; + gboolean found = FALSE; if (trie) { ud = luaL_checkudata (L, 2, "rspamd{task}"); @@ -979,11 +1049,14 @@ lua_trie_search_task (lua_State *L) if (!part->is_empty && part->content != NULL) { pos = (const gchar *)part->content->data; end = pos + part->content->len; - while (pos < end && (pos = rspamd_trie_lookup (trie, pos, part->content->len, &id)) != NULL) { + while (pos < end && + (pos = + rspamd_trie_lookup (trie, pos, part->content->len, + &id)) != NULL) { lua_pushinteger (L, i); lua_pushinteger (L, id); lua_settable (L, -3); - i ++; + i++; found = TRUE; break; } @@ -1049,7 +1122,7 @@ luaopen_trie (lua_State * L) lua_pushstring (L, "rspamd{trie}"); lua_rawset (L, -3); - luaL_register (L, NULL, trielib_m); + luaL_register (L, NULL, trielib_m); luaL_register (L, "rspamd_trie", trielib_f); lua_pop (L, 1); /* remove metatable from stack */ diff --git a/src/lua/lua_dns.c b/src/lua/lua_dns.c index 49ed205da..e0930a2aa 100644 --- a/src/lua/lua_dns.c +++ b/src/lua/lua_dns.c @@ -25,7 +25,7 @@ #include "dns.h" /* Public prototypes */ -struct rspamd_dns_resolver *lua_check_dns_resolver (lua_State * L); +struct rspamd_dns_resolver * lua_check_dns_resolver (lua_State * L); gint luaopen_dns_resolver (lua_State * L); /* Lua bindings */ @@ -36,12 +36,12 @@ LUA_FUNCTION_DEF (dns_resolver, resolve_txt); LUA_FUNCTION_DEF (dns_resolver, resolve_mx); LUA_FUNCTION_DEF (dns_resolver, resolve); -static const struct luaL_reg dns_resolverlib_f[] = { +static const struct luaL_reg dns_resolverlib_f[] = { LUA_INTERFACE_DEF (dns_resolver, init), {NULL, NULL} }; -static const struct luaL_reg dns_resolverlib_m[] = { +static const struct luaL_reg dns_resolverlib_m[] = { LUA_INTERFACE_DEF (dns_resolver, resolve_a), LUA_INTERFACE_DEF (dns_resolver, resolve_ptr), LUA_INTERFACE_DEF (dns_resolver, resolve_txt), @@ -51,20 +51,20 @@ static const struct luaL_reg dns_resolverlib_m[] = { {NULL, NULL} }; -struct rspamd_dns_resolver * +struct rspamd_dns_resolver * lua_check_dns_resolver (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{resolver}"); + void *ud = luaL_checkudata (L, 1, "rspamd{resolver}"); luaL_argcheck (L, ud != NULL, 1, "'resolver' expected"); return ud ? *((struct rspamd_dns_resolver **)ud) : NULL; } struct lua_dns_cbdata { - lua_State *L; - struct rspamd_dns_resolver *resolver; - gint cbref; - const gchar *to_resolve; - const gchar *user_str; + lua_State *L; + struct rspamd_dns_resolver *resolver; + gint cbref; + const gchar *to_resolve; + const gchar *user_str; }; static int @@ -86,11 +86,11 @@ lua_dns_get_type (lua_State *L, int argno) static void lua_dns_callback (struct rdns_reply *reply, gpointer arg) { - struct lua_dns_cbdata *cd = arg; - gint i = 0; - struct rspamd_dns_resolver **presolver; - struct rdns_reply_entry *elt; - rspamd_inet_addr_t addr; + struct lua_dns_cbdata *cd = arg; + gint i = 0; + struct rspamd_dns_resolver **presolver; + struct rdns_reply_entry *elt; + rspamd_inet_addr_t addr; lua_rawgeti (cd->L, LUA_REGISTRYINDEX, cd->cbref); presolver = lua_newuserdata (cd->L, sizeof (gpointer)); @@ -104,13 +104,14 @@ lua_dns_callback (struct rdns_reply *reply, gpointer arg) */ if (reply->code == RDNS_RC_NOERROR) { lua_newtable (cd->L); - LL_FOREACH (reply->entries, elt) { + LL_FOREACH (reply->entries, elt) + { switch (elt->type) { case RDNS_REQUEST_A: addr.af = AF_INET; addr.slen = sizeof (addr.addr.s4); memcpy (&addr.addr.s4.sin_addr, &elt->content.a.addr, - sizeof (addr.addr.s4.sin_addr)); + sizeof (addr.addr.s4.sin_addr)); lua_ip_push (cd->L, &addr); lua_rawseti (cd->L, -2, ++i); break; @@ -118,7 +119,7 @@ lua_dns_callback (struct rdns_reply *reply, gpointer arg) addr.af = AF_INET6; addr.slen = sizeof (addr.addr.s6); memcpy (&addr.addr.s6.sin6_addr, &elt->content.aaa.addr, - sizeof (addr.addr.s6.sin6_addr)); + sizeof (addr.addr.s6.sin6_addr)); lua_ip_push (cd->L, &addr); lua_rawseti (cd->L, -2, ++i); break; @@ -168,16 +169,16 @@ lua_dns_callback (struct rdns_reply *reply, gpointer arg) static int lua_dns_resolver_init (lua_State *L) { - struct rspamd_dns_resolver *resolver, **presolver; - struct rspamd_config *cfg, **pcfg; - struct event_base *base, **pbase; + struct rspamd_dns_resolver *resolver, **presolver; + struct rspamd_config *cfg, **pcfg; + struct event_base *base, **pbase; /* Check args */ pbase = luaL_checkudata (L, 1, "rspamd{ev_base}"); luaL_argcheck (L, pbase != NULL, 1, "'ev_base' expected"); base = pbase ? *(pbase) : NULL; pcfg = luaL_checkudata (L, 2, "rspamd{config}"); - luaL_argcheck (L, pcfg != NULL, 2, "'config' expected"); + luaL_argcheck (L, pcfg != NULL, 2, "'config' expected"); cfg = pcfg ? *(pcfg) : NULL; if (base != NULL && cfg != NULL) { @@ -199,24 +200,27 @@ lua_dns_resolver_init (lua_State *L) } static int -lua_dns_resolver_resolve_common (lua_State *L, struct rspamd_dns_resolver *resolver, - enum rdns_request_type type, int first) +lua_dns_resolver_resolve_common (lua_State *L, + struct rspamd_dns_resolver *resolver, + enum rdns_request_type type, + int first) { - struct rspamd_async_session *session, **psession; - rspamd_mempool_t *pool, **ppool; - const gchar *to_resolve; - struct lua_dns_cbdata *cbdata; + struct rspamd_async_session *session, **psession; + rspamd_mempool_t *pool, **ppool; + const gchar *to_resolve; + struct lua_dns_cbdata *cbdata; /* Check arguments */ psession = luaL_checkudata (L, first, "rspamd{session}"); - luaL_argcheck (L, psession != NULL, first, "'session' expected"); + luaL_argcheck (L, psession != NULL, first, "'session' expected"); session = psession ? *(psession) : NULL; ppool = luaL_checkudata (L, first + 1, "rspamd{mempool}"); - luaL_argcheck (L, ppool != NULL, first + 1, "'mempool' expected"); + luaL_argcheck (L, ppool != NULL, first + 1, "'mempool' expected"); pool = ppool ? *(ppool) : NULL; to_resolve = luaL_checkstring (L, first + 2); - if (pool != NULL && session != NULL && to_resolve != NULL && lua_isfunction (L, first + 3)) { + if (pool != NULL && session != NULL && to_resolve != NULL && + lua_isfunction (L, first + 3)) { cbdata = rspamd_mempool_alloc (pool, sizeof (struct lua_dns_cbdata)); cbdata->L = L; cbdata->resolver = resolver; @@ -243,7 +247,13 @@ lua_dns_resolver_resolve_common (lua_State *L, struct rspamd_dns_resolver *resol else { cbdata->user_str = NULL; } - make_dns_request (resolver, session, pool, lua_dns_callback, cbdata, type, to_resolve); + make_dns_request (resolver, + session, + pool, + lua_dns_callback, + cbdata, + type, + to_resolve); lua_pushboolean (L, TRUE); } else { @@ -258,10 +268,13 @@ lua_dns_resolver_resolve_common (lua_State *L, struct rspamd_dns_resolver *resol static int lua_dns_resolver_resolve_a (lua_State *L) { - struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); + struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); if (dns_resolver) { - return lua_dns_resolver_resolve_common (L, dns_resolver, RDNS_REQUEST_A, 2); + return lua_dns_resolver_resolve_common (L, + dns_resolver, + RDNS_REQUEST_A, + 2); } else { lua_pushnil (L); @@ -273,10 +286,13 @@ lua_dns_resolver_resolve_a (lua_State *L) static int lua_dns_resolver_resolve_ptr (lua_State *L) { - struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); + struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); if (dns_resolver) { - return lua_dns_resolver_resolve_common (L, dns_resolver, RDNS_REQUEST_PTR, 2); + return lua_dns_resolver_resolve_common (L, + dns_resolver, + RDNS_REQUEST_PTR, + 2); } else { lua_pushnil (L); @@ -288,10 +304,13 @@ lua_dns_resolver_resolve_ptr (lua_State *L) static int lua_dns_resolver_resolve_txt (lua_State *L) { - struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); + struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); if (dns_resolver) { - return lua_dns_resolver_resolve_common (L, dns_resolver, RDNS_REQUEST_TXT, 2); + return lua_dns_resolver_resolve_common (L, + dns_resolver, + RDNS_REQUEST_TXT, + 2); } else { lua_pushnil (L); @@ -303,10 +322,13 @@ lua_dns_resolver_resolve_txt (lua_State *L) static int lua_dns_resolver_resolve_mx (lua_State *L) { - struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); + struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); if (dns_resolver) { - return lua_dns_resolver_resolve_common (L, dns_resolver, RDNS_REQUEST_MX, 2); + return lua_dns_resolver_resolve_common (L, + dns_resolver, + RDNS_REQUEST_MX, + 2); } else { lua_pushnil (L); @@ -318,7 +340,7 @@ lua_dns_resolver_resolve_mx (lua_State *L) static int lua_dns_resolver_resolve (lua_State *L) { - struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); + struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L); int type; type = lua_dns_get_type (L, 2); @@ -347,18 +369,18 @@ luaopen_dns_resolver (lua_State * L) lua_rawset (L, -3); { - LUA_ENUM(L, RDNS_REQUEST_A, RDNS_REQUEST_A); - LUA_ENUM(L, RDNS_REQUEST_PTR, RDNS_REQUEST_PTR); - LUA_ENUM(L, RDNS_REQUEST_MX, RDNS_REQUEST_MX); - LUA_ENUM(L, RDNS_REQUEST_TXT, RDNS_REQUEST_TXT); - LUA_ENUM(L, RDNS_REQUEST_SRV, RDNS_REQUEST_SRV); - LUA_ENUM(L, RDNS_REQUEST_SPF, RDNS_REQUEST_SRV); - LUA_ENUM(L, RDNS_REQUEST_AAA, RDNS_REQUEST_SRV); + LUA_ENUM (L, RDNS_REQUEST_A, RDNS_REQUEST_A); + LUA_ENUM (L, RDNS_REQUEST_PTR, RDNS_REQUEST_PTR); + LUA_ENUM (L, RDNS_REQUEST_MX, RDNS_REQUEST_MX); + LUA_ENUM (L, RDNS_REQUEST_TXT, RDNS_REQUEST_TXT); + LUA_ENUM (L, RDNS_REQUEST_SRV, RDNS_REQUEST_SRV); + LUA_ENUM (L, RDNS_REQUEST_SPF, RDNS_REQUEST_SRV); + LUA_ENUM (L, RDNS_REQUEST_AAA, RDNS_REQUEST_SRV); } - luaL_register (L, NULL, dns_resolverlib_m); + luaL_register (L, NULL, dns_resolverlib_m); luaL_register (L, "rspamd_resolver", dns_resolverlib_f); lua_pop (L, 1); /* remove metatable from stack */ - return 1; + return 1; } diff --git a/src/lua/lua_http.c b/src/lua/lua_http.c index 60253c000..3ab057aee 100644 --- a/src/lua/lua_http.c +++ b/src/lua/lua_http.c @@ -31,7 +31,7 @@ LUA_FUNCTION_DEF (http, make_post_request); LUA_FUNCTION_DEF (http, make_get_request); -static const struct luaL_reg httplib_m[] = { +static const struct luaL_reg httplib_m[] = { LUA_INTERFACE_DEF (http, make_post_request), LUA_INTERFACE_DEF (http, make_get_request), {"__tostring", lua_class_tostring}, @@ -68,7 +68,7 @@ struct lua_http_ud { static void lua_http_fin (void *arg) { - struct lua_http_ud *ud = arg; + struct lua_http_ud *ud = arg; if (ud->callback == NULL) { /* Unref callback */ @@ -81,8 +81,8 @@ lua_http_fin (void *arg) static void lua_http_push_error (gint code, struct lua_http_ud *ud) { - struct rspamd_task **ptask; - gint num; + struct rspamd_task **ptask; + gint num; /* Push error */ if (ud->callback) { @@ -104,7 +104,9 @@ lua_http_push_error (gint code, struct lua_http_ud *ud) /* Reply */ lua_pushnil (ud->L); if (lua_pcall (ud->L, num, 0, 0) != 0) { - msg_info ("call to %s failed: %s", ud->callback ? ud->callback : "local function", lua_tostring (ud->L, -1)); + msg_info ("call to %s failed: %s", + ud->callback ? ud->callback : "local function", + lua_tostring (ud->L, -1)); } if (ud->headers != NULL) { @@ -120,10 +122,10 @@ lua_http_push_error (gint code, struct lua_http_ud *ud) static void lua_http_push_reply (f_str_t *in, struct lua_http_ud *ud) { - GList *cur; - struct lua_http_header *header; - struct rspamd_task **ptask; - gint num; + GList *cur; + struct lua_http_header *header; + struct rspamd_task **ptask; + gint num; if (ud->callback) { /* Push error */ @@ -156,12 +158,14 @@ lua_http_push_reply (f_str_t *in, struct lua_http_ud *ud) /* Date */ if (ud->date != (time_t)-1) { - num ++; + num++; lua_pushnumber (ud->L, ud->date); } if (lua_pcall (ud->L, num, 0, 0) != 0) { - msg_info ("call to %s failed: %s", ud->callback ? ud->callback : "local function", lua_tostring (ud->L, -1)); + msg_info ("call to %s failed: %s", + ud->callback ? ud->callback : "local function", + lua_tostring (ud->L, -1)); } if (ud->headers != NULL) { @@ -179,7 +183,7 @@ lua_http_push_reply (f_str_t *in, struct lua_http_ud *ud) static gboolean lua_http_parse_first_line (struct lua_http_ud *ud, f_str_t *in) { - const gchar *p; + const gchar *p; /* Assume first line is like this: HTTP/1.1 200 OK */ if (in->len < sizeof ("HTTP/1.1 OK") + 2) { @@ -197,14 +201,14 @@ lua_http_parse_first_line (struct lua_http_ud *ud, f_str_t *in) static gboolean lua_http_parse_header_line (struct lua_http_ud *ud, f_str_t *in) { - const gchar *p = in->begin; - struct lua_http_header *new; + const gchar *p = in->begin; + struct lua_http_header *new; while (p < in->begin + in->len) { if (*p == ':') { break; } - p ++; + p++; } if (*p != ':') { @@ -215,16 +219,17 @@ lua_http_parse_header_line (struct lua_http_ud *ud, f_str_t *in) new->name = rspamd_mempool_alloc (ud->pool, p - in->begin + 1); rspamd_strlcpy (new->name, in->begin, p - in->begin + 1); - p ++; + p++; /* Copy value */ while (p < in->begin + in->len && g_ascii_isspace (*p)) { - p ++; + p++; } new->value = rspamd_mempool_alloc (ud->pool, in->begin + in->len - p + 1); rspamd_strlcpy (new->value, p, in->begin + in->len - p + 1); /* Check content-length */ - if (ud->rep_len == 0 && g_ascii_strcasecmp (new->name, "content-length") == 0) { + if (ud->rep_len == 0 && + g_ascii_strcasecmp (new->name, "content-length") == 0) { ud->rep_len = strtoul (new->value, NULL, 10); } @@ -243,7 +248,7 @@ lua_http_parse_header_line (struct lua_http_ud *ud, f_str_t *in) static gboolean lua_http_read_cb (f_str_t * in, void *arg) { - struct lua_http_ud *ud = arg; + struct lua_http_ud *ud = arg; switch (ud->parser_state) { case 0: @@ -265,7 +270,9 @@ lua_http_read_cb (f_str_t * in, void *arg) } else { ud->parser_state = 2; - rspamd_set_dispatcher_policy (ud->io_dispatcher, BUFFER_CHARACTER, ud->rep_len); + rspamd_set_dispatcher_policy (ud->io_dispatcher, + BUFFER_CHARACTER, + ud->rep_len); } } else { @@ -284,8 +291,9 @@ lua_http_read_cb (f_str_t * in, void *arg) static void lua_http_err_cb (GError * err, void *arg) { - struct lua_http_ud *ud = arg; - msg_info ("abnormally closing connection to http server error: %s", err->message); + struct lua_http_ud *ud = arg; + msg_info ("abnormally closing connection to http server error: %s", + err->message); g_error_free (err); if (ud->parser_state != 3) { @@ -301,10 +309,10 @@ lua_http_err_cb (GError * err, void *arg) static void lua_http_dns_callback (struct rdns_reply *reply, gpointer arg) { - struct lua_http_ud *ud = arg; - struct rdns_reply_entry *elt; - struct in_addr ina; - struct timeval tv; + struct lua_http_ud *ud = arg; + struct rdns_reply_entry *elt; + struct in_addr ina; + struct timeval tv; if (reply->code != RDNS_RC_NOERROR) { lua_http_push_error (450, ud); @@ -315,7 +323,8 @@ lua_http_dns_callback (struct rdns_reply *reply, gpointer arg) elt = reply->entries; memcpy (&ina, &elt->content.a.addr, sizeof (struct in_addr)); - ud->fd = make_universal_socket (inet_ntoa (ina), ud->port, SOCK_STREAM, TRUE, FALSE, FALSE); + ud->fd = make_universal_socket (inet_ntoa ( + ina), ud->port, SOCK_STREAM, TRUE, FALSE, FALSE); if (ud->fd == -1) { lua_http_push_error (450, ud); @@ -324,12 +333,20 @@ lua_http_dns_callback (struct rdns_reply *reply, gpointer arg) /* Create dispatcher for HTTP protocol */ msec_to_tv (ud->timeout, &tv); - ud->io_dispatcher = rspamd_create_dispatcher (ud->ev_base, ud->fd, BUFFER_LINE, lua_http_read_cb, NULL, - lua_http_err_cb, &tv, ud); + ud->io_dispatcher = rspamd_create_dispatcher (ud->ev_base, + ud->fd, + BUFFER_LINE, + lua_http_read_cb, + NULL, + lua_http_err_cb, + &tv, + ud); /* Write request */ - register_async_event (ud->s, lua_http_fin, ud, g_quark_from_static_string ("lua http")); + register_async_event (ud->s, lua_http_fin, ud, + g_quark_from_static_string ("lua http")); - if (!rspamd_dispatcher_write (ud->io_dispatcher, ud->req_buf, ud->req_len, TRUE, TRUE)) { + if (!rspamd_dispatcher_write (ud->io_dispatcher, ud->req_buf, ud->req_len, + TRUE, TRUE)) { lua_http_push_error (450, ud); return; } @@ -339,16 +356,22 @@ lua_http_dns_callback (struct rdns_reply *reply, gpointer arg) * Common request function */ static gint -lua_http_make_request_common (lua_State *L, struct rspamd_task *task, const gchar *callback, - const gchar *hostname, const gchar *path, const gchar *data, gint top) +lua_http_make_request_common (lua_State *L, + struct rspamd_task *task, + const gchar *callback, + const gchar *hostname, + const gchar *path, + const gchar *data, + gint top) { - gint r, s, datalen; - struct lua_http_ud *ud; + gint r, s, datalen; + struct lua_http_ud *ud; /* Calculate buffer size */ datalen = (data != NULL) ? strlen (data) : 0; - s = MAX_HEADERS_SIZE + sizeof (CRLF) * 3 + strlen (hostname) + strlen (path) + datalen - + sizeof ("POST HTTP/1.1"); + s = MAX_HEADERS_SIZE + sizeof (CRLF) * 3 + strlen (hostname) + + strlen (path) + datalen + + sizeof ("POST HTTP/1.1"); ud = rspamd_mempool_alloc0 (task->task_pool, sizeof (struct lua_http_ud)); ud->L = L; @@ -362,11 +385,14 @@ lua_http_make_request_common (lua_State *L, struct rspamd_task *task, const gcha /* Print request */ r = rspamd_snprintf (ud->req_buf, s, "%s %s HTTP/1.1" CRLF - "Connection: close" CRLF - "Host: %s" CRLF, - (data != NULL) ? "POST" : "GET", path, hostname); + "Connection: close" CRLF + "Host: %s" CRLF, + (data != NULL) ? "POST" : "GET", path, hostname); if (datalen > 0) { - r += rspamd_snprintf (ud->req_buf + r, s - r, "Content-Length: %d" CRLF, datalen); + r += rspamd_snprintf (ud->req_buf + r, + s - r, + "Content-Length: %d" CRLF, + datalen); } /* Now assume that we have a table with headers at the top of the stack */ @@ -374,8 +400,12 @@ lua_http_make_request_common (lua_State *L, struct rspamd_task *task, const gcha /* Add headers */ lua_pushnil (L); /* first key */ while (lua_next (L, top + 1) != 0) { - r += rspamd_snprintf (ud->req_buf + r, s - r, "%s: %s" CRLF, lua_tostring (L, -2), lua_tostring (L, -1)); - lua_pop(L, 1); + r += rspamd_snprintf (ud->req_buf + r, + s - r, + "%s: %s" CRLF, + lua_tostring (L, -2), + lua_tostring (L, -1)); + lua_pop (L, 1); } } /* Now check port and timeout */ @@ -403,9 +433,10 @@ lua_http_make_request_common (lua_State *L, struct rspamd_task *task, const gcha ud->req_len = r; /* Resolve hostname */ - if (make_dns_request (task->resolver, task->s, task->task_pool, lua_http_dns_callback, ud, - RDNS_REQUEST_A, hostname)) { - task->dns_requests ++; + if (make_dns_request (task->resolver, task->s, task->task_pool, + lua_http_dns_callback, ud, + RDNS_REQUEST_A, hostname)) { + task->dns_requests++; } return 0; @@ -415,18 +446,26 @@ lua_http_make_request_common (lua_State *L, struct rspamd_task *task, const gcha * Common request function (new version) */ static gint -lua_http_make_request_common_new (lua_State *L, struct rspamd_async_session *session, rspamd_mempool_t *pool, struct event_base *base, gint cbref, - const gchar *hostname, const gchar *path, const gchar *data, gint top) +lua_http_make_request_common_new (lua_State *L, + struct rspamd_async_session *session, + rspamd_mempool_t *pool, + struct event_base *base, + gint cbref, + const gchar *hostname, + const gchar *path, + const gchar *data, + gint top) { - gint r, s, datalen; - struct lua_http_ud *ud; - struct in_addr ina; - struct timeval tv; + gint r, s, datalen; + struct lua_http_ud *ud; + struct in_addr ina; + struct timeval tv; /* Calculate buffer size */ datalen = (data != NULL) ? strlen (data) : 0; - s = MAX_HEADERS_SIZE + sizeof (CRLF) * 3 + strlen (hostname) + strlen (path) + datalen - + sizeof ("POST HTTP/1.1"); + s = MAX_HEADERS_SIZE + sizeof (CRLF) * 3 + strlen (hostname) + + strlen (path) + datalen + + sizeof ("POST HTTP/1.1"); ud = rspamd_mempool_alloc0 (pool, sizeof (struct lua_http_ud)); ud->L = L; @@ -440,10 +479,13 @@ lua_http_make_request_common_new (lua_State *L, struct rspamd_async_session *ses /* Print request */ r = rspamd_snprintf (ud->req_buf, s, "%s %s HTTP/1.1" CRLF - "Connection: close" CRLF, - (data != NULL) ? "POST" : "GET", path); + "Connection: close" CRLF, + (data != NULL) ? "POST" : "GET", path); if (datalen > 0) { - r += rspamd_snprintf (ud->req_buf + r, s - r, "Content-Length: %d" CRLF, datalen); + r += rspamd_snprintf (ud->req_buf + r, + s - r, + "Content-Length: %d" CRLF, + datalen); } /* Now assume that we have a table with headers at the top of the stack */ @@ -451,7 +493,11 @@ lua_http_make_request_common_new (lua_State *L, struct rspamd_async_session *ses /* Add headers */ lua_pushnil (L); /* first key */ while (lua_next (L, top + 1) != 0) { - r += rspamd_snprintf (ud->req_buf + r, s - r, "%s: %s" CRLF, lua_tostring (L, -2), lua_tostring (L, -1)); + r += rspamd_snprintf (ud->req_buf + r, + s - r, + "%s: %s" CRLF, + lua_tostring (L, -2), + lua_tostring (L, -1)); lua_pop (L, 1); } } @@ -486,7 +532,8 @@ lua_http_make_request_common_new (lua_State *L, struct rspamd_async_session *ses return 1; } - ud->fd = make_universal_socket (inet_ntoa (ina), ud->port, SOCK_STREAM, TRUE, FALSE, FALSE); + ud->fd = make_universal_socket (inet_ntoa ( + ina), ud->port, SOCK_STREAM, TRUE, FALSE, FALSE); if (ud->fd == -1) { luaL_unref (L, LUA_REGISTRYINDEX, cbref); @@ -496,12 +543,20 @@ lua_http_make_request_common_new (lua_State *L, struct rspamd_async_session *ses /* Create dispatcher for HTTP protocol */ msec_to_tv (ud->timeout, &tv); - ud->io_dispatcher = rspamd_create_dispatcher (ud->ev_base, ud->fd, BUFFER_LINE, lua_http_read_cb, NULL, - lua_http_err_cb, &tv, ud); + ud->io_dispatcher = rspamd_create_dispatcher (ud->ev_base, + ud->fd, + BUFFER_LINE, + lua_http_read_cb, + NULL, + lua_http_err_cb, + &tv, + ud); /* Write request */ - register_async_event (ud->s, lua_http_fin, ud, g_quark_from_static_string ("lua http")); + register_async_event (ud->s, lua_http_fin, ud, + g_quark_from_static_string ("lua http")); - if (!rspamd_dispatcher_write (ud->io_dispatcher, ud->req_buf, ud->req_len, TRUE, TRUE)) { + if (!rspamd_dispatcher_write (ud->io_dispatcher, ud->req_buf, ud->req_len, + TRUE, TRUE)) { luaL_unref (L, LUA_REGISTRYINDEX, cbref); lua_pushnil (L); return 1; @@ -518,12 +573,12 @@ lua_http_make_request_common_new (lua_State *L, struct rspamd_async_session *ses static gint lua_http_make_post_request (lua_State *L) { - struct rspamd_task *task, **ptask; - rspamd_mempool_t *pool, **ppool; - struct rspamd_async_session *session, **psession; - struct event_base *base, **pbase; - const gchar *hostname, *path, *data, *callback; - gint cbref; + struct rspamd_task *task, **ptask; + rspamd_mempool_t *pool, **ppool; + struct rspamd_async_session *session, **psession; + struct event_base *base, **pbase; + const gchar *hostname, *path, *data, *callback; + gint cbref; /* Check whether we have a task object */ @@ -535,23 +590,32 @@ lua_http_make_post_request (lua_State *L) luaL_argcheck (L, psession != NULL, 1, "'session' expected"); session = psession ? *(psession) : NULL; ppool = luaL_checkudata (L, 2, "rspamd{mempool}"); - luaL_argcheck (L, ppool != NULL, 2, "'mempool' expected"); + luaL_argcheck (L, ppool != NULL, 2, "'mempool' expected"); pool = ppool ? *(ppool) : NULL; pbase = luaL_checkudata (L, 3, "rspamd{ev_base}"); - luaL_argcheck (L, ppool != NULL, 3, "'ev_base' expected"); + luaL_argcheck (L, ppool != NULL, 3, "'ev_base' expected"); base = pbase ? *(pbase) : NULL; } /* Now extract hostname, path and data */ if (task) { - callback = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 2)); - hostname = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 3)); + callback = + rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 2)); + hostname = + rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 3)); path = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 4)); data = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 5)); - if (callback != NULL && hostname != NULL && path != NULL && data != NULL) { - return lua_http_make_request_common (L, task, callback, hostname, path, data, 5); + if (callback != NULL && hostname != NULL && path != NULL && data != + NULL) { + return lua_http_make_request_common (L, + task, + callback, + hostname, + path, + data, + 5); } else { msg_info ("invalid arguments number"); @@ -562,10 +626,19 @@ lua_http_make_post_request (lua_State *L) hostname = rspamd_mempool_strdup (pool, luaL_checkstring (L, 4)); path = rspamd_mempool_strdup (pool, luaL_checkstring (L, 5)); data = rspamd_mempool_strdup (pool, luaL_checkstring (L, 6)); - if (session != NULL && pool != NULL && hostname != NULL && path != NULL && data != NULL && lua_isfunction (L, 7)) { + if (session != NULL && pool != NULL && hostname != NULL && path != + NULL && data != NULL && lua_isfunction (L, 7)) { lua_pushvalue (L, 7); cbref = luaL_ref (L, LUA_REGISTRYINDEX); - return lua_http_make_request_common_new (L, session, pool, base, cbref, hostname, path, data, 7); + return lua_http_make_request_common_new (L, + session, + pool, + base, + cbref, + hostname, + path, + data, + 7); } } @@ -579,12 +652,12 @@ lua_http_make_post_request (lua_State *L) static gint lua_http_make_get_request (lua_State *L) { - struct rspamd_task *task, **ptask; - rspamd_mempool_t *pool, **ppool; - struct rspamd_async_session *session, **psession; - struct event_base *base, **pbase; - const gchar *hostname, *path, *callback; - gint cbref; + struct rspamd_task *task, **ptask; + rspamd_mempool_t *pool, **ppool; + struct rspamd_async_session *session, **psession; + struct event_base *base, **pbase; + const gchar *hostname, *path, *callback; + gint cbref; /* Check whether we have a task object */ @@ -596,22 +669,30 @@ lua_http_make_get_request (lua_State *L) luaL_argcheck (L, psession != NULL, 1, "'session' expected"); session = psession ? *(psession) : NULL; ppool = luaL_checkudata (L, 2, "rspamd{mempool}"); - luaL_argcheck (L, ppool != NULL, 2, "'mempool' expected"); + luaL_argcheck (L, ppool != NULL, 2, "'mempool' expected"); pool = ppool ? *(ppool) : NULL; pbase = luaL_checkudata (L, 3, "rspamd{ev_base}"); - luaL_argcheck (L, ppool != NULL, 3, "'ev_base' expected"); + luaL_argcheck (L, ppool != NULL, 3, "'ev_base' expected"); base = pbase ? *(pbase) : NULL; } /* Now extract hostname, path and data */ if (task) { - callback = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 2)); - hostname = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 3)); + callback = + rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 2)); + hostname = + rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 3)); path = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 4)); if (callback != NULL && hostname != NULL && path != NULL) { - return lua_http_make_request_common (L, task, callback, hostname, path, NULL, 4); + return lua_http_make_request_common (L, + task, + callback, + hostname, + path, + NULL, + 4); } else { msg_info ("invalid arguments number"); @@ -621,10 +702,19 @@ lua_http_make_get_request (lua_State *L) /* Common version */ hostname = rspamd_mempool_strdup (pool, luaL_checkstring (L, 4)); path = rspamd_mempool_strdup (pool, luaL_checkstring (L, 5)); - if (session != NULL && pool != NULL && hostname != NULL && path != NULL && lua_isfunction (L, 6)) { + if (session != NULL && pool != NULL && hostname != NULL && path != + NULL && lua_isfunction (L, 6)) { lua_pushvalue (L, 6); cbref = luaL_ref (L, LUA_REGISTRYINDEX); - return lua_http_make_request_common_new (L, session, pool, base, cbref, hostname, path, NULL, 6); + return lua_http_make_request_common_new (L, + session, + pool, + base, + cbref, + hostname, + path, + NULL, + 6); } } diff --git a/src/lua/lua_ip.c b/src/lua/lua_ip.c index f477e1d77..3292d93e7 100644 --- a/src/lua/lua_ip.c +++ b/src/lua/lua_ip.c @@ -34,7 +34,7 @@ LUA_FUNCTION_DEF (ip, destroy); LUA_FUNCTION_DEF (ip, get_version); LUA_FUNCTION_DEF (ip, is_valid); -static const struct luaL_reg iplib_m[] = { +static const struct luaL_reg iplib_m[] = { LUA_INTERFACE_DEF (ip, to_string), LUA_INTERFACE_DEF (ip, to_table), LUA_INTERFACE_DEF (ip, to_number), @@ -47,13 +47,13 @@ static const struct luaL_reg iplib_m[] = { {NULL, NULL} }; -static const struct luaL_reg iplib_f[] = { +static const struct luaL_reg iplib_f[] = { LUA_INTERFACE_DEF (ip, from_string), LUA_INTERFACE_DEF (ip, from_number), {NULL, NULL} }; -static struct rspamd_lua_ip * +static struct rspamd_lua_ip * lua_check_ip (lua_State * L, gint pos) { void *ud = luaL_checkudata (L, pos, "rspamd{ip}"); @@ -80,7 +80,7 @@ lua_ip_to_table (lua_State *L) ptr = (guint8 *)&ip->addr.addr.s6.sin6_addr; } - for (i = 1; i <= max; i ++, ptr ++) { + for (i = 1; i <= max; i++, ptr++) { lua_pushnumber (L, *ptr); lua_rawseti (L, -2, i); } @@ -111,19 +111,22 @@ lua_ip_str_octets (lua_State *L) ptr = (guint8 *)&ip->addr.addr.s6.sin6_addr; } - for (i = 1; i <= max; i ++, ptr ++) { + for (i = 1; i <= max; i++, ptr++) { if (ip->addr.af == AF_INET) { rspamd_snprintf (numbuf, sizeof (numbuf), "%d", *ptr); lua_pushstring (L, numbuf); lua_rawseti (L, -2, i); } else { - rspamd_snprintf (numbuf, sizeof (numbuf), "%xd", (*ptr & 0xf0) >> 4); + rspamd_snprintf (numbuf, + sizeof (numbuf), + "%xd", + (*ptr & 0xf0) >> 4); lua_pushstring (L, numbuf); - lua_rawseti (L, -2, i*2 - 1); + lua_rawseti (L, -2, i * 2 - 1); rspamd_snprintf (numbuf, sizeof (numbuf), "%xd", *ptr & 0x0f); lua_pushstring (L, numbuf); - lua_rawseti (L, -2, i*2); + lua_rawseti (L, -2, i * 2); } } } @@ -154,7 +157,7 @@ lua_ip_inversed_str_octets (lua_State *L) } ptr += max - 1; - for (i = 1; i <= max; i ++, ptr --) { + for (i = 1; i <= max; i++, ptr--) { if (ip->addr.af == AF_INET) { rspamd_snprintf (numbuf, sizeof (numbuf), "%d", *ptr); lua_pushstring (L, numbuf); @@ -163,10 +166,13 @@ lua_ip_inversed_str_octets (lua_State *L) else { rspamd_snprintf (numbuf, sizeof (numbuf), "%xd", *ptr & 0x0f); lua_pushstring (L, numbuf); - lua_rawseti (L, -2, i*2 - 1); - rspamd_snprintf (numbuf, sizeof (numbuf), "%xd", (*ptr & 0xf0) >> 4); + lua_rawseti (L, -2, i * 2 - 1); + rspamd_snprintf (numbuf, + sizeof (numbuf), + "%xd", + (*ptr & 0xf0) >> 4); lua_pushstring (L, numbuf); - lua_rawseti (L, -2, i*2); + lua_rawseti (L, -2, i * 2); } } } @@ -226,9 +232,10 @@ lua_ip_to_number (lua_State *L) } else { /* 4 integers in host byte order */ - G_STATIC_ASSERT (sizeof (ip->addr.addr.s6.sin6_addr) >= sizeof (dst)); + G_STATIC_ASSERT (sizeof (ip->addr.addr.s6.sin6_addr) >= + sizeof (dst)); memcpy (dst, &ip->addr.addr.s6.sin6_addr, sizeof (dst)); - for (i = 0; i < G_N_ELEMENTS (dst); i ++) { + for (i = 0; i < G_N_ELEMENTS (dst); i++) { lua_pushinteger (L, ntohl (dst[i])); } return 4; @@ -260,7 +267,7 @@ lua_ip_from_number (lua_State *L) } else if (lua_gettop (L) == 4 && lua_isnumber (L, 1)) { /* Ipv6 version */ - for (i = 0; i < 4; i ++) { + for (i = 0; i < 4; i++) { src[i] = htonl (lua_tonumber (L, i + 1)); } G_STATIC_ASSERT (sizeof (ip->addr.addr.s6.sin6_addr) >= sizeof (src)); @@ -370,7 +377,7 @@ luaopen_ip (lua_State * L) lua_pushstring (L, "rspamd{ip}"); lua_rawset (L, -3); - luaL_register (L, NULL, iplib_m); + luaL_register (L, NULL, iplib_m); luaL_register (L, "rspamd_ip", iplib_f); lua_pop (L, 1); /* remove metatable from stack */ diff --git a/src/lua/lua_mempool.c b/src/lua/lua_mempool.c index 2648a60b2..50de17dd1 100644 --- a/src/lua/lua_mempool.c +++ b/src/lua/lua_mempool.c @@ -25,7 +25,7 @@ #include "mem_pool.h" /* Public prototypes */ -struct memory_pool_s *lua_check_mempool (lua_State * L); +struct memory_pool_s * lua_check_mempool (lua_State * L); gint luaopen_mempool (lua_State * L); /* Lua bindings */ @@ -37,7 +37,7 @@ LUA_FUNCTION_DEF (mempool, memory_pool_suggest_size); LUA_FUNCTION_DEF (mempool, memory_pool_set_variable); LUA_FUNCTION_DEF (mempool, memory_pool_get_variable); -static const struct luaL_reg mempoollib_m[] = { +static const struct luaL_reg mempoollib_m[] = { LUA_INTERFACE_DEF (mempool, memory_pool_add_destructor), LUA_INTERFACE_DEF (mempool, memory_pool_stat), LUA_INTERFACE_DEF (mempool, memory_pool_suggest_size), @@ -48,7 +48,7 @@ static const struct luaL_reg mempoollib_m[] = { {NULL, NULL} }; -static const struct luaL_reg mempoollib_f[] = { +static const struct luaL_reg mempoollib_f[] = { LUA_INTERFACE_DEF (mempool, create), {NULL, NULL} }; @@ -63,10 +63,10 @@ struct lua_mempool_udata { rspamd_mempool_t *mempool; }; -struct memory_pool_s * +struct memory_pool_s * lua_check_mempool (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{mempool}"); + void *ud = luaL_checkudata (L, 1, "rspamd{mempool}"); luaL_argcheck (L, ud != NULL, 1, "'mempool' expected"); return ud ? *((struct memory_pool_s **)ud) : NULL; } @@ -75,7 +75,8 @@ lua_check_mempool (lua_State * L) static int lua_mempool_create (lua_State *L) { - struct memory_pool_s *mempool = rspamd_mempool_new (rspamd_mempool_suggest_size ()), **pmempool; + struct memory_pool_s *mempool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()), **pmempool; if (mempool) { pmempool = lua_newuserdata (L, sizeof (struct memory_pool_s *)); @@ -92,7 +93,7 @@ lua_mempool_create (lua_State *L) static void lua_mempool_destructor_func (gpointer p) { - struct lua_mempool_udata *ud = p; + struct lua_mempool_udata *ud = p; lua_rawgeti (ud->L, LUA_REGISTRYINDEX, ud->cbref); if (lua_pcall (ud->L, 0, 0, 0) != 0) { @@ -104,18 +105,21 @@ lua_mempool_destructor_func (gpointer p) static int lua_mempool_memory_pool_add_destructor (lua_State *L) { - struct memory_pool_s *mempool = lua_check_mempool (L); - struct lua_mempool_udata *ud; + struct memory_pool_s *mempool = lua_check_mempool (L); + struct lua_mempool_udata *ud; if (mempool) { if (lua_isfunction (L, 2)) { - ud = rspamd_mempool_alloc (mempool, sizeof (struct lua_mempool_udata)); + ud = rspamd_mempool_alloc (mempool, + sizeof (struct lua_mempool_udata)); lua_pushvalue (L, 2); /* Get a reference */ ud->cbref = luaL_ref (L, LUA_REGISTRYINDEX); ud->L = L; ud->mempool = mempool; - rspamd_mempool_add_destructor (mempool, lua_mempool_destructor_func, ud); + rspamd_mempool_add_destructor (mempool, + lua_mempool_destructor_func, + ud); } else { msg_err ("trying to add destructor without function"); @@ -131,7 +135,7 @@ lua_mempool_memory_pool_add_destructor (lua_State *L) static int lua_mempool_memory_pool_delete (lua_State *L) { - struct memory_pool_s *mempool = lua_check_mempool (L); + struct memory_pool_s *mempool = lua_check_mempool (L); if (mempool) { rspamd_mempool_delete (mempool); @@ -147,10 +151,10 @@ lua_mempool_memory_pool_delete (lua_State *L) static int lua_mempool_memory_pool_stat (lua_State *L) { - struct memory_pool_s *mempool = lua_check_mempool (L); + struct memory_pool_s *mempool = lua_check_mempool (L); if (mempool) { - + } else { lua_pushnil (L); @@ -162,7 +166,7 @@ lua_mempool_memory_pool_stat (lua_State *L) static int lua_mempool_memory_pool_suggest_size (lua_State *L) { - struct memory_pool_s *mempool = lua_check_mempool (L); + struct memory_pool_s *mempool = lua_check_mempool (L); if (mempool) { lua_pushinteger (L, rspamd_mempool_suggest_size ()); @@ -178,12 +182,13 @@ lua_mempool_memory_pool_suggest_size (lua_State *L) static int lua_mempool_memory_pool_set_variable (lua_State *L) { - struct memory_pool_s *mempool = lua_check_mempool (L); - const gchar *var = luaL_checkstring (L, 2), - *value = luaL_checkstring (L, 3); + struct memory_pool_s *mempool = lua_check_mempool (L); + const gchar *var = luaL_checkstring (L, 2), + *value = luaL_checkstring (L, 3); if (mempool && var && value) { - rspamd_mempool_set_variable (mempool, var, rspamd_mempool_strdup (mempool, value), NULL); + rspamd_mempool_set_variable (mempool, var, + rspamd_mempool_strdup (mempool, value), NULL); return 0; } else { @@ -196,9 +201,9 @@ lua_mempool_memory_pool_set_variable (lua_State *L) static int lua_mempool_memory_pool_get_variable (lua_State *L) { - struct memory_pool_s *mempool = lua_check_mempool (L); - const gchar *var = luaL_checkstring (L, 2); - gchar *value; + struct memory_pool_s *mempool = lua_check_mempool (L); + const gchar *var = luaL_checkstring (L, 2); + gchar *value; if (mempool && var) { value = rspamd_mempool_get_variable (mempool, var); @@ -228,10 +233,10 @@ luaopen_mempool (lua_State * L) lua_pushstring (L, "rspamd{mempool}"); lua_rawset (L, -3); - luaL_register (L, NULL, mempoollib_m); + luaL_register (L, NULL, mempoollib_m); luaL_register (L, "rspamd_mempool", mempoollib_f); lua_pop (L, 1); /* remove metatable from stack */ - return 1; + return 1; } diff --git a/src/lua/lua_message.c b/src/lua/lua_message.c index f02178d1a..8dd89c75c 100644 --- a/src/lua/lua_message.c +++ b/src/lua/lua_message.c @@ -26,35 +26,35 @@ #include "lua_common.h" #include "message.h" -#define LUA_GMIME_BRIDGE_GET(class, name, mime_class) \ -static gint \ -lua_##class##_##name(lua_State *L) \ -{ \ - GMime##mime_class *obj = lua_check_##class(L); \ - if (obj != NULL) { \ - lua_pushstring (L, g_mime_##class##_##name(obj)); \ - } \ - else { \ - lua_pushnil (L); \ - } \ - return 1; \ -} +#define LUA_GMIME_BRIDGE_GET(class, name, mime_class) \ + static gint \ + lua_ ## class ## _ ## name (lua_State * L) \ + { \ + GMime ## mime_class * obj = lua_check_ ## class (L); \ + if (obj != NULL) { \ + lua_pushstring (L, g_mime_ ## class ## _ ## name (obj)); \ + } \ + else { \ + lua_pushnil (L); \ + } \ + return 1; \ + } -#define LUA_GMIME_BRIDGE_SET(class, name, mime_class) \ -static gint \ -lua_##class##_##name(lua_State *L) \ -{ \ - const gchar *str; \ - GMime##mime_class *obj = lua_check_##class(L); \ - if (obj != NULL) { \ - str = luaL_checkstring (L, 2); \ - g_mime_##class##_##name(obj, str); \ - } \ - else { \ - lua_pushnil (L); \ - } \ - return 1; \ -} +#define LUA_GMIME_BRIDGE_SET(class, name, mime_class) \ + static gint \ + lua_ ## class ## _ ## name (lua_State * L) \ + { \ + const gchar *str; \ + GMime ## mime_class * obj = lua_check_ ## class (L); \ + if (obj != NULL) { \ + str = luaL_checkstring (L, 2); \ + g_mime_ ## class ## _ ## name (obj, str); \ + } \ + else { \ + lua_pushnil (L); \ + } \ + return 1; \ + } /* Message methods */ LUA_FUNCTION_DEF (message, get_subject); @@ -70,7 +70,7 @@ LUA_FUNCTION_DEF (message, get_header_strong); LUA_FUNCTION_DEF (message, set_header); LUA_FUNCTION_DEF (message, get_date); -static const struct luaL_reg msglib_m[] = { +static const struct luaL_reg msglib_m[] = { LUA_INTERFACE_DEF (message, get_subject), LUA_INTERFACE_DEF (message, set_subject), LUA_INTERFACE_DEF (message, get_message_id), @@ -89,10 +89,10 @@ static const struct luaL_reg msglib_m[] = { -static GMimeMessage * +static GMimeMessage * lua_check_message (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{message}"); + void *ud = luaL_checkudata (L, 1, "rspamd{message}"); luaL_argcheck (L, ud != NULL, 1, "'message' expected"); return ud ? *((GMimeMessage **) ud) : NULL; } @@ -112,10 +112,10 @@ LUA_GMIME_BRIDGE_SET (message, set_reply_to, Message) static gint lua_message_get_header_common (lua_State * L, gboolean strong) { - const gchar *headern; - GMimeMessage *obj = lua_check_message (L); - GList *res = NULL, *cur; - gint i = 1; + const gchar *headern; + GMimeMessage *obj = lua_check_message (L); + GList *res = NULL, *cur; + gint i = 1; if (obj != NULL) { headern = luaL_checkstring (L, 2); @@ -162,8 +162,8 @@ lua_message_get_header_strong (lua_State * L) static gint lua_message_set_header (lua_State * L) { - const gchar *headern, *headerv; - GMimeMessage *obj = lua_check_message (L); + const gchar *headern, *headerv; + GMimeMessage *obj = lua_check_message (L); if (obj != NULL) { headern = luaL_checkstring (L, 2); @@ -185,9 +185,9 @@ lua_message_set_header (lua_State * L) static gint lua_message_get_date (lua_State * L) { - GMimeMessage *obj = lua_check_message (L); - time_t msg_time; - int offset; + GMimeMessage *obj = lua_check_message (L); + time_t msg_time; + int offset; if (obj != NULL) { g_mime_message_get_date (obj, &msg_time, &offset); diff --git a/src/lua/lua_redis.c b/src/lua/lua_redis.c index 2642daf9a..c1b52f330 100644 --- a/src/lua/lua_redis.c +++ b/src/lua/lua_redis.c @@ -41,7 +41,7 @@ LUA_FUNCTION_DEF (redis, make_request); -static const struct luaL_reg redislib_m[] = { +static const struct luaL_reg redislib_m[] = { LUA_INTERFACE_DEF (redis, make_request), {"__tostring", lua_class_tostring}, {NULL, NULL} @@ -68,10 +68,10 @@ struct lua_redis_userdata { * @param L lua stack * @return worker task object */ -static struct rspamd_task * +static struct rspamd_task * lua_check_task (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{task}"); + void *ud = luaL_checkudata (L, 1, "rspamd{task}"); luaL_argcheck (L, ud != NULL, 1, "'task' expected"); return ud ? *((struct rspamd_task **)ud) : NULL; } @@ -79,7 +79,7 @@ lua_check_task (lua_State * L) static void lua_redis_fin (void *arg) { - struct lua_redis_userdata *ud = arg; + struct lua_redis_userdata *ud = arg; if (ud->ctx) { redisAsyncFree (ud->ctx); @@ -93,9 +93,11 @@ lua_redis_fin (void *arg) * @param ud */ static void -lua_redis_push_error (const gchar *err, struct lua_redis_userdata *ud, gboolean connected) +lua_redis_push_error (const gchar *err, + struct lua_redis_userdata *ud, + gboolean connected) { - struct rspamd_task **ptask; + struct rspamd_task **ptask; /* Push error */ lua_rawgeti (ud->L, LUA_REGISTRYINDEX, ud->cbref); @@ -125,7 +127,7 @@ lua_redis_push_error (const gchar *err, struct lua_redis_userdata *ud, gboolean static void lua_redis_push_data (const redisReply *r, struct lua_redis_userdata *ud) { - struct rspamd_task **ptask; + struct rspamd_task **ptask; /* Push error */ lua_rawgeti (ud->L, LUA_REGISTRYINDEX, ud->cbref); @@ -169,8 +171,8 @@ lua_redis_push_data (const redisReply *r, struct lua_redis_userdata *ud) static void lua_redis_callback (redisAsyncContext *c, gpointer r, gpointer priv) { - redisReply *reply = r; - struct lua_redis_userdata *ud = priv; + redisReply *reply = r; + struct lua_redis_userdata *ud = priv; if (c->err == 0) { if (r != NULL) { @@ -204,11 +206,16 @@ lua_redis_make_request_real (struct lua_redis_userdata *ud) { ud->ctx = redisAsyncConnect (inet_ntoa (ud->ina), ud->port); if (ud->ctx == NULL || ud->ctx->err) { - lua_redis_push_error (ud->ctx ? ud->ctx->errstr : "unknown error", ud, FALSE); + lua_redis_push_error (ud->ctx ? ud->ctx->errstr : "unknown error", + ud, + FALSE); return FALSE; } else { - register_async_event (ud->task->s, lua_redis_fin, ud, g_quark_from_static_string ("lua redis")); + register_async_event (ud->task->s, + lua_redis_fin, + ud, + g_quark_from_static_string ("lua redis")); } redisLibeventAttach (ud->ctx, ud->task->ev_base); /* Make a request now */ @@ -217,17 +224,35 @@ lua_redis_make_request_real (struct lua_redis_userdata *ud) redisAsyncCommand (ud->ctx, lua_redis_callback, ud, ud->reqline); break; case 1: - redisAsyncCommand (ud->ctx, lua_redis_callback, ud, ud->reqline, ud->args[0].begin, ud->args[0].len); + redisAsyncCommand (ud->ctx, + lua_redis_callback, + ud, + ud->reqline, + ud->args[0].begin, + ud->args[0].len); break; case 2: - redisAsyncCommand (ud->ctx, lua_redis_callback, ud, ud->reqline, ud->args[0].begin, ud->args[0].len, - ud->args[1].begin, ud->args[1].len); + redisAsyncCommand (ud->ctx, + lua_redis_callback, + ud, + ud->reqline, + ud->args[0].begin, + ud->args[0].len, + ud->args[1].begin, + ud->args[1].len); break; default: /* XXX: cannot handle more than 3 arguments */ - redisAsyncCommand (ud->ctx, lua_redis_callback, ud, ud->reqline, ud->args[0].begin, ud->args[0].len, - ud->args[1].begin, ud->args[1].len, - ud->args[2].begin, ud->args[2].len); + redisAsyncCommand (ud->ctx, + lua_redis_callback, + ud, + ud->reqline, + ud->args[0].begin, + ud->args[0].len, + ud->args[1].begin, + ud->args[1].len, + ud->args[2].begin, + ud->args[2].len); break; } @@ -242,8 +267,8 @@ lua_redis_make_request_real (struct lua_redis_userdata *ud) static void lua_redis_dns_callback (struct rdns_reply *reply, gpointer arg) { - struct lua_redis_userdata *ud = arg; - struct rdns_reply_entry *elt; + struct lua_redis_userdata *ud = arg; + struct rdns_reply_entry *elt; if (reply->code != RDNS_RC_NOERROR) { @@ -271,18 +296,21 @@ lua_redis_dns_callback (struct rdns_reply *reply, gpointer arg) static int lua_redis_make_request (lua_State *L) { - struct rspamd_task *task; - struct lua_redis_userdata *ud; - const gchar *server, *tmp; - guint port, i; + struct rspamd_task *task; + struct lua_redis_userdata *ud; + const gchar *server, *tmp; + guint port, i; if ((task = lua_check_task (L)) != NULL) { server = luaL_checkstring (L, 2); port = luaL_checkint (L, 3); /* Now get callback */ - if (lua_isfunction (L, 4) && server != NULL && port > 0 && port < G_MAXUINT16) { + if (lua_isfunction (L, + 4) && server != NULL && port > 0 && port < G_MAXUINT16) { /* Create userdata */ - ud = rspamd_mempool_alloc (task->task_pool, sizeof (struct lua_redis_userdata)); + ud = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct lua_redis_userdata)); ud->server = rspamd_mempool_strdup (task->task_pool, server); ud->port = port; ud->task = task; @@ -292,14 +320,17 @@ lua_redis_make_request (lua_State *L) lua_pushvalue (L, 4); /* Get a reference */ ud->cbref = luaL_ref (L, LUA_REGISTRYINDEX); - ud->reqline = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 5)); + ud->reqline = rspamd_mempool_strdup (task->task_pool, + luaL_checkstring (L, 5)); /* Now get remaining args */ ud->args_num = lua_gettop (L) - 5; - ud->args = rspamd_mempool_alloc (task->task_pool, ud->args_num * sizeof (f_str_t)); - for (i = 0; i < ud->args_num; i ++) { + ud->args = rspamd_mempool_alloc (task->task_pool, + ud->args_num * sizeof (f_str_t)); + for (i = 0; i < ud->args_num; i++) { tmp = lua_tolstring (L, i + 6, &ud->args[i].len); /* Make a copy of argument */ - ud->args[i].begin = rspamd_mempool_alloc (task->task_pool, ud->args[i].len); + ud->args[i].begin = rspamd_mempool_alloc (task->task_pool, + ud->args[i].len); memcpy (ud->args[i].begin, tmp, ud->args[i].len); } /* Now check whether we need to perform DNS request */ @@ -307,9 +338,9 @@ lua_redis_make_request (lua_State *L) /* Need to make dns request */ /* Resolve hostname */ if (make_dns_request (task->resolver, task->s, task->task_pool, - lua_redis_dns_callback, ud, - RDNS_REQUEST_A, ud->server)) { - task->dns_requests ++; + lua_redis_dns_callback, ud, + RDNS_REQUEST_A, ud->server)) { + task->dns_requests++; lua_pushboolean (L, TRUE); } else { @@ -318,7 +349,7 @@ lua_redis_make_request (lua_State *L) } } else { - if (! lua_redis_make_request_real (ud)) { + if (!lua_redis_make_request_real (ud)) { lua_pushboolean (L, FALSE); } else { diff --git a/src/lua/lua_regexp.c b/src/lua/lua_regexp.c index ac489e53d..53b5d2e05 100644 --- a/src/lua/lua_regexp.c +++ b/src/lua/lua_regexp.c @@ -31,7 +31,7 @@ LUA_FUNCTION_DEF (regexp, match); LUA_FUNCTION_DEF (regexp, split); LUA_FUNCTION_DEF (regexp, destroy); -static const struct luaL_reg regexplib_m[] = { +static const struct luaL_reg regexplib_m[] = { LUA_INTERFACE_DEF (regexp, get_pattern), LUA_INTERFACE_DEF (regexp, match), LUA_INTERFACE_DEF (regexp, split), @@ -39,7 +39,7 @@ static const struct luaL_reg regexplib_m[] = { {"__tostring", lua_class_tostring}, {NULL, NULL} }; -static const struct luaL_reg regexplib_f[] = { +static const struct luaL_reg regexplib_f[] = { LUA_INTERFACE_DEF (regexp, create), LUA_INTERFACE_DEF (regexp, get_cached), {NULL, NULL} @@ -53,10 +53,10 @@ struct rspamd_lua_regexp { gint re_flags; }; -static struct rspamd_lua_regexp * +static struct rspamd_lua_regexp * lua_check_regexp (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{regexp}"); + void *ud = luaL_checkudata (L, 1, "rspamd{regexp}"); luaL_argcheck (L, ud != NULL, 1, "'regexp' expected"); return ud ? *((struct rspamd_lua_regexp **)ud) : NULL; @@ -65,11 +65,11 @@ lua_check_regexp (lua_State * L) static int lua_regexp_create (lua_State *L) { - gint regexp_flags = 0; - GRegex *re; - struct rspamd_lua_regexp *new, **pnew; - const gchar *string, *flags_str = NULL; - GError *err = NULL; + gint regexp_flags = 0; + GRegex *re; + struct rspamd_lua_regexp *new, **pnew; + const gchar *string, *flags_str = NULL; + GError *err = NULL; string = luaL_checkstring (L, 1); if (lua_gettop (L) == 2) { @@ -104,14 +104,16 @@ lua_regexp_create (lua_State *L) msg_info ("invalid regexp flag: %c", *flags_str); break; } - flags_str ++; + flags_str++; } } re = g_regex_new (string, regexp_flags, 0, &err); if (re == NULL) { lua_pushnil (L); - msg_info ("cannot parse regexp: %s, error: %s", string, err == NULL ? "undefined" : err->message); + msg_info ("cannot parse regexp: %s, error: %s", + string, + err == NULL ? "undefined" : err->message); } else { new = g_slice_alloc (sizeof (struct rspamd_lua_regexp)); @@ -130,8 +132,8 @@ lua_regexp_create (lua_State *L) static int lua_regexp_get_cached (lua_State *L) { - struct rspamd_lua_regexp *new, **pnew; - const gchar *line; + struct rspamd_lua_regexp *new, **pnew; + const gchar *line; line = luaL_checkstring (L, 1); new = re_cache_check (line, regexp_static_pool); @@ -150,7 +152,7 @@ lua_regexp_get_cached (lua_State *L) static int lua_regexp_get_pattern (lua_State *L) { - struct rspamd_lua_regexp *re = lua_check_regexp (L); + struct rspamd_lua_regexp *re = lua_check_regexp (L); if (re) { lua_pushstring (L, re->re_pattern); @@ -162,11 +164,11 @@ lua_regexp_get_pattern (lua_State *L) static int lua_regexp_match (lua_State *L) { - struct rspamd_lua_regexp *re = lua_check_regexp (L); - GMatchInfo *mi; - const gchar *data; - gchar **matches; - gint i; + struct rspamd_lua_regexp *re = lua_check_regexp (L); + GMatchInfo *mi; + const gchar *data; + gchar **matches; + gint i; if (re) { data = luaL_checkstring (L, 2); @@ -181,7 +183,7 @@ lua_regexp_match (lua_State *L) if (g_regex_match_full (re->re, data, -1, 0, 0, &mi, NULL)) { matches = g_match_info_fetch_all (mi); lua_newtable (L); - for (i = 1; matches[i - 1] != NULL; i ++) { + for (i = 1; matches[i - 1] != NULL; i++) { lua_pushstring (L, matches[i - 1]); lua_rawseti (L, -2, i); } @@ -202,10 +204,10 @@ lua_regexp_match (lua_State *L) static int lua_regexp_split (lua_State *L) { - struct rspamd_lua_regexp *re = lua_check_regexp (L); - const gchar *data; - gchar **parts; - gint i; + struct rspamd_lua_regexp *re = lua_check_regexp (L); + const gchar *data; + gchar **parts; + gint i; if (re) { data = luaL_checkstring (L, 2); @@ -219,7 +221,7 @@ lua_regexp_split (lua_State *L) } parts = g_regex_split (re->re, data, 0); lua_newtable (L); - for (i = 1; parts[i - 1] != NULL; i ++) { + for (i = 1; parts[i - 1] != NULL; i++) { lua_pushstring (L, parts[i - 1]); lua_rawseti (L, -2, i); } @@ -242,7 +244,7 @@ lua_regexp_split (lua_State *L) static gint lua_regexp_destroy (lua_State *L) { - struct rspamd_lua_regexp *to_del = lua_check_regexp (L); + struct rspamd_lua_regexp *to_del = lua_check_regexp (L); if (to_del) { re_cache_del (to_del->re_pattern, regexp_static_pool); @@ -266,7 +268,7 @@ luaopen_glib_regexp (lua_State * L) lua_pushstring (L, "rspamd{regexp}"); lua_rawset (L, -3); - luaL_register (L, NULL, regexplib_m); + luaL_register (L, NULL, regexplib_m); luaL_register (L, "regexp", regexplib_f); regexp_static_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); diff --git a/src/lua/lua_rsa.c b/src/lua/lua_rsa.c index 38820e4e2..40eab8358 100644 --- a/src/lua/lua_rsa.c +++ b/src/lua/lua_rsa.c @@ -36,22 +36,22 @@ #include <openssl/rsa.h> #include <openssl/pem.h> -LUA_FUNCTION_DEF (rsa_pubkey, load); -LUA_FUNCTION_DEF (rsa_pubkey, create); -LUA_FUNCTION_DEF (rsa_pubkey, gc); -LUA_FUNCTION_DEF (rsa_privkey, load); -LUA_FUNCTION_DEF (rsa_privkey, create); -LUA_FUNCTION_DEF (rsa_privkey, gc); +LUA_FUNCTION_DEF (rsa_pubkey, load); +LUA_FUNCTION_DEF (rsa_pubkey, create); +LUA_FUNCTION_DEF (rsa_pubkey, gc); +LUA_FUNCTION_DEF (rsa_privkey, load); +LUA_FUNCTION_DEF (rsa_privkey, create); +LUA_FUNCTION_DEF (rsa_privkey, gc); LUA_FUNCTION_DEF (rsa_signature, create); LUA_FUNCTION_DEF (rsa_signature, load); LUA_FUNCTION_DEF (rsa_signature, save); LUA_FUNCTION_DEF (rsa_signature, gc); -LUA_FUNCTION_DEF (rsa, verify_memory); -LUA_FUNCTION_DEF (rsa, verify_file); -LUA_FUNCTION_DEF (rsa, sign_file); -LUA_FUNCTION_DEF (rsa, sign_memory); +LUA_FUNCTION_DEF (rsa, verify_memory); +LUA_FUNCTION_DEF (rsa, verify_file); +LUA_FUNCTION_DEF (rsa, sign_file); +LUA_FUNCTION_DEF (rsa, sign_memory); -static const struct luaL_reg rsalib_f[] = { +static const struct luaL_reg rsalib_f[] = { LUA_INTERFACE_DEF (rsa, verify_memory), LUA_INTERFACE_DEF (rsa, verify_file), LUA_INTERFACE_DEF (rsa, sign_memory), @@ -60,46 +60,46 @@ static const struct luaL_reg rsalib_f[] = { }; static const struct luaL_reg rsapubkeylib_f[] = { - LUA_INTERFACE_DEF (rsa_pubkey, load), - LUA_INTERFACE_DEF (rsa_pubkey, create), - {NULL, NULL} + LUA_INTERFACE_DEF (rsa_pubkey, load), + LUA_INTERFACE_DEF (rsa_pubkey, create), + {NULL, NULL} }; static const struct luaL_reg rsapubkeylib_m[] = { - {"__tostring", lua_class_tostring}, - {"__gc", lua_rsa_pubkey_gc}, - {NULL, NULL} + {"__tostring", lua_class_tostring}, + {"__gc", lua_rsa_pubkey_gc}, + {NULL, NULL} }; static const struct luaL_reg rsaprivkeylib_f[] = { - LUA_INTERFACE_DEF (rsa_privkey, load), - LUA_INTERFACE_DEF (rsa_privkey, create), - {NULL, NULL} + LUA_INTERFACE_DEF (rsa_privkey, load), + LUA_INTERFACE_DEF (rsa_privkey, create), + {NULL, NULL} }; static const struct luaL_reg rsaprivkeylib_m[] = { - {"__tostring", lua_class_tostring}, - {"__gc", lua_rsa_privkey_gc}, - {NULL, NULL} + {"__tostring", lua_class_tostring}, + {"__gc", lua_rsa_privkey_gc}, + {NULL, NULL} }; static const struct luaL_reg rsasignlib_f[] = { - LUA_INTERFACE_DEF (rsa_signature, load), - LUA_INTERFACE_DEF (rsa_signature, create), - {NULL, NULL} + LUA_INTERFACE_DEF (rsa_signature, load), + LUA_INTERFACE_DEF (rsa_signature, create), + {NULL, NULL} }; static const struct luaL_reg rsasignlib_m[] = { - LUA_INTERFACE_DEF (rsa_signature, save), - {"__tostring", lua_class_tostring}, - {"__gc", lua_rsa_signature_gc}, - {NULL, NULL} + LUA_INTERFACE_DEF (rsa_signature, save), + {"__tostring", lua_class_tostring}, + {"__gc", lua_rsa_signature_gc}, + {NULL, NULL} }; static RSA * lua_check_rsa_pubkey (lua_State * L, int pos) { - void *ud = luaL_checkudata (L, pos, "rspamd{rsa_pubkey}"); + void *ud = luaL_checkudata (L, pos, "rspamd{rsa_pubkey}"); luaL_argcheck (L, ud != NULL, 1, "'rsa_pubkey' expected"); return ud ? *((RSA **)ud) : NULL; @@ -108,7 +108,7 @@ lua_check_rsa_pubkey (lua_State * L, int pos) static RSA * lua_check_rsa_privkey (lua_State * L, int pos) { - void *ud = luaL_checkudata (L, pos, "rspamd{rsa_privkey}"); + void *ud = luaL_checkudata (L, pos, "rspamd{rsa_privkey}"); luaL_argcheck (L, ud != NULL, 1, "'rsa_privkey' expected"); return ud ? *((RSA **)ud) : NULL; @@ -117,7 +117,7 @@ lua_check_rsa_privkey (lua_State * L, int pos) static f_str_t * lua_check_rsa_sign (lua_State * L, int pos) { - void *ud = luaL_checkudata (L, pos, "rspamd{rsa_signature}"); + void *ud = luaL_checkudata (L, pos, "rspamd{rsa_signature}"); luaL_argcheck (L, ud != NULL, 1, "'rsa_signature' expected"); return ud ? *((f_str_t **)ud) : NULL; @@ -126,7 +126,7 @@ lua_check_rsa_sign (lua_State * L, int pos) static gint lua_rsa_pubkey_load (lua_State *L) { - RSA *rsa = NULL, **prsa; + RSA *rsa = NULL, **prsa; const gchar *filename; FILE *f; @@ -134,13 +134,15 @@ lua_rsa_pubkey_load (lua_State *L) if (filename != NULL) { f = fopen (filename, "r"); if (f == NULL) { - msg_err ("cannot open pubkey from file: %s, %s", filename, strerror (errno)); + msg_err ("cannot open pubkey from file: %s, %s", + filename, + strerror (errno)); lua_pushnil (L); } else { - if (! PEM_read_RSA_PUBKEY (f, &rsa, NULL, NULL)) { + if (!PEM_read_RSA_PUBKEY (f, &rsa, NULL, NULL)) { msg_err ("cannot open pubkey from file: %s, %s", filename, - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); lua_pushnil (L); } else { @@ -160,7 +162,7 @@ lua_rsa_pubkey_load (lua_State *L) static gint lua_rsa_pubkey_create (lua_State *L) { - RSA *rsa = NULL, **prsa; + RSA *rsa = NULL, **prsa; const gchar *buf; BIO *bp; @@ -168,9 +170,9 @@ lua_rsa_pubkey_create (lua_State *L) if (buf != NULL) { bp = BIO_new_mem_buf ((void *)buf, -1); - if (! PEM_read_bio_RSA_PUBKEY (bp, &rsa, NULL, NULL)) { + if (!PEM_read_bio_RSA_PUBKEY (bp, &rsa, NULL, NULL)) { msg_err ("cannot parse pubkey: %s", - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); lua_pushnil (L); } else { @@ -201,7 +203,7 @@ lua_rsa_pubkey_gc (lua_State *L) static gint lua_rsa_privkey_load (lua_State *L) { - RSA *rsa = NULL, **prsa; + RSA *rsa = NULL, **prsa; const gchar *filename; FILE *f; @@ -209,13 +211,15 @@ lua_rsa_privkey_load (lua_State *L) if (filename != NULL) { f = fopen (filename, "r"); if (f == NULL) { - msg_err ("cannot open private key from file: %s, %s", filename, strerror (errno)); + msg_err ("cannot open private key from file: %s, %s", + filename, + strerror (errno)); lua_pushnil (L); } else { - if (! PEM_read_RSAPrivateKey (f, &rsa, NULL, NULL)) { + if (!PEM_read_RSAPrivateKey (f, &rsa, NULL, NULL)) { msg_err ("cannot open private key from file: %s, %s", filename, - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); lua_pushnil (L); } else { @@ -235,7 +239,7 @@ lua_rsa_privkey_load (lua_State *L) static gint lua_rsa_privkey_create (lua_State *L) { - RSA *rsa = NULL, **prsa; + RSA *rsa = NULL, **prsa; const gchar *buf; BIO *bp; @@ -243,9 +247,9 @@ lua_rsa_privkey_create (lua_State *L) if (buf != NULL) { bp = BIO_new_mem_buf ((void *)buf, -1); - if (! PEM_read_bio_RSAPrivateKey (bp, &rsa, NULL, NULL)) { + if (!PEM_read_bio_RSAPrivateKey (bp, &rsa, NULL, NULL)) { msg_err ("cannot parse private key: %s", - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); lua_pushnil (L); } else { @@ -286,13 +290,16 @@ lua_rsa_signature_load (lua_State *L) if (filename != NULL) { fd = open (filename, O_RDONLY); if (fd == -1) { - msg_err ("cannot open signature file: %s, %s", filename, strerror (errno)); + msg_err ("cannot open signature file: %s, %s", filename, + strerror (errno)); lua_pushnil (L); } else { sig = g_malloc (sizeof (f_str_t)); if (fstat (fd, &st) == -1 || - (data = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + (data = + mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, + 0)) == MAP_FAILED) { msg_err ("cannot mmap file %s: %s", filename, strerror (errno)); lua_pushnil (L); } @@ -339,7 +346,9 @@ lua_rsa_signature_save (lua_State *L) } fd = open (filename, flags, 00644); if (fd == -1) { - msg_err ("cannot create a signature file: %s, %s", filename, strerror (errno)); + msg_err ("cannot create a signature file: %s, %s", + filename, + strerror (errno)); lua_pushboolean (L, FALSE); } else { @@ -347,7 +356,9 @@ lua_rsa_signature_save (lua_State *L) if (errno == EINTR) { continue; } - msg_err ("cannot write to a signature file: %s, %s", filename, strerror (errno)); + msg_err ("cannot write to a signature file: %s, %s", + filename, + strerror (errno)); res = FALSE; break; } @@ -427,7 +438,7 @@ lua_rsa_verify_memory (lua_State *L) signature->begin, signature->len, rsa); if (ret == 0) { msg_info ("cannot check rsa signature for data: %s", - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); lua_pushboolean (L, FALSE); } else { @@ -474,17 +485,21 @@ lua_rsa_verify_file (lua_State *L) } else { if (fstat (fd, &st) == -1 || - (data = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + (data = + mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, + 0)) == MAP_FAILED) { msg_err ("cannot mmap file %s: %s", filename, strerror (errno)); lua_pushnil (L); } else { - data_sig = g_compute_checksum_for_data (G_CHECKSUM_SHA256, data, st.st_size); + data_sig = g_compute_checksum_for_data (G_CHECKSUM_SHA256, + data, + st.st_size); ret = RSA_verify (NID_sha1, data_sig, strlen (data_sig), signature->begin, signature->len, rsa); if (ret == 0) { msg_info ("cannot check rsa signature for file: %s, %s", - filename, ERR_error_string (ERR_get_error (), NULL)); + filename, ERR_error_string (ERR_get_error (), NULL)); lua_pushboolean (L, FALSE); } else { @@ -535,7 +550,7 @@ lua_rsa_sign_memory (lua_State *L) signature->begin, (guint *)&signature->len, rsa); if (ret == 0) { msg_info ("cannot make a signature for data: %s", - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); lua_pushnil (L); g_free (signature->begin); g_free (signature); @@ -585,7 +600,9 @@ lua_rsa_sign_file (lua_State *L) } else { if (fstat (fd, &st) == -1 || - (data = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + (data = + mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, + 0)) == MAP_FAILED) { msg_err ("cannot mmap file %s: %s", filename, strerror (errno)); lua_pushnil (L); } @@ -594,12 +611,14 @@ lua_rsa_sign_file (lua_State *L) signature->len = RSA_size (rsa); signature->size = signature->len; signature->begin = g_malloc (signature->len); - data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, st.st_size); + data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256, + data, + st.st_size); ret = RSA_sign (NID_sha1, data_sig, strlen (data_sig), signature->begin, (guint *)&signature->len, rsa); if (ret == 0) { msg_info ("cannot make a signature for data: %s", - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); lua_pushnil (L); g_free (signature->begin); g_free (signature); @@ -634,7 +653,7 @@ luaopen_rsa (lua_State * L) lua_pushstring (L, "rspamd{rsa_pubkey}"); lua_rawset (L, -3); - luaL_register (L, NULL, rsapubkeylib_m); + luaL_register (L, NULL, rsapubkeylib_m); luaL_register (L, "rsa_pubkey", rsapubkeylib_f); luaL_newmetatable (L, "rspamd{rsa_privkey}"); @@ -646,7 +665,7 @@ luaopen_rsa (lua_State * L) lua_pushstring (L, "rspamd{rsa_privkey}"); lua_rawset (L, -3); - luaL_register (L, NULL, rsaprivkeylib_m); + luaL_register (L, NULL, rsaprivkeylib_m); luaL_register (L, "rsa_privkey", rsaprivkeylib_f); luaL_newmetatable (L, "rspamd{rsa_signature}"); @@ -658,10 +677,10 @@ luaopen_rsa (lua_State * L) lua_pushstring (L, "rspamd{rsa_signature}"); lua_rawset (L, -3); - luaL_register (L, NULL, rsasignlib_m); + luaL_register (L, NULL, rsasignlib_m); luaL_register (L, "rsa_signature", rsasignlib_f); - luaL_register (L, "rsa", rsalib_f); + luaL_register (L, "rsa", rsalib_f); return 1; } @@ -671,7 +690,7 @@ gint luaopen_rsa (lua_State * L) { msg_info ("this rspamd version is not linked against openssl, therefore no " - "RSA support is available"); + "RSA support is available"); return 1; diff --git a/src/lua/lua_session.c b/src/lua/lua_session.c index 193488cef..7cfdcccbe 100644 --- a/src/lua/lua_session.c +++ b/src/lua/lua_session.c @@ -24,7 +24,7 @@ #include "lua_common.h" /* Public prototypes */ -struct rspamd_async_session *lua_check_session (lua_State * L); +struct rspamd_async_session * lua_check_session (lua_State * L); gint luaopen_session (lua_State * L); /* Lua bindings */ @@ -34,7 +34,7 @@ LUA_FUNCTION_DEF (session, check_session_pending); LUA_FUNCTION_DEF (session, create); LUA_FUNCTION_DEF (session, delete); -static const struct luaL_reg sessionlib_m[] = { +static const struct luaL_reg sessionlib_m[] = { LUA_INTERFACE_DEF (session, register_async_event), LUA_INTERFACE_DEF (session, remove_normal_event), LUA_INTERFACE_DEF (session, check_session_pending), @@ -43,12 +43,12 @@ static const struct luaL_reg sessionlib_m[] = { {NULL, NULL} }; -static const struct luaL_reg sessionlib_f[] = { +static const struct luaL_reg sessionlib_f[] = { LUA_INTERFACE_DEF (session, create), {NULL, NULL} }; -static const struct luaL_reg eventlib_m[] = { +static const struct luaL_reg eventlib_m[] = { {"__tostring", lua_class_tostring}, {NULL, NULL} }; @@ -67,18 +67,18 @@ struct lua_event_udata { struct rspamd_async_session *session; }; -struct rspamd_async_session * +struct rspamd_async_session * lua_check_session (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{session}"); + void *ud = luaL_checkudata (L, 1, "rspamd{session}"); luaL_argcheck (L, ud != NULL, 1, "'session' expected"); return ud ? *((struct rspamd_async_session **)ud) : NULL; } -struct rspamd_async_event * +struct rspamd_async_event * lua_check_event (lua_State * L, gint pos) { - void *ud = luaL_checkudata (L, pos, "rspamd{event}"); + void *ud = luaL_checkudata (L, pos, "rspamd{event}"); luaL_argcheck (L, ud != NULL, 1, "'event' expected"); return ud ? *((struct rspamd_async_event **)ud) : NULL; } @@ -88,13 +88,14 @@ lua_check_event (lua_State * L, gint pos) static gboolean lua_session_finalizer (gpointer ud) { - struct lua_session_udata *cbdata = ud; - gboolean res; + struct lua_session_udata *cbdata = ud; + gboolean res; /* Call finalizer function */ lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref_fin); if (lua_pcall (cbdata->L, 0, 1, 0) != 0) { - msg_info ("call to session finalizer failed: %s", lua_tostring (cbdata->L, -1)); + msg_info ("call to session finalizer failed: %s", + lua_tostring (cbdata->L, -1)); } res = lua_toboolean (cbdata->L, -1); lua_pop (cbdata->L, 1); @@ -107,14 +108,15 @@ lua_session_finalizer (gpointer ud) static void lua_session_restore (gpointer ud) { - struct lua_session_udata *cbdata = ud; + struct lua_session_udata *cbdata = ud; if (cbdata->cbref_restore) { /* Call restorer function */ lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref_restore); if (lua_pcall (cbdata->L, 0, 0, 0) != 0) { - msg_info ("call to session restorer failed: %s", lua_tostring (cbdata->L, -1)); + msg_info ("call to session restorer failed: %s", + lua_tostring (cbdata->L, -1)); } luaL_unref (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref_restore); } @@ -123,14 +125,15 @@ lua_session_restore (gpointer ud) static void lua_session_cleanup (gpointer ud) { - struct lua_session_udata *cbdata = ud; + struct lua_session_udata *cbdata = ud; if (cbdata->cbref_cleanup) { /* Call restorer function */ lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref_cleanup); if (lua_pcall (cbdata->L, 0, 0, 0) != 0) { - msg_info ("call to session cleanup failed: %s", lua_tostring (cbdata->L, -1)); + msg_info ("call to session cleanup failed: %s", + lua_tostring (cbdata->L, -1)); } luaL_unref (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref_cleanup); } @@ -141,9 +144,9 @@ lua_session_cleanup (gpointer ud) static int lua_session_create (lua_State *L) { - struct rspamd_async_session *session, **psession; - struct lua_session_udata *cbdata; - rspamd_mempool_t *mempool; + struct rspamd_async_session *session, **psession; + struct lua_session_udata *cbdata; + rspamd_mempool_t *mempool; @@ -186,7 +189,11 @@ lua_session_create (lua_State *L) cbdata->cbref_cleanup = luaL_ref (L, LUA_REGISTRYINDEX); } } - session = new_async_session (mempool, lua_session_finalizer, lua_session_restore, lua_session_cleanup, cbdata); + session = new_async_session (mempool, + lua_session_finalizer, + lua_session_restore, + lua_session_cleanup, + cbdata); cbdata->session = session; psession = lua_newuserdata (L, sizeof (struct rspamd_async_session *)); lua_setclass (L, "rspamd{session}", -1); @@ -198,7 +205,7 @@ lua_session_create (lua_State *L) static int lua_session_delete (lua_State *L) { - struct rspamd_async_session *session = lua_check_session (L); + struct rspamd_async_session *session = lua_check_session (L); if (session) { destroy_session (session); @@ -214,13 +221,14 @@ lua_session_delete (lua_State *L) static void lua_event_fin (gpointer ud) { - struct lua_event_udata *cbdata = ud; + struct lua_event_udata *cbdata = ud; if (cbdata->cbref) { /* Call restorer function */ lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref); if (lua_pcall (cbdata->L, 0, 0, 0) != 0) { - msg_info ("call to event finalizer failed: %s", lua_tostring (cbdata->L, -1)); + msg_info ("call to event finalizer failed: %s", + lua_tostring (cbdata->L, -1)); } luaL_unref (cbdata->L, LUA_REGISTRYINDEX, cbdata->cbref); } @@ -229,18 +237,23 @@ lua_event_fin (gpointer ud) static int lua_session_register_async_event (lua_State *L) { - struct rspamd_async_session *session = lua_check_session (L); - struct lua_event_udata *cbdata; - gpointer *pdata; + struct rspamd_async_session *session = lua_check_session (L); + struct lua_event_udata *cbdata; + gpointer *pdata; if (session) { if (lua_isfunction (L, 1)) { - cbdata = rspamd_mempool_alloc (session->pool, sizeof (struct lua_event_udata)); + cbdata = + rspamd_mempool_alloc (session->pool, + sizeof (struct lua_event_udata)); cbdata->L = L; lua_pushvalue (L, 1); cbdata->cbref = luaL_ref (L, LUA_REGISTRYINDEX); cbdata->session = session; - register_async_event (session, lua_event_fin, cbdata, g_quark_from_static_string ("lua event")); + register_async_event (session, + lua_event_fin, + cbdata, + g_quark_from_static_string ("lua event")); pdata = lua_newuserdata (L, sizeof (gpointer)); lua_setclass (L, "rspamd{event}", -1); *pdata = cbdata; @@ -257,8 +270,8 @@ lua_session_register_async_event (lua_State *L) static int lua_session_remove_normal_event (lua_State *L) { - struct rspamd_async_session *session = lua_check_session (L); - gpointer data; + struct rspamd_async_session *session = lua_check_session (L); + gpointer data; if (session) { data = lua_check_event (L, 2); @@ -277,10 +290,10 @@ lua_session_remove_normal_event (lua_State *L) static int lua_session_check_session_pending (lua_State *L) { - struct rspamd_async_session *session = lua_check_session (L); + struct rspamd_async_session *session = lua_check_session (L); if (session) { - + } else { lua_pushnil (L); @@ -301,7 +314,7 @@ luaopen_session (lua_State * L) lua_pushstring (L, "rspamd{session}"); lua_rawset (L, -3); - luaL_register (L, NULL, sessionlib_m); + luaL_register (L, NULL, sessionlib_m); luaL_register (L, "rspamd_session", sessionlib_f); lua_pop (L, 1); /* remove metatable from stack */ @@ -312,5 +325,5 @@ luaopen_session (lua_State * L) lua_pop (L, 1); /* remove metatable from stack */ - return 1; + return 1; } diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c index 0572226be..1b62ee83f 100644 --- a/src/lua/lua_task.c +++ b/src/lua/lua_task.c @@ -39,8 +39,11 @@ #include "statfile_sync.h" #include "diff.h" -extern stat_file_t* get_statfile_by_symbol (statfile_pool_t *pool, struct rspamd_classifier_config *ccf, - const gchar *symbol, struct rspamd_statfile_config **st, gboolean try_create); +extern stat_file_t * get_statfile_by_symbol (statfile_pool_t *pool, + struct rspamd_classifier_config *ccf, + const gchar *symbol, + struct rspamd_statfile_config **st, + gboolean try_create); /* Task creation */ LUA_FUNCTION_DEF (task, create_empty); @@ -90,13 +93,13 @@ LUA_FUNCTION_DEF (task, get_metric_score); LUA_FUNCTION_DEF (task, get_metric_action); LUA_FUNCTION_DEF (task, learn_statfile); -static const struct luaL_reg tasklib_f[] = { +static const struct luaL_reg tasklib_f[] = { LUA_INTERFACE_DEF (task, create_empty), LUA_INTERFACE_DEF (task, create_from_buffer), {NULL, NULL} }; -static const struct luaL_reg tasklib_m[] = { +static const struct luaL_reg tasklib_m[] = { LUA_INTERFACE_DEF (task, get_message), LUA_INTERFACE_DEF (task, destroy), LUA_INTERFACE_DEF (task, process_message), @@ -153,7 +156,7 @@ LUA_FUNCTION_DEF (textpart, get_fuzzy); LUA_FUNCTION_DEF (textpart, get_language); LUA_FUNCTION_DEF (textpart, compare_distance); -static const struct luaL_reg textpartlib_m[] = { +static const struct luaL_reg textpartlib_m[] = { LUA_INTERFACE_DEF (textpart, get_content), LUA_INTERFACE_DEF (textpart, get_length), LUA_INTERFACE_DEF (textpart, is_empty), @@ -171,7 +174,7 @@ LUA_FUNCTION_DEF (mimepart, get_length); LUA_FUNCTION_DEF (mimepart, get_type); LUA_FUNCTION_DEF (mimepart, get_filename); -static const struct luaL_reg mimepartlib_m[] = { +static const struct luaL_reg mimepartlib_m[] = { LUA_INTERFACE_DEF (mimepart, get_content), LUA_INTERFACE_DEF (mimepart, get_length), LUA_INTERFACE_DEF (mimepart, get_type), @@ -188,7 +191,7 @@ LUA_FUNCTION_DEF (image, get_type); LUA_FUNCTION_DEF (image, get_filename); LUA_FUNCTION_DEF (image, get_size); -static const struct luaL_reg imagelib_m[] = { +static const struct luaL_reg imagelib_m[] = { LUA_INTERFACE_DEF (image, get_width), LUA_INTERFACE_DEF (image, get_height), LUA_INTERFACE_DEF (image, get_type), @@ -207,7 +210,7 @@ LUA_FUNCTION_DEF (url, get_text); LUA_FUNCTION_DEF (url, is_phished); LUA_FUNCTION_DEF (url, get_phished); -static const struct luaL_reg urllib_m[] = { +static const struct luaL_reg urllib_m[] = { LUA_INTERFACE_DEF (url, get_length), LUA_INTERFACE_DEF (url, get_host), LUA_INTERFACE_DEF (url, get_user), @@ -220,42 +223,42 @@ static const struct luaL_reg urllib_m[] = { }; /* Utility functions */ -static struct rspamd_task * +static struct rspamd_task * lua_check_task (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{task}"); + void *ud = luaL_checkudata (L, 1, "rspamd{task}"); luaL_argcheck (L, ud != NULL, 1, "'task' expected"); return ud ? *((struct rspamd_task **)ud) : NULL; } -static struct mime_text_part * +static struct mime_text_part * lua_check_textpart (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{textpart}"); + void *ud = luaL_checkudata (L, 1, "rspamd{textpart}"); luaL_argcheck (L, ud != NULL, 1, "'textpart' expected"); return ud ? *((struct mime_text_part **)ud) : NULL; } -static struct mime_part * +static struct mime_part * lua_check_mimepart (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{mimepart}"); + void *ud = luaL_checkudata (L, 1, "rspamd{mimepart}"); luaL_argcheck (L, ud != NULL, 1, "'mimepart' expected"); return ud ? *((struct mime_part **)ud) : NULL; } -static struct rspamd_image * +static struct rspamd_image * lua_check_image (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{image}"); + void *ud = luaL_checkudata (L, 1, "rspamd{image}"); luaL_argcheck (L, ud != NULL, 1, "'image' expected"); return ud ? *((struct rspamd_image **)ud) : NULL; } -static struct uri * +static struct uri * lua_check_url (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{url}"); + void *ud = luaL_checkudata (L, 1, "rspamd{url}"); luaL_argcheck (L, ud != NULL, 1, "'url' expected"); return ud ? *((struct uri **)ud) : NULL; } @@ -265,7 +268,7 @@ lua_check_url (lua_State * L) static int lua_task_create_empty (lua_State *L) { - struct rspamd_task **ptask, *task; + struct rspamd_task **ptask, *task; task = rspamd_task_new (NULL); ptask = lua_newuserdata (L, sizeof (gpointer)); @@ -277,9 +280,9 @@ lua_task_create_empty (lua_State *L) static int lua_task_create_from_buffer (lua_State *L) { - struct rspamd_task **ptask, *task; - const gchar *data; - size_t len; + struct rspamd_task **ptask, *task; + const gchar *data; + size_t len; data = luaL_checklstring (L, 1, &len); if (data) { @@ -295,7 +298,7 @@ lua_task_create_from_buffer (lua_State *L) static int lua_task_process_message (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); + struct rspamd_task *task = lua_check_task (L); if (task != NULL && task->msg != NULL && task->msg->len > 0) { if (process_message (task) == 0) { @@ -314,8 +317,8 @@ lua_task_process_message (lua_State *L) static int lua_task_set_cfg (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - void *ud = luaL_checkudata (L, 2, "rspamd{config}"); + struct rspamd_task *task = lua_check_task (L); + void *ud = luaL_checkudata (L, 2, "rspamd{config}"); luaL_argcheck (L, ud != NULL, 1, "'config' expected"); task->cfg = ud ? *((struct rspamd_config **)ud) : NULL; @@ -325,7 +328,7 @@ lua_task_set_cfg (lua_State *L) static int lua_task_destroy (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); + struct rspamd_task *task = lua_check_task (L); if (task != NULL) { rspamd_task_free (task, FALSE); @@ -337,8 +340,8 @@ lua_task_destroy (lua_State *L) static int lua_task_get_message (lua_State * L) { - GMimeMessage **pmsg; - struct rspamd_task *task = lua_check_task (L); + GMimeMessage **pmsg; + struct rspamd_task *task = lua_check_task (L); if (task != NULL && task->message != NULL) { pmsg = lua_newuserdata (L, sizeof (GMimeMessage *)); @@ -354,8 +357,8 @@ lua_task_get_message (lua_State * L) static int lua_task_get_mempool (lua_State * L) { - rspamd_mempool_t **ppool; - struct rspamd_task *task = lua_check_task (L); + rspamd_mempool_t **ppool; + struct rspamd_task *task = lua_check_task (L); if (task != NULL) { ppool = lua_newuserdata (L, sizeof (rspamd_mempool_t *)); @@ -371,8 +374,8 @@ lua_task_get_mempool (lua_State * L) static int lua_task_get_session (lua_State * L) { - struct rspamd_async_session **psession; - struct rspamd_task *task = lua_check_task (L); + struct rspamd_async_session **psession; + struct rspamd_task *task = lua_check_task (L); if (task != NULL) { psession = lua_newuserdata (L, sizeof (void *)); @@ -388,8 +391,8 @@ lua_task_get_session (lua_State * L) static int lua_task_get_ev_base (lua_State * L) { - struct event_base **pbase; - struct rspamd_task *task = lua_check_task (L); + struct event_base **pbase; + struct rspamd_task *task = lua_check_task (L); if (task != NULL) { pbase = lua_newuserdata (L, sizeof (struct event_base *)); @@ -405,20 +408,23 @@ lua_task_get_ev_base (lua_State * L) static gint lua_task_insert_result (lua_State * L) { - struct rspamd_task *task = lua_check_task (L); - const gchar *symbol_name, *param; - double flag; - GList *params = NULL; - gint i, top; + struct rspamd_task *task = lua_check_task (L); + const gchar *symbol_name, *param; + double flag; + GList *params = NULL; + gint i, top; if (task != NULL) { - symbol_name = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 2)); + symbol_name = + rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 2)); flag = luaL_checknumber (L, 3); top = lua_gettop (L); /* Get additional options */ for (i = 4; i <= top; i++) { param = luaL_checkstring (L, i); - params = g_list_prepend (params, rspamd_mempool_strdup (task->task_pool, param)); + params = + g_list_prepend (params, + rspamd_mempool_strdup (task->task_pool, param)); } insert_result (task, symbol_name, flag, params); @@ -429,16 +435,17 @@ lua_task_insert_result (lua_State * L) static gint lua_task_set_pre_result (lua_State * L) { - struct rspamd_task *task = lua_check_task (L); - gchar *action_str; - guint action; + struct rspamd_task *task = lua_check_task (L); + gchar *action_str; + guint action; if (task != NULL) { action = luaL_checkinteger (L, 2); if (action < task->pre_result.action) { task->pre_result.action = action; if (lua_gettop (L) >= 3) { - action_str = rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 3)); + action_str = rspamd_mempool_strdup (task->task_pool, + luaL_checkstring (L, 3)); task->pre_result.str = action_str; } else { @@ -450,15 +457,15 @@ lua_task_set_pre_result (lua_State * L) } struct lua_tree_cb_data { - lua_State *L; - int i; + lua_State *L; + int i; }; static gboolean lua_tree_url_callback (gpointer key, gpointer value, gpointer ud) { - struct uri **purl; - struct lua_tree_cb_data *cb = ud; + struct uri **purl; + struct lua_tree_cb_data *cb = ud; purl = lua_newuserdata (cb->L, sizeof (struct uri *)); lua_setclass (cb->L, "rspamd{url}", -1); @@ -471,8 +478,8 @@ lua_tree_url_callback (gpointer key, gpointer value, gpointer ud) static gint lua_task_get_urls (lua_State * L) { - struct rspamd_task *task = lua_check_task (L); - struct lua_tree_cb_data cb; + struct rspamd_task *task = lua_check_task (L); + struct lua_tree_cb_data cb; if (task) { lua_newtable (L); @@ -489,8 +496,8 @@ lua_task_get_urls (lua_State * L) static gint lua_task_get_emails (lua_State * L) { - struct rspamd_task *task = lua_check_task (L); - struct lua_tree_cb_data cb; + struct rspamd_task *task = lua_check_task (L); + struct lua_tree_cb_data cb; if (task) { lua_newtable (L); @@ -507,10 +514,10 @@ lua_task_get_emails (lua_State * L) static gint lua_task_get_text_parts (lua_State * L) { - gint i = 1; - struct rspamd_task *task = lua_check_task (L); - GList *cur; - struct mime_text_part *part, **ppart; + gint i = 1; + struct rspamd_task *task = lua_check_task (L); + GList *cur; + struct mime_text_part *part, **ppart; if (task != NULL) { lua_newtable (L); @@ -533,10 +540,10 @@ lua_task_get_text_parts (lua_State * L) static gint lua_task_get_parts (lua_State * L) { - gint i = 1; - struct rspamd_task *task = lua_check_task (L); - GList *cur; - struct mime_part *part, **ppart; + gint i = 1; + struct rspamd_task *task = lua_check_task (L); + GList *cur; + struct mime_part *part, **ppart; if (task != NULL) { lua_newtable (L); @@ -560,7 +567,7 @@ lua_task_get_parts (lua_State * L) static gint lua_task_get_raw_headers (lua_State * L) { - struct rspamd_task *task = lua_check_task (L); + struct rspamd_task *task = lua_check_task (L); if (task) { lua_pushstring (L, task->raw_headers_str); @@ -575,10 +582,10 @@ lua_task_get_raw_headers (lua_State * L) static gint lua_task_get_raw_header_common (lua_State * L, gboolean strong) { - struct rspamd_task *task = lua_check_task (L); - struct raw_header *rh; - gint i = 1; - const gchar *name; + struct rspamd_task *task = lua_check_task (L); + struct raw_header *rh; + gint i = 1; + const gchar *name; if (task) { name = luaL_checkstring (L, 2); @@ -613,7 +620,7 @@ lua_task_get_raw_header_common (lua_State * L, gboolean strong) } /* Create new associated table for a header */ lua_newtable (L); - lua_set_table_index (L, "name", rh->name); + lua_set_table_index (L, "name", rh->name); lua_set_table_index (L, "value", rh->value); lua_pushstring (L, "tab_separated"); lua_pushboolean (L, rh->tab_separated); @@ -649,17 +656,17 @@ lua_task_get_raw_header_strong (lua_State * L) static gint lua_task_get_received_headers (lua_State * L) { - struct rspamd_task *task = lua_check_task (L); - GList *cur; - struct received_header *rh; - gint i = 1; + struct rspamd_task *task = lua_check_task (L); + GList *cur; + struct received_header *rh; + gint i = 1; if (task) { lua_newtable (L); cur = g_list_first (task->received); while (cur) { rh = cur->data; - if (rh->is_error || G_UNLIKELY( + if (rh->is_error || G_UNLIKELY ( rh->from_ip == NULL && rh->real_ip == NULL && rh->real_hostname == NULL && @@ -691,8 +698,8 @@ lua_task_get_received_headers (lua_State * L) static gint lua_task_get_resolver (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - struct rspamd_dns_resolver **presolver; + struct rspamd_task *task = lua_check_task (L); + struct rspamd_dns_resolver **presolver; if (task != NULL && task->resolver != NULL) { presolver = lua_newuserdata (L, sizeof (void *)); @@ -709,10 +716,10 @@ lua_task_get_resolver (lua_State *L) static gint lua_task_inc_dns_req (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); + struct rspamd_task *task = lua_check_task (L); if (task != NULL) { - task->dns_requests ++; + task->dns_requests++; } return 0; @@ -721,11 +728,11 @@ lua_task_inc_dns_req (lua_State *L) static gint lua_task_call_rspamd_function (lua_State * L) { - struct rspamd_task *task = lua_check_task (L); - struct expression_function f; - gint i, top; - gboolean res; - gchar *arg; + struct rspamd_task *task = lua_check_task (L); + struct expression_function f; + gint i, top; + gboolean res; + gchar *arg; if (task) { f.name = (gchar *)luaL_checkstring (L, 2); @@ -769,12 +776,13 @@ lua_push_internet_address (lua_State *L, InternetAddress *ia) } return FALSE; #else - InternetAddressMailbox *iamb; + InternetAddressMailbox *iamb; if (ia && INTERNET_ADDRESS_IS_MAILBOX (ia)) { lua_newtable (L); iamb = INTERNET_ADDRESS_MAILBOX (ia); lua_set_table_index (L, "name", internet_address_get_name (ia)); - lua_set_table_index (L, "addr", internet_address_mailbox_get_addr (iamb)); + lua_set_table_index (L, "addr", + internet_address_mailbox_get_addr (iamb)); return TRUE; } return FALSE; @@ -787,12 +795,12 @@ lua_push_internet_address (lua_State *L, InternetAddress *ia) static void lua_push_internet_address_list (lua_State *L, InternetAddressList *addrs) { - InternetAddress *ia; - gint idx = 1; + InternetAddress *ia; + gint idx = 1; #ifndef GMIME24 /* Gmime 2.2 version */ - InternetAddressList *cur; + InternetAddressList *cur; lua_newtable (L); cur = addrs; @@ -805,12 +813,12 @@ lua_push_internet_address_list (lua_State *L, InternetAddressList *addrs) } #else /* Gmime 2.4 version */ - gsize len, i; + gsize len, i; lua_newtable (L); if (addrs != NULL) { len = internet_address_list_length (addrs); - for (i = 0; i < len; i ++) { + for (i = 0; i < len; i++) { ia = internet_address_list_get_address (addrs, i); if (lua_push_internet_address (L, ia)) { lua_rawseti (L, -2, idx++); @@ -823,10 +831,10 @@ lua_push_internet_address_list (lua_State *L, InternetAddressList *addrs) static gint lua_task_get_recipients (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - GList *cur; - InternetAddressList *addrs; - gint idx = 1; + struct rspamd_task *task = lua_check_task (L); + GList *cur; + InternetAddressList *addrs; + gint idx = 1; if (task) { cur = task->rcpt; @@ -836,7 +844,8 @@ lua_task_get_recipients (lua_State *L) #ifndef GMIME24 addrs = internet_address_parse_string (cur->data); if (addrs) { - if (lua_push_internet_address (L, internet_address_list_get_address (addrs))) { + if (lua_push_internet_address (L, + internet_address_list_get_address (addrs))) { lua_rawseti (L, -2, idx++); } internet_address_list_destroy (addrs); @@ -845,7 +854,8 @@ lua_task_get_recipients (lua_State *L) addrs = internet_address_list_parse_string (cur->data); if (addrs) { - if (lua_push_internet_address (L, internet_address_list_get_address (addrs, 0))) { + if (lua_push_internet_address (L, + internet_address_list_get_address (addrs, 0))) { lua_rawseti (L, -2, idx++); } g_object_unref (addrs); @@ -864,9 +874,9 @@ lua_task_get_recipients (lua_State *L) static gint lua_task_get_from (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - InternetAddressList *addrs; - + struct rspamd_task *task = lua_check_task (L); + InternetAddressList *addrs; + if (task) { if (task->from != NULL) { #ifndef GMIME24 @@ -876,7 +886,7 @@ lua_task_get_from (lua_State *L) #endif if (addrs != NULL) { lua_push_internet_address_list (L, addrs); -#ifndef GMIME24 +#ifndef GMIME24 internet_address_list_destroy (addrs); #else g_object_unref (addrs); @@ -897,8 +907,8 @@ lua_task_get_from (lua_State *L) static gint lua_task_set_from (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - const gchar *new_from; + struct rspamd_task *task = lua_check_task (L); + const gchar *new_from; if (task) { new_from = luaL_checkstring (L, 2); @@ -913,7 +923,7 @@ lua_task_set_from (lua_State *L) static gint lua_task_get_user (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); + struct rspamd_task *task = lua_check_task (L); if (task && task->user != NULL) { lua_pushstring (L, task->user); @@ -927,8 +937,8 @@ lua_task_get_user (lua_State *L) static gint lua_task_set_user (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - const gchar *new_user; + struct rspamd_task *task = lua_check_task (L); + const gchar *new_user; if (task) { new_user = luaL_checkstring (L, 2); @@ -946,7 +956,7 @@ lua_task_set_user (lua_State *L) static gint lua_task_get_recipients_headers (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); + struct rspamd_task *task = lua_check_task (L); if (task && task->rcpts) { lua_push_internet_address_list (L, task->rcpts); @@ -960,18 +970,22 @@ lua_task_get_recipients_headers (lua_State *L) static gint lua_task_get_from_headers (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - InternetAddressList *addrs; + struct rspamd_task *task = lua_check_task (L); + InternetAddressList *addrs; if (task && task->message != NULL) { #ifndef GMIME24 - addrs = internet_address_parse_string (g_mime_message_get_sender (task->message)); + addrs = + internet_address_parse_string (g_mime_message_get_sender ( + task->message)); #else - addrs = internet_address_list_parse_string (g_mime_message_get_sender (task->message)); + addrs = + internet_address_list_parse_string (g_mime_message_get_sender (task + ->message)); #endif if (addrs) { lua_push_internet_address_list (L, addrs); -#ifndef GMIME24 +#ifndef GMIME24 internet_address_list_destroy (addrs); #else g_object_unref (addrs); @@ -990,8 +1004,8 @@ lua_task_get_from_headers (lua_State *L) static gint lua_task_get_from_ip (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - + struct rspamd_task *task = lua_check_task (L); + if (task) { lua_ip_push (L, &task->from_addr); } @@ -1020,8 +1034,8 @@ lua_task_get_from_ip_num (lua_State *L) static gint lua_task_get_client_ip_num (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - + struct rspamd_task *task = lua_check_task (L); + if (task) { lua_ip_push (L, &task->client_addr); } @@ -1035,8 +1049,8 @@ lua_task_get_client_ip_num (lua_State *L) static gint lua_task_get_helo (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - + struct rspamd_task *task = lua_check_task (L); + if (task) { if (task->helo != NULL) { lua_pushstring (L, (gchar *)task->helo); @@ -1051,8 +1065,8 @@ lua_task_get_helo (lua_State *L) static gint lua_task_set_helo (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - const gchar *new_helo; + struct rspamd_task *task = lua_check_task (L); + const gchar *new_helo; if (task) { new_helo = luaL_checkstring (L, 2); @@ -1067,7 +1081,7 @@ lua_task_set_helo (lua_State *L) static gint lua_task_get_hostname (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); + struct rspamd_task *task = lua_check_task (L); if (task) { if (task->hostname != NULL) { @@ -1097,13 +1111,14 @@ lua_task_get_hostname (lua_State *L) static gint lua_task_set_hostname (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - const gchar *new_hostname; + struct rspamd_task *task = lua_check_task (L); + const gchar *new_hostname; if (task) { new_hostname = luaL_checkstring (L, 2); if (new_hostname) { - task->hostname = rspamd_mempool_strdup (task->task_pool, new_hostname); + task->hostname = rspamd_mempool_strdup (task->task_pool, + new_hostname); } } @@ -1113,10 +1128,10 @@ lua_task_set_hostname (lua_State *L) static gint lua_task_get_images (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - gint i = 1; - GList *cur; - struct rspamd_image **pimg; + struct rspamd_task *task = lua_check_task (L); + gint i = 1; + GList *cur; + struct rspamd_image **pimg; if (task) { cur = task->images; @@ -1138,12 +1153,15 @@ lua_task_get_images (lua_State *L) } static inline gboolean -lua_push_symbol_result (lua_State *L, struct rspamd_task *task, struct metric *metric, const gchar *symbol) +lua_push_symbol_result (lua_State *L, + struct rspamd_task *task, + struct metric *metric, + const gchar *symbol) { - struct metric_result *metric_res; - struct symbol *s; - gint j; - GList *opt; + struct metric_result *metric_res; + struct symbol *s; + gint j; + GList *opt; metric_res = g_hash_table_lookup (task->results, metric->name); if (metric_res) { @@ -1178,12 +1196,12 @@ lua_push_symbol_result (lua_State *L, struct rspamd_task *task, struct metric *m static gint lua_task_get_symbol (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - const gchar *symbol; - struct metric *metric; - GList *cur = NULL, *metric_list; - gboolean found = FALSE; - gint i = 1; + struct rspamd_task *task = lua_check_task (L); + const gchar *symbol; + struct metric *metric; + GList *cur = NULL, *metric_list; + gboolean found = FALSE; + gint i = 1; symbol = luaL_checkstring (L, 2); @@ -1224,8 +1242,8 @@ lua_task_get_symbol (lua_State *L) static gint lua_task_get_date (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - time_t task_time; + struct rspamd_task *task = lua_check_task (L); + time_t task_time; if (task != NULL) { /* Get GMT date and store it to time_t */ @@ -1242,7 +1260,7 @@ lua_task_get_date (lua_State *L) static gint lua_task_get_message_id (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); + struct rspamd_task *task = lua_check_task (L); if (task != NULL && task->message_id != NULL) { lua_pushstring (L, task->message_id); @@ -1257,7 +1275,7 @@ lua_task_get_message_id (lua_State *L) static gint lua_task_get_timeval (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); + struct rspamd_task *task = lua_check_task (L); if (task != NULL) { lua_newtable (L); @@ -1279,13 +1297,13 @@ lua_task_get_timeval (lua_State *L) static gint lua_task_learn_statfile (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - const gchar *symbol; - struct rspamd_classifier_config *cl; - GTree *tokens; - struct rspamd_statfile_config *st; - stat_file_t *statfile; - struct classifier_ctx *ctx; + struct rspamd_task *task = lua_check_task (L); + const gchar *symbol; + struct rspamd_classifier_config *cl; + GTree *tokens; + struct rspamd_statfile_config *st; + stat_file_t *statfile; + struct classifier_ctx *ctx; symbol = luaL_checkstring (L, 2); @@ -1297,13 +1315,17 @@ lua_task_learn_statfile (lua_State *L) return 1; } ctx = cl->classifier->init_func (task->task_pool, cl); - if ((tokens = g_hash_table_lookup (task->tokens, cl->tokenizer)) == NULL) { + if ((tokens = + g_hash_table_lookup (task->tokens, cl->tokenizer)) == NULL) { msg_warn ("no tokens found learn failed!"); lua_pushboolean (L, FALSE); return 1; } - statfile = get_statfile_by_symbol (task->worker->srv->statfile_pool, ctx->cfg, - symbol, &st, TRUE); + statfile = get_statfile_by_symbol (task->worker->srv->statfile_pool, + ctx->cfg, + symbol, + &st, + TRUE); if (statfile == NULL) { msg_warn ("opening statfile failed!"); @@ -1311,7 +1333,14 @@ lua_task_learn_statfile (lua_State *L) return 1; } - cl->classifier->learn_func (ctx, task->worker->srv->statfile_pool, symbol, tokens, TRUE, NULL, 1., NULL); + cl->classifier->learn_func (ctx, + task->worker->srv->statfile_pool, + symbol, + tokens, + TRUE, + NULL, + 1., + NULL); maybe_write_binlog (ctx->cfg, st, statfile, tokens); lua_pushboolean (L, TRUE); } @@ -1322,20 +1351,23 @@ lua_task_learn_statfile (lua_State *L) static gint lua_task_get_metric_score (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - const gchar *metric_name; - struct metric_result *metric_res; + struct rspamd_task *task = lua_check_task (L); + const gchar *metric_name; + struct metric_result *metric_res; metric_name = luaL_checkstring (L, 2); if (task && metric_name) { - if ((metric_res = g_hash_table_lookup (task->results, metric_name)) != NULL) { + if ((metric_res = + g_hash_table_lookup (task->results, metric_name)) != NULL) { lua_newtable (L); lua_pushnumber (L, metric_res->score); lua_rawseti (L, -2, 1); - lua_pushnumber (L, metric_res->metric->actions[METRIC_ACTION_REJECT].score); + lua_pushnumber (L, + metric_res->metric->actions[METRIC_ACTION_REJECT].score); lua_rawseti (L, -2, 2); - lua_pushnumber (L, metric_res->metric->actions[METRIC_ACTION_REJECT].score); + lua_pushnumber (L, + metric_res->metric->actions[METRIC_ACTION_REJECT].score); lua_rawseti (L, -2, 3); } else { @@ -1350,17 +1382,19 @@ lua_task_get_metric_score (lua_State *L) static gint lua_task_get_metric_action (lua_State *L) { - struct rspamd_task *task = lua_check_task (L); - const gchar *metric_name; - struct metric_result *metric_res; - enum rspamd_metric_action action; + struct rspamd_task *task = lua_check_task (L); + const gchar *metric_name; + struct metric_result *metric_res; + enum rspamd_metric_action action; metric_name = luaL_checkstring (L, 2); if (task && metric_name) { - if ((metric_res = g_hash_table_lookup (task->results, metric_name)) != NULL) { + if ((metric_res = + g_hash_table_lookup (task->results, metric_name)) != NULL) { action = check_metric_action (metric_res->score, - metric_res->metric->actions[METRIC_ACTION_REJECT].score, metric_res->metric); + metric_res->metric->actions[METRIC_ACTION_REJECT].score, + metric_res->metric); lua_pushstring (L, str_action_metric (action)); } else { @@ -1377,7 +1411,7 @@ lua_task_get_metric_action (lua_State *L) static gint lua_textpart_get_content (lua_State * L) { - struct mime_text_part *part = lua_check_textpart (L); + struct mime_text_part *part = lua_check_textpart (L); if (part == NULL || part->is_empty) { lua_pushnil (L); @@ -1392,7 +1426,7 @@ lua_textpart_get_content (lua_State * L) static gint lua_textpart_get_length (lua_State * L) { - struct mime_text_part *part = lua_check_textpart (L); + struct mime_text_part *part = lua_check_textpart (L); if (part == NULL) { lua_pushnil (L); @@ -1412,7 +1446,7 @@ lua_textpart_get_length (lua_State * L) static gint lua_textpart_is_empty (lua_State * L) { - struct mime_text_part *part = lua_check_textpart (L); + struct mime_text_part *part = lua_check_textpart (L); if (part == NULL) { lua_pushnil (L); @@ -1427,7 +1461,7 @@ lua_textpart_is_empty (lua_State * L) static gint lua_textpart_is_html (lua_State * L) { - struct mime_text_part *part = lua_check_textpart (L); + struct mime_text_part *part = lua_check_textpart (L); if (part == NULL) { lua_pushnil (L); @@ -1442,106 +1476,108 @@ lua_textpart_is_html (lua_State * L) static gint lua_textpart_get_fuzzy (lua_State * L) { - struct mime_text_part *part = lua_check_textpart (L); + struct mime_text_part *part = lua_check_textpart (L); if (part == NULL || part->is_empty) { lua_pushnil (L); return 1; } - lua_pushlstring (L, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe)); + lua_pushlstring (L, part->fuzzy->hash_pipe, + sizeof (part->fuzzy->hash_pipe)); return 1; } static gint lua_textpart_get_language (lua_State * L) { - struct mime_text_part *part = lua_check_textpart (L); - static const gchar languages[][4] = { - "", /* G_UNICODE_SCRIPT_COMMON */ - "", /* G_UNICODE_SCRIPT_INHERITED */ - "ar", /* G_UNICODE_SCRIPT_ARABIC */ - "hy", /* G_UNICODE_SCRIPT_ARMENIAN */ - "bn", /* G_UNICODE_SCRIPT_BENGALI */ - /* Used primarily in Taiwan, but not part of the standard - * zh-tw orthography */ - "", /* G_UNICODE_SCRIPT_BOPOMOFO */ - "chr", /* G_UNICODE_SCRIPT_CHEROKEE */ - "cop", /* G_UNICODE_SCRIPT_COPTIC */ - "ru", /* G_UNICODE_SCRIPT_CYRILLIC */ - /* Deseret was used to write English */ - "", /* G_UNICODE_SCRIPT_DESERET */ - "hi", /* G_UNICODE_SCRIPT_DEVANAGARI */ - "am", /* G_UNICODE_SCRIPT_ETHIOPIC */ - "ka", /* G_UNICODE_SCRIPT_GEORGIAN */ - "", /* G_UNICODE_SCRIPT_GOTHIC */ - "el", /* G_UNICODE_SCRIPT_GREEK */ - "gu", /* G_UNICODE_SCRIPT_GUJARATI */ - "pa", /* G_UNICODE_SCRIPT_GURMUKHI */ - "", /* G_UNICODE_SCRIPT_HAN */ - "ko", /* G_UNICODE_SCRIPT_HANGUL */ - "he", /* G_UNICODE_SCRIPT_HEBREW */ - "ja", /* G_UNICODE_SCRIPT_HIRAGANA */ - "kn", /* G_UNICODE_SCRIPT_KANNADA */ - "ja", /* G_UNICODE_SCRIPT_KATAKANA */ - "km", /* G_UNICODE_SCRIPT_KHMER */ - "lo", /* G_UNICODE_SCRIPT_LAO */ - "en", /* G_UNICODE_SCRIPT_LATIN */ - "ml", /* G_UNICODE_SCRIPT_MALAYALAM */ - "mn", /* G_UNICODE_SCRIPT_MONGOLIAN */ - "my", /* G_UNICODE_SCRIPT_MYANMAR */ - /* Ogham was used to write old Irish */ - "", /* G_UNICODE_SCRIPT_OGHAM */ - "", /* G_UNICODE_SCRIPT_OLD_ITALIC */ - "or", /* G_UNICODE_SCRIPT_ORIYA */ - "", /* G_UNICODE_SCRIPT_RUNIC */ - "si", /* G_UNICODE_SCRIPT_SINHALA */ - "syr", /* G_UNICODE_SCRIPT_SYRIAC */ - "ta", /* G_UNICODE_SCRIPT_TAMIL */ - "te", /* G_UNICODE_SCRIPT_TELUGU */ - "dv", /* G_UNICODE_SCRIPT_THAANA */ - "th", /* G_UNICODE_SCRIPT_THAI */ - "bo", /* G_UNICODE_SCRIPT_TIBETAN */ - "iu", /* G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL */ - "", /* G_UNICODE_SCRIPT_YI */ - "tl", /* G_UNICODE_SCRIPT_TAGALOG */ - /* Phillipino languages/scripts */ - "hnn", /* G_UNICODE_SCRIPT_HANUNOO */ - "bku", /* G_UNICODE_SCRIPT_BUHID */ - "tbw", /* G_UNICODE_SCRIPT_TAGBANWA */ - - "", /* G_UNICODE_SCRIPT_BRAILLE */ - "", /* G_UNICODE_SCRIPT_CYPRIOT */ - "", /* G_UNICODE_SCRIPT_LIMBU */ - /* Used for Somali (so) in the past */ - "", /* G_UNICODE_SCRIPT_OSMANYA */ - /* The Shavian alphabet was designed for English */ - "", /* G_UNICODE_SCRIPT_SHAVIAN */ - "", /* G_UNICODE_SCRIPT_LINEAR_B */ - "", /* G_UNICODE_SCRIPT_TAI_LE */ - "uga", /* G_UNICODE_SCRIPT_UGARITIC */ - - "", /* G_UNICODE_SCRIPT_NEW_TAI_LUE */ - "bug", /* G_UNICODE_SCRIPT_BUGINESE */ - /* The original script for Old Church Slavonic (chu), later - * written with Cyrillic */ - "", /* G_UNICODE_SCRIPT_GLAGOLITIC */ - /* Used for for Berber (ber), but Arabic script is more common */ - "", /* G_UNICODE_SCRIPT_TIFINAGH */ - "syl", /* G_UNICODE_SCRIPT_SYLOTI_NAGRI */ - "peo", /* G_UNICODE_SCRIPT_OLD_PERSIAN */ - "", /* G_UNICODE_SCRIPT_KHAROSHTHI */ - - "", /* G_UNICODE_SCRIPT_UNKNOWN */ - "", /* G_UNICODE_SCRIPT_BALINESE */ - "", /* G_UNICODE_SCRIPT_CUNEIFORM */ - "", /* G_UNICODE_SCRIPT_PHOENICIAN */ - "", /* G_UNICODE_SCRIPT_PHAGS_PA */ - "nqo" /* G_UNICODE_SCRIPT_NKO */ + struct mime_text_part *part = lua_check_textpart (L); + static const gchar languages[][4] = { + "", /* G_UNICODE_SCRIPT_COMMON */ + "", /* G_UNICODE_SCRIPT_INHERITED */ + "ar", /* G_UNICODE_SCRIPT_ARABIC */ + "hy", /* G_UNICODE_SCRIPT_ARMENIAN */ + "bn", /* G_UNICODE_SCRIPT_BENGALI */ + /* Used primarily in Taiwan, but not part of the standard + * zh-tw orthography */ + "", /* G_UNICODE_SCRIPT_BOPOMOFO */ + "chr", /* G_UNICODE_SCRIPT_CHEROKEE */ + "cop", /* G_UNICODE_SCRIPT_COPTIC */ + "ru", /* G_UNICODE_SCRIPT_CYRILLIC */ + /* Deseret was used to write English */ + "", /* G_UNICODE_SCRIPT_DESERET */ + "hi", /* G_UNICODE_SCRIPT_DEVANAGARI */ + "am", /* G_UNICODE_SCRIPT_ETHIOPIC */ + "ka", /* G_UNICODE_SCRIPT_GEORGIAN */ + "", /* G_UNICODE_SCRIPT_GOTHIC */ + "el", /* G_UNICODE_SCRIPT_GREEK */ + "gu", /* G_UNICODE_SCRIPT_GUJARATI */ + "pa", /* G_UNICODE_SCRIPT_GURMUKHI */ + "", /* G_UNICODE_SCRIPT_HAN */ + "ko", /* G_UNICODE_SCRIPT_HANGUL */ + "he", /* G_UNICODE_SCRIPT_HEBREW */ + "ja", /* G_UNICODE_SCRIPT_HIRAGANA */ + "kn", /* G_UNICODE_SCRIPT_KANNADA */ + "ja", /* G_UNICODE_SCRIPT_KATAKANA */ + "km", /* G_UNICODE_SCRIPT_KHMER */ + "lo", /* G_UNICODE_SCRIPT_LAO */ + "en", /* G_UNICODE_SCRIPT_LATIN */ + "ml", /* G_UNICODE_SCRIPT_MALAYALAM */ + "mn", /* G_UNICODE_SCRIPT_MONGOLIAN */ + "my", /* G_UNICODE_SCRIPT_MYANMAR */ + /* Ogham was used to write old Irish */ + "", /* G_UNICODE_SCRIPT_OGHAM */ + "", /* G_UNICODE_SCRIPT_OLD_ITALIC */ + "or", /* G_UNICODE_SCRIPT_ORIYA */ + "", /* G_UNICODE_SCRIPT_RUNIC */ + "si", /* G_UNICODE_SCRIPT_SINHALA */ + "syr", /* G_UNICODE_SCRIPT_SYRIAC */ + "ta", /* G_UNICODE_SCRIPT_TAMIL */ + "te", /* G_UNICODE_SCRIPT_TELUGU */ + "dv", /* G_UNICODE_SCRIPT_THAANA */ + "th", /* G_UNICODE_SCRIPT_THAI */ + "bo", /* G_UNICODE_SCRIPT_TIBETAN */ + "iu", /* G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL */ + "", /* G_UNICODE_SCRIPT_YI */ + "tl", /* G_UNICODE_SCRIPT_TAGALOG */ + /* Phillipino languages/scripts */ + "hnn", /* G_UNICODE_SCRIPT_HANUNOO */ + "bku", /* G_UNICODE_SCRIPT_BUHID */ + "tbw", /* G_UNICODE_SCRIPT_TAGBANWA */ + + "", /* G_UNICODE_SCRIPT_BRAILLE */ + "", /* G_UNICODE_SCRIPT_CYPRIOT */ + "", /* G_UNICODE_SCRIPT_LIMBU */ + /* Used for Somali (so) in the past */ + "", /* G_UNICODE_SCRIPT_OSMANYA */ + /* The Shavian alphabet was designed for English */ + "", /* G_UNICODE_SCRIPT_SHAVIAN */ + "", /* G_UNICODE_SCRIPT_LINEAR_B */ + "", /* G_UNICODE_SCRIPT_TAI_LE */ + "uga", /* G_UNICODE_SCRIPT_UGARITIC */ + + "", /* G_UNICODE_SCRIPT_NEW_TAI_LUE */ + "bug", /* G_UNICODE_SCRIPT_BUGINESE */ + /* The original script for Old Church Slavonic (chu), later + * written with Cyrillic */ + "", /* G_UNICODE_SCRIPT_GLAGOLITIC */ + /* Used for for Berber (ber), but Arabic script is more common */ + "", /* G_UNICODE_SCRIPT_TIFINAGH */ + "syl", /* G_UNICODE_SCRIPT_SYLOTI_NAGRI */ + "peo", /* G_UNICODE_SCRIPT_OLD_PERSIAN */ + "", /* G_UNICODE_SCRIPT_KHAROSHTHI */ + + "", /* G_UNICODE_SCRIPT_UNKNOWN */ + "", /* G_UNICODE_SCRIPT_BALINESE */ + "", /* G_UNICODE_SCRIPT_CUNEIFORM */ + "", /* G_UNICODE_SCRIPT_PHOENICIAN */ + "", /* G_UNICODE_SCRIPT_PHAGS_PA */ + "nqo" /* G_UNICODE_SCRIPT_NKO */ }; - const gchar *sel; + const gchar *sel; - if (part != NULL && part->script > 0 && part->script < (gint)G_N_ELEMENTS (languages)) { + if (part != NULL && part->script > 0 && part->script < + (gint)G_N_ELEMENTS (languages)) { sel = languages[part->script]; if (*sel != '\0') { lua_pushstring (L, sel); @@ -1556,11 +1592,11 @@ lua_textpart_get_language (lua_State * L) static gint lua_textpart_compare_distance (lua_State * L) { - struct mime_text_part *part = lua_check_textpart (L), *other; - void *ud = luaL_checkudata (L, 2, "rspamd{textpart}"); - gint diff = -1; - GMimeObject *parent; - const GMimeContentType *ct; + struct mime_text_part *part = lua_check_textpart (L), *other; + void *ud = luaL_checkudata (L, 2, "rspamd{textpart}"); + gint diff = -1; + GMimeObject *parent; + const GMimeContentType *ct; luaL_argcheck (L, ud != NULL, 2, "'textpart' expected"); other = ud ? *((struct mime_text_part **)ud) : NULL; @@ -1569,9 +1605,12 @@ lua_textpart_compare_distance (lua_State * L) parent = part->parent; ct = g_mime_object_get_content_type (parent); #ifndef GMIME24 - if (ct == NULL || ! g_mime_content_type_is_type (ct, "multipart", "alternative")) { + if (ct == NULL || + !g_mime_content_type_is_type (ct, "multipart", "alternative")) { #else - if (ct == NULL || ! g_mime_content_type_is_type ((GMimeContentType *)ct, "multipart", "alternative")) { + if (ct == NULL || + !g_mime_content_type_is_type ((GMimeContentType *)ct, "multipart", + "alternative")) { #endif diff = -1; @@ -1579,20 +1618,22 @@ lua_textpart_compare_distance (lua_State * L) else { if (!part->is_empty && !other->is_empty) { if (part->diff_str != NULL && other->diff_str != NULL) { - diff = compare_diff_distance (part->diff_str, other->diff_str); + diff = compare_diff_distance (part->diff_str, + other->diff_str); } else { diff = fuzzy_compare_parts (part, other); } } - else if ((part->is_empty && !other->is_empty) || (!part->is_empty && other->is_empty)) { + else if ((part->is_empty && + !other->is_empty) || (!part->is_empty && other->is_empty)) { /* Empty and non empty parts are different */ diff = 0; } } } else { - diff = -1; + diff = -1; } @@ -1606,7 +1647,7 @@ lua_textpart_compare_distance (lua_State * L) static gint lua_mimepart_get_content (lua_State * L) { - struct mime_part *part = lua_check_mimepart (L); + struct mime_part *part = lua_check_mimepart (L); if (part == NULL) { lua_pushnil (L); @@ -1621,7 +1662,7 @@ lua_mimepart_get_content (lua_State * L) static gint lua_mimepart_get_length (lua_State * L) { - struct mime_part *part = lua_check_mimepart (L); + struct mime_part *part = lua_check_mimepart (L); if (part == NULL) { lua_pushnil (L); @@ -1636,7 +1677,7 @@ lua_mimepart_get_length (lua_State * L) static gint lua_mimepart_get_type (lua_State * L) { - struct mime_part *part = lua_check_mimepart (L); + struct mime_part *part = lua_check_mimepart (L); if (part == NULL) { lua_pushnil (L); @@ -1657,7 +1698,7 @@ lua_mimepart_get_type (lua_State * L) static gint lua_mimepart_get_filename (lua_State * L) { - struct mime_part *part = lua_check_mimepart (L); + struct mime_part *part = lua_check_mimepart (L); if (part == NULL || part->filename == NULL) { lua_pushnil (L); @@ -1673,7 +1714,7 @@ lua_mimepart_get_filename (lua_State * L) static gint lua_image_get_width (lua_State *L) { - struct rspamd_image *img = lua_check_image (L); + struct rspamd_image *img = lua_check_image (L); if (img != NULL) { lua_pushnumber (L, img->width); @@ -1687,7 +1728,7 @@ lua_image_get_width (lua_State *L) static gint lua_image_get_height (lua_State *L) { - struct rspamd_image *img = lua_check_image (L); + struct rspamd_image *img = lua_check_image (L); if (img != NULL) { lua_pushnumber (L, img->height); @@ -1702,7 +1743,7 @@ lua_image_get_height (lua_State *L) static gint lua_image_get_type (lua_State *L) { - struct rspamd_image *img = lua_check_image (L); + struct rspamd_image *img = lua_check_image (L); if (img != NULL) { lua_pushstring (L, image_type_str (img->type)); @@ -1717,7 +1758,7 @@ lua_image_get_type (lua_State *L) static gint lua_image_get_size (lua_State *L) { - struct rspamd_image *img = lua_check_image (L); + struct rspamd_image *img = lua_check_image (L); if (img != NULL) { lua_pushinteger (L, img->data->len); @@ -1732,7 +1773,7 @@ lua_image_get_size (lua_State *L) static gint lua_image_get_filename (lua_State *L) { - struct rspamd_image *img = lua_check_image (L); + struct rspamd_image *img = lua_check_image (L); if (img != NULL && img->filename != NULL) { lua_pushstring (L, img->filename); @@ -1748,7 +1789,7 @@ lua_image_get_filename (lua_State *L) static gint lua_url_get_length (lua_State *L) { - struct uri *url = lua_check_url (L); + struct uri *url = lua_check_url (L); if (url != NULL) { lua_pushinteger (L, strlen (struri (url))); @@ -1762,7 +1803,7 @@ lua_url_get_length (lua_State *L) static gint lua_url_get_host (lua_State *L) { - struct uri *url = lua_check_url (L); + struct uri *url = lua_check_url (L); if (url != NULL) { lua_pushlstring (L, url->host, url->hostlen); @@ -1776,7 +1817,7 @@ lua_url_get_host (lua_State *L) static gint lua_url_get_user (lua_State *L) { - struct uri *url = lua_check_url (L); + struct uri *url = lua_check_url (L); if (url != NULL) { lua_pushlstring (L, url->user, url->userlen); @@ -1791,7 +1832,7 @@ lua_url_get_user (lua_State *L) static gint lua_url_get_path (lua_State *L) { - struct uri *url = lua_check_url (L); + struct uri *url = lua_check_url (L); if (url != NULL) { lua_pushlstring (L, url->data, url->datalen); @@ -1806,7 +1847,7 @@ lua_url_get_path (lua_State *L) static gint lua_url_get_text (lua_State *L) { - struct uri *url = lua_check_url (L); + struct uri *url = lua_check_url (L); if (url != NULL) { lua_pushstring (L, struri (url)); @@ -1821,7 +1862,7 @@ lua_url_get_text (lua_State *L) static gint lua_url_is_phished (lua_State *L) { - struct uri *url = lua_check_url (L); + struct uri *url = lua_check_url (L); if (url != NULL) { lua_pushboolean (L, url->is_phished); @@ -1836,7 +1877,7 @@ lua_url_is_phished (lua_State *L) static gint lua_url_get_phished (lua_State *L) { - struct uri **purl, *url = lua_check_url (L); + struct uri **purl, *url = lua_check_url (L); if (url) { if (url->is_phished && url->phished_url != NULL) { diff --git a/src/lua/lua_upstream.c b/src/lua/lua_upstream.c index ee06fe2c1..8e7980037 100644 --- a/src/lua/lua_upstream.c +++ b/src/lua/lua_upstream.c @@ -41,7 +41,7 @@ LUA_FUNCTION_DEF (upstream_list, get_upstream_by_hash); LUA_FUNCTION_DEF (upstream_list, get_upstream_round_robin); LUA_FUNCTION_DEF (upstream_list, get_upstream_master_slave); -static const struct luaL_reg upstream_list_m[] = { +static const struct luaL_reg upstream_list_m[] = { LUA_INTERFACE_DEF (upstream_list, get_upstream_by_hash), LUA_INTERFACE_DEF (upstream_list, get_upstream_round_robin), @@ -50,7 +50,7 @@ static const struct luaL_reg upstream_list_m[] = { {"__gc", lua_upstream_list_destroy}, {NULL, NULL} }; -static const struct luaL_reg upstream_list_f[] = { +static const struct luaL_reg upstream_list_f[] = { LUA_INTERFACE_DEF (upstream_list, create), {NULL, NULL} }; @@ -65,7 +65,7 @@ LUA_FUNCTION_DEF (upstream, get_port); LUA_FUNCTION_DEF (upstream, get_ip_string); LUA_FUNCTION_DEF (upstream, get_priority); -static const struct luaL_reg upstream_m[] = { +static const struct luaL_reg upstream_m[] = { LUA_INTERFACE_DEF (upstream, ok), LUA_INTERFACE_DEF (upstream, fail), LUA_INTERFACE_DEF (upstream, get_ip), @@ -76,7 +76,7 @@ static const struct luaL_reg upstream_m[] = { {"__tostring", lua_class_tostring}, {NULL, NULL} }; -static const struct luaL_reg upstream_f[] = { +static const struct luaL_reg upstream_f[] = { LUA_INTERFACE_DEF (upstream, create), {NULL, NULL} }; @@ -89,10 +89,10 @@ struct lua_upstream { gchar *addr; }; -static struct lua_upstream * +static struct lua_upstream * lua_check_upstream (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{upstream}"); + void *ud = luaL_checkudata (L, 1, "rspamd{upstream}"); luaL_argcheck (L, ud != NULL, 1, "'upstream' expected"); return ud ? *((struct lua_upstream **)ud) : NULL; @@ -106,15 +106,16 @@ lua_check_upstream (lua_State * L) static gint lua_upstream_create (lua_State *L) { - struct lua_upstream *new, **pnew; - const gchar *def; + struct lua_upstream *new, **pnew; + const gchar *def; def = luaL_checkstring (L, 1); if (def) { new = g_slice_alloc0 (sizeof (struct lua_upstream)); new->def = g_strdup (def); new->addr = g_malloc (INET6_ADDRSTRLEN); - if (!rspamd_parse_host_port_priority (NULL, new->def, &new->addr, &new->port, &new->up.priority)) { + if (!rspamd_parse_host_port_priority (NULL, new->def, &new->addr, + &new->port, &new->up.priority)) { g_free (new->def); g_slice_free1 (sizeof (struct lua_upstream), new); lua_pushnil (L); @@ -137,7 +138,7 @@ lua_upstream_create (lua_State *L) static gint lua_upstream_destroy (lua_State *L) { - struct lua_upstream *up = lua_check_upstream (L); + struct lua_upstream *up = lua_check_upstream (L); if (up) { g_free (up->def); @@ -156,7 +157,7 @@ lua_upstream_destroy (lua_State *L) static gint lua_upstream_get_ip (lua_State *L) { - struct lua_upstream *up = lua_check_upstream (L); + struct lua_upstream *up = lua_check_upstream (L); if (up) { lua_pushstring (L, up->addr); @@ -176,7 +177,7 @@ lua_upstream_get_ip (lua_State *L) static gint lua_upstream_get_ip_string (lua_State *L) { - struct lua_upstream *up = lua_check_upstream (L); + struct lua_upstream *up = lua_check_upstream (L); if (up) { lua_pushstring (L, up->addr); @@ -196,7 +197,7 @@ lua_upstream_get_ip_string (lua_State *L) static gint lua_upstream_get_port (lua_State *L) { - struct lua_upstream *up = lua_check_upstream (L); + struct lua_upstream *up = lua_check_upstream (L); if (up) { lua_pushinteger (L, up->port); @@ -216,7 +217,7 @@ lua_upstream_get_port (lua_State *L) static gint lua_upstream_get_priority (lua_State *L) { - struct lua_upstream *up = lua_check_upstream (L); + struct lua_upstream *up = lua_check_upstream (L); if (up) { lua_pushinteger (L, up->up.priority); @@ -236,8 +237,8 @@ lua_upstream_get_priority (lua_State *L) static gint lua_upstream_fail (lua_State *L) { - struct lua_upstream *up = lua_check_upstream (L); - time_t now; + struct lua_upstream *up = lua_check_upstream (L); + time_t now; if (up) { if (lua_gettop (L) >= 2) { @@ -260,8 +261,8 @@ lua_upstream_fail (lua_State *L) static gint lua_upstream_ok (lua_State *L) { - struct lua_upstream *up = lua_check_upstream (L); - time_t now; + struct lua_upstream *up = lua_check_upstream (L); + time_t now; if (up) { if (lua_gettop (L) >= 2) { @@ -282,10 +283,10 @@ struct lua_upstream_list { guint count; }; -static struct lua_upstream_list * +static struct lua_upstream_list * lua_check_upstream_list (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{upstream_list}"); + void *ud = luaL_checkudata (L, 1, "rspamd{upstream_list}"); luaL_argcheck (L, ud != NULL, 1, "'upstream_list' expected"); return ud ? *((struct lua_upstream_list **)ud) : NULL; @@ -299,11 +300,11 @@ lua_check_upstream_list (lua_State * L) static gint lua_upstream_list_create (lua_State *L) { - struct lua_upstream_list *new, **pnew; - struct lua_upstream *cur; - const gchar *def; - char **tokens; - guint i, default_port = 0; + struct lua_upstream_list *new, **pnew; + struct lua_upstream *cur; + const gchar *def; + char **tokens; + guint i, default_port = 0; def = luaL_checkstring (L, 1); if (def) { @@ -317,12 +318,14 @@ lua_upstream_list_create (lua_State *L) goto err; } new->count = g_strv_length (tokens); - new->upstreams = g_slice_alloc0 (new->count * sizeof (struct lua_upstream)); + new->upstreams = + g_slice_alloc0 (new->count * sizeof (struct lua_upstream)); - for (i = 0; i < new->count; i ++) { + for (i = 0; i < new->count; i++) { cur = &new->upstreams[i]; cur->addr = g_malloc (INET6_ADDRSTRLEN); - if (!rspamd_parse_host_port_priority (NULL, tokens[i], &cur->addr, &cur->port, &cur->up.priority)) { + if (!rspamd_parse_host_port_priority (NULL, tokens[i], &cur->addr, + &cur->port, &cur->up.priority)) { goto err; } if (cur->port == 0) { @@ -340,13 +343,14 @@ err: g_strfreev (tokens); } if (new->upstreams) { - for (i = 0; i < new->count; i ++) { + for (i = 0; i < new->count; i++) { cur = &new->upstreams[i]; if (cur->addr) { g_free (cur->addr); } } - g_slice_free1 (new->count * sizeof (struct lua_upstream), new->upstreams); + g_slice_free1 (new->count * sizeof (struct lua_upstream), + new->upstreams); } g_slice_free1 (sizeof (struct lua_upstream_list), new); lua_pushnil (L); @@ -361,19 +365,20 @@ err: static gint lua_upstream_list_destroy (lua_State *L) { - struct lua_upstream_list *upl = lua_check_upstream_list (L); - struct lua_upstream *cur; - guint i; + struct lua_upstream_list *upl = lua_check_upstream_list (L); + struct lua_upstream *cur; + guint i; if (upl) { if (upl->upstreams) { - for (i = 0; i < upl->count; i ++) { + for (i = 0; i < upl->count; i++) { cur = &upl->upstreams[i]; if (cur->addr) { g_free (cur->addr); } } - g_slice_free1 (upl->count * sizeof (struct lua_upstream), upl->upstreams); + g_slice_free1 (upl->count * sizeof (struct lua_upstream), + upl->upstreams); } g_slice_free1 (sizeof (struct lua_upstream_list), upl); } @@ -389,10 +394,10 @@ lua_upstream_list_destroy (lua_State *L) static gint lua_upstream_list_get_upstream_by_hash (lua_State *L) { - struct lua_upstream_list *upl; - struct lua_upstream *selected, **pselected; - time_t now; - const gchar *key; + struct lua_upstream_list *upl; + struct lua_upstream *selected, **pselected; + time_t now; + const gchar *key; upl = lua_check_upstream_list (L); if (upl) { @@ -404,10 +409,16 @@ lua_upstream_list_get_upstream_by_hash (lua_State *L) else { now = time (NULL); } - selected = (struct lua_upstream *)get_upstream_by_hash (upl->upstreams, upl->count, - sizeof (struct lua_upstream), now, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, - key, 0); + selected = (struct lua_upstream *)get_upstream_by_hash ( + upl->upstreams, + upl->count, + sizeof (struct lua_upstream), + now, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS, + key, + 0); if (selected) { pselected = lua_newuserdata (L, sizeof (struct lua_upstream *)); lua_setclass (L, "rspamd{upstream}", -1); @@ -436,9 +447,9 @@ lua_upstream_list_get_upstream_by_hash (lua_State *L) static gint lua_upstream_list_get_upstream_round_robin (lua_State *L) { - struct lua_upstream_list *upl; - struct lua_upstream *selected, **pselected; - time_t now; + struct lua_upstream_list *upl; + struct lua_upstream *selected, **pselected; + time_t now; upl = lua_check_upstream_list (L); if (upl) { @@ -448,9 +459,14 @@ lua_upstream_list_get_upstream_round_robin (lua_State *L) else { now = time (NULL); } - selected = (struct lua_upstream *)get_upstream_round_robin (upl->upstreams, upl->count, - sizeof (struct lua_upstream), now, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS); + selected = (struct lua_upstream *)get_upstream_round_robin ( + upl->upstreams, + upl->count, + sizeof (struct lua_upstream), + now, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS); if (selected) { pselected = lua_newuserdata (L, sizeof (struct lua_upstream *)); lua_setclass (L, "rspamd{upstream}", -1); @@ -475,9 +491,9 @@ lua_upstream_list_get_upstream_round_robin (lua_State *L) static gint lua_upstream_list_get_upstream_master_slave (lua_State *L) { - struct lua_upstream_list *upl; - struct lua_upstream *selected, **pselected; - time_t now; + struct lua_upstream_list *upl; + struct lua_upstream *selected, **pselected; + time_t now; upl = lua_check_upstream_list (L); if (upl) { @@ -487,9 +503,14 @@ lua_upstream_list_get_upstream_master_slave (lua_State *L) else { now = time (NULL); } - selected = (struct lua_upstream *)get_upstream_master_slave (upl->upstreams, upl->count, - sizeof (struct lua_upstream), now, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS); + selected = (struct lua_upstream *)get_upstream_master_slave ( + upl->upstreams, + upl->count, + sizeof (struct lua_upstream), + now, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS); if (selected) { pselected = lua_newuserdata (L, sizeof (struct lua_upstream *)); lua_setclass (L, "rspamd{upstream}", -1); @@ -519,7 +540,7 @@ luaopen_upstream (lua_State * L) lua_pushstring (L, "rspamd{upstream_list}"); lua_rawset (L, -3); - luaL_register (L, NULL, upstream_list_m); + luaL_register (L, NULL, upstream_list_m); luaL_register (L, "upstream_list", upstream_list_f); lua_pop (L, 1); /* remove metatable from stack */ @@ -533,7 +554,7 @@ luaopen_upstream (lua_State * L) lua_pushstring (L, "rspamd{upstream}"); lua_rawset (L, -3); - luaL_register (L, NULL, upstream_m); + luaL_register (L, NULL, upstream_m); luaL_register (L, "upstream", upstream_f); lua_pop (L, 1); /* remove metatable from stack */ diff --git a/src/lua/lua_xmlrpc.c b/src/lua/lua_xmlrpc.c index 4608d2328..762711c30 100644 --- a/src/lua/lua_xmlrpc.c +++ b/src/lua/lua_xmlrpc.c @@ -27,7 +27,7 @@ LUA_FUNCTION_DEF (xmlrpc, parse_reply); LUA_FUNCTION_DEF (xmlrpc, make_request); -static const struct luaL_reg xmlrpclib_m[] = { +static const struct luaL_reg xmlrpclib_m[] = { LUA_INTERFACE_DEF (xmlrpc, parse_reply), LUA_INTERFACE_DEF (xmlrpc, make_request), {"__tostring", lua_class_tostring}, @@ -42,13 +42,24 @@ struct lua_xmlrpc_ud { lua_State *L; }; -static void xmlrpc_start_element (GMarkupParseContext *context, const gchar *name, const gchar **attribute_names, - const gchar **attribute_values, gpointer user_data, GError **error); -static void xmlrpc_end_element (GMarkupParseContext *context, const gchar *element_name, gpointer user_data, - GError **error); -static void xmlrpc_error (GMarkupParseContext *context, GError *error, gpointer user_data); -static void xmlrpc_text (GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, - GError **error); +static void xmlrpc_start_element (GMarkupParseContext *context, + const gchar *name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error); +static void xmlrpc_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error); +static void xmlrpc_error (GMarkupParseContext *context, + GError *error, + gpointer user_data); +static void xmlrpc_text (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error); static GMarkupParser xmlrpc_parser = { .start_element = xmlrpc_start_element, @@ -65,11 +76,15 @@ xmlrpc_error_quark (void) } static void -xmlrpc_start_element (GMarkupParseContext *context, const gchar *name, const gchar **attribute_names, - const gchar **attribute_values, gpointer user_data, GError **error) +xmlrpc_start_element (GMarkupParseContext *context, + const gchar *name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) { - struct lua_xmlrpc_ud *ud = user_data; - int last_state; + struct lua_xmlrpc_ud *ud = user_data; + int last_state; last_state = ud->parser_state; @@ -123,7 +138,7 @@ xmlrpc_start_element (GMarkupParseContext *context, const gchar *name, const gch ud->parser_state = 5; /* Create new param of table type */ lua_newtable (ud->L); - ud->depth ++; + ud->depth++; } else if (g_ascii_strcasecmp (name, "string") == 0) { ud->parser_state = 11; @@ -193,7 +208,7 @@ xmlrpc_start_element (GMarkupParseContext *context, const gchar *name, const gch ud->parser_state = 5; /* Create new param of table type */ lua_newtable (ud->L); - ud->depth ++; + ud->depth++; } else { /* Error state */ @@ -203,16 +218,20 @@ xmlrpc_start_element (GMarkupParseContext *context, const gchar *name, const gch } if (ud->parser_state == 99) { - g_set_error (error, xmlrpc_error_quark(), 1, "xmlrpc parse error on state: %d, while parsing start tag: %s", - last_state, name); + g_set_error (error, + xmlrpc_error_quark (), 1, "xmlrpc parse error on state: %d, while parsing start tag: %s", + last_state, name); } } static void -xmlrpc_end_element (GMarkupParseContext *context, const gchar *name, gpointer user_data, GError **error) +xmlrpc_end_element (GMarkupParseContext *context, + const gchar *name, + gpointer user_data, + GError **error) { - struct lua_xmlrpc_ud *ud = user_data; - int last_state; + struct lua_xmlrpc_ud *ud = user_data; + int last_state; last_state = ud->parser_state; @@ -272,7 +291,7 @@ xmlrpc_end_element (GMarkupParseContext *context, const gchar *name, gpointer us /* Got tag struct */ if (g_ascii_strcasecmp (name, "struct") == 0) { ud->parser_state = 4; - ud->depth --; + ud->depth--; } else { /* Error state */ @@ -340,25 +359,30 @@ xmlrpc_end_element (GMarkupParseContext *context, const gchar *name, gpointer us } if (ud->parser_state == 99) { - g_set_error (error, xmlrpc_error_quark(), 1, "xmlrpc parse error on state: %d, while parsing end tag: %s", - last_state, name); + g_set_error (error, + xmlrpc_error_quark (), 1, "xmlrpc parse error on state: %d, while parsing end tag: %s", + last_state, name); } } static void -xmlrpc_text (GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error) +xmlrpc_text (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) { - struct lua_xmlrpc_ud *ud = user_data; - gint num; - gdouble dnum; + struct lua_xmlrpc_ud *ud = user_data; + gint num; + gdouble dnum; /* Strip line */ while (text_len > 0 && g_ascii_isspace (*text)) { - text ++; - text_len --; + text++; + text_len--; } while (text_len > 0 && g_ascii_isspace (text[text_len - 1])) { - text_len --; + text_len--; } if (text_len > 0) { @@ -390,7 +414,7 @@ xmlrpc_text (GMarkupParseContext *context, const gchar *text, gsize text_len, gp static void xmlrpc_error (GMarkupParseContext *context, GError *error, gpointer user_data) { - struct lua_xmlrpc_ud *ud = user_data; + struct lua_xmlrpc_ud *ud = user_data; msg_err ("xmlrpc parser error: %s", error->message, ud->parser_state); } @@ -398,12 +422,12 @@ xmlrpc_error (GMarkupParseContext *context, GError *error, gpointer user_data) static gint lua_xmlrpc_parse_reply (lua_State *L) { - const gchar *data; - GMarkupParseContext *ctx; - GError *err = NULL; - struct lua_xmlrpc_ud ud; - gsize s; - gboolean res; + const gchar *data; + GMarkupParseContext *ctx; + GError *err = NULL; + struct lua_xmlrpc_ud ud; + gsize s; + gboolean res; data = luaL_checklstring (L, 1, &s); @@ -418,7 +442,7 @@ lua_xmlrpc_parse_reply (lua_State *L) res = g_markup_parse_context_parse (ctx, data, s, &err); g_markup_parse_context_free (ctx); - if (! res) { + if (!res) { lua_pushnil (L); } } @@ -431,10 +455,14 @@ lua_xmlrpc_parse_reply (lua_State *L) } static gint -lua_xmlrpc_parse_table (lua_State *L, gint pos, gchar *databuf, gint pr, gsize size) +lua_xmlrpc_parse_table (lua_State *L, + gint pos, + gchar *databuf, + gint pr, + gsize size) { - gint r = pr, num; - double dnum; + gint r = pr, num; + double dnum; r += rspamd_snprintf (databuf + r, size - r, "<struct>"); lua_pushnil (L); /* first key */ @@ -442,10 +470,12 @@ lua_xmlrpc_parse_table (lua_State *L, gint pos, gchar *databuf, gint pr, gsize s /* uses 'key' (at index -2) and 'value' (at index -1) */ if (lua_type (L, -2) != LUA_TSTRING) { /* Ignore non sting keys */ - lua_pop(L, 1); + lua_pop (L, 1); continue; } - r += rspamd_snprintf (databuf + r, size - r, "<member><name>%s</name><value>", + r += rspamd_snprintf (databuf + r, + size - r, + "<member><name>%s</name><value>", lua_tostring (L, -2)); switch (lua_type (L, -1)) { case LUA_TNUMBER: @@ -454,16 +484,22 @@ lua_xmlrpc_parse_table (lua_State *L, gint pos, gchar *databuf, gint pr, gsize s /* Try to avoid conversion errors */ if (dnum != (double)num) { - r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "<double>%f</double>", + r += rspamd_snprintf (databuf + r, + sizeof (databuf) - r, + "<double>%f</double>", dnum); } else { - r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "<int>%d</int>", + r += rspamd_snprintf (databuf + r, + sizeof (databuf) - r, + "<int>%d</int>", num); } break; case LUA_TBOOLEAN: - r += rspamd_snprintf (databuf + r, size - r, "<boolean>%d</boolean>", + r += rspamd_snprintf (databuf + r, + size - r, + "<boolean>%d</boolean>", lua_toboolean (L, -1) ? 1 : 0); break; case LUA_TSTRING: @@ -477,7 +513,7 @@ lua_xmlrpc_parse_table (lua_State *L, gint pos, gchar *databuf, gint pr, gsize s } r += rspamd_snprintf (databuf + r, size - r, "</value></member>"); /* removes 'value'; keeps 'key' for next iteration */ - lua_pop(L, 1); + lua_pop (L, 1); } r += rspamd_snprintf (databuf + r, size - r, "</struct>"); @@ -491,10 +527,10 @@ lua_xmlrpc_parse_table (lua_State *L, gint pos, gchar *databuf, gint pr, gsize s static gint lua_xmlrpc_make_request (lua_State *L) { - gchar databuf[BUFSIZ * 2]; - const gchar *func; - gint r, top, i, num; - double dnum; + gchar databuf[BUFSIZ * 2]; + const gchar *func; + gint r, top, i, num; + double dnum; func = luaL_checkstring (L, 1); @@ -507,7 +543,9 @@ lua_xmlrpc_make_request (lua_State *L) top = lua_gettop (L); /* Get additional options */ for (i = 2; i <= top; i++) { - r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "<param><value>"); + r += rspamd_snprintf (databuf + r, + sizeof (databuf) - r, + "<param><value>"); switch (lua_type (L, i)) { case LUA_TNUMBER: num = lua_tointeger (L, i); @@ -515,30 +553,43 @@ lua_xmlrpc_make_request (lua_State *L) /* Try to avoid conversion errors */ if (dnum != (double)num) { - r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "<double>%f</double>", - dnum); + r += rspamd_snprintf (databuf + r, + sizeof (databuf) - r, + "<double>%f</double>", + dnum); } else { - r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "<int>%d</int>", - num); + r += rspamd_snprintf (databuf + r, + sizeof (databuf) - r, + "<int>%d</int>", + num); } break; case LUA_TBOOLEAN: - r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "<boolean>%d</boolean>", + r += rspamd_snprintf (databuf + r, + sizeof (databuf) - r, + "<boolean>%d</boolean>", lua_toboolean (L, i) ? 1 : 0); break; case LUA_TSTRING: - r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "<string>%s</string>", + r += rspamd_snprintf (databuf + r, + sizeof (databuf) - r, + "<string>%s</string>", lua_tostring (L, i)); break; case LUA_TTABLE: - r += lua_xmlrpc_parse_table (L, i, databuf, r, sizeof (databuf)); + r += + lua_xmlrpc_parse_table (L, i, databuf, r, sizeof (databuf)); break; } - r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "</value></param>"); + r += rspamd_snprintf (databuf + r, + sizeof (databuf) - r, + "</value></param>"); } - r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "</params></methodCall>"); + r += rspamd_snprintf (databuf + r, + sizeof (databuf) - r, + "</params></methodCall>"); lua_pushlstring (L, databuf, r); } else { diff --git a/src/lua_worker.c b/src/lua_worker.c index 8aeeb94d1..0473404d6 100644 --- a/src/lua_worker.c +++ b/src/lua_worker.c @@ -46,14 +46,14 @@ gpointer init_lua_worker (struct rspamd_config *cfg); void start_lua_worker (struct rspamd_worker *worker); worker_t lua_worker = { - "lua", /* Name */ - init_lua_worker, /* Init function */ - start_lua_worker, /* Start function */ - TRUE, /* Has socket */ - FALSE, /* Non unique */ - FALSE, /* Non threaded */ - TRUE, /* Killable */ - SOCK_STREAM /* TCP socket */ + "lua", /* Name */ + init_lua_worker, /* Init function */ + start_lua_worker, /* Start function */ + TRUE, /* Has socket */ + FALSE, /* Non unique */ + FALSE, /* Non threaded */ + TRUE, /* Killable */ + SOCK_STREAM /* TCP socket */ }; /* @@ -61,23 +61,23 @@ worker_t lua_worker = { */ struct rspamd_lua_worker_ctx { /* DNS resolver */ - struct rspamd_dns_resolver *resolver; + struct rspamd_dns_resolver *resolver; /* Events base */ - struct event_base *ev_base; + struct event_base *ev_base; /* Other params */ - GHashTable *params; + GHashTable *params; /* Lua script to load */ - gchar *file; + gchar *file; /* Lua state */ - lua_State *L; + lua_State *L; /* Callback for accept */ - gint cbref_accept; + gint cbref_accept; /* Callback for finishing */ - gint cbref_fin; + gint cbref_fin; /* Config file */ - struct rspamd_config *cfg; + struct rspamd_config *cfg; /* The rest options */ - ucl_object_t *opts; + ucl_object_t *opts; }; /* Lua bindings */ @@ -88,7 +88,7 @@ LUA_FUNCTION_DEF (worker, get_option); LUA_FUNCTION_DEF (worker, get_resolver); LUA_FUNCTION_DEF (worker, get_cfg); -static const struct luaL_reg lua_workerlib_m[] = { +static const struct luaL_reg lua_workerlib_m[] = { LUA_INTERFACE_DEF (worker, get_ev_base), LUA_INTERFACE_DEF (worker, register_accept_callback), LUA_INTERFACE_DEF (worker, register_exit_callback), @@ -111,10 +111,10 @@ luaopen_lua_worker (lua_State * L) return 1; } -struct rspamd_lua_worker_ctx * +struct rspamd_lua_worker_ctx * lua_check_lua_worker (lua_State * L) { - void *ud = luaL_checkudata (L, 1, "rspamd{worker}"); + void *ud = luaL_checkudata (L, 1, "rspamd{worker}"); luaL_argcheck (L, ud != NULL, 1, "'worker' expected"); return ud ? *((struct rspamd_lua_worker_ctx **)ud) : NULL; } @@ -122,8 +122,8 @@ lua_check_lua_worker (lua_State * L) static int lua_worker_get_ev_base (lua_State *L) { - struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); - struct event_base **pbase; + struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); + struct event_base **pbase; if (ctx) { pbase = lua_newuserdata (L, sizeof (struct event_base *)); @@ -140,7 +140,7 @@ lua_worker_get_ev_base (lua_State *L) static int lua_worker_register_accept_callback (lua_State *L) { - struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); + struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); if (ctx) { if (!lua_isfunction (L, 2)) { @@ -163,7 +163,7 @@ lua_worker_register_accept_callback (lua_State *L) static int lua_worker_register_exit_callback (lua_State *L) { - struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); + struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); if (ctx) { if (!lua_isfunction (L, 2)) { @@ -187,9 +187,9 @@ lua_worker_register_exit_callback (lua_State *L) static int lua_worker_get_option (lua_State *L) { - struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); - const ucl_object_t *val; - const gchar *name; + struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); + const ucl_object_t *val; + const gchar *name; if (ctx) { name = luaL_checkstring (L, 2); @@ -217,8 +217,8 @@ lua_worker_get_option (lua_State *L) static int lua_worker_get_resolver (lua_State *L) { - struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); - struct rspamd_dns_resolver **presolver; + struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); + struct rspamd_dns_resolver **presolver; if (ctx) { presolver = lua_newuserdata (L, sizeof (gpointer)); @@ -235,8 +235,8 @@ lua_worker_get_resolver (lua_State *L) static int lua_worker_get_cfg (lua_State *L) { - struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); - struct rspamd_config **pcfg; + struct rspamd_lua_worker_ctx *ctx = lua_check_lua_worker (L); + struct rspamd_config **pcfg; if (ctx) { pcfg = lua_newuserdata (L, sizeof (gpointer)); @@ -258,17 +258,17 @@ lua_worker_get_cfg (lua_State *L) static void lua_accept_socket (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *) arg; - struct rspamd_lua_worker_ctx *ctx, **pctx; - gint nfd; - lua_State *L; - rspamd_inet_addr_t addr; + struct rspamd_worker *worker = (struct rspamd_worker *) arg; + struct rspamd_lua_worker_ctx *ctx, **pctx; + gint nfd; + lua_State *L; + rspamd_inet_addr_t addr; ctx = worker->ctx; L = ctx->L; if ((nfd = - rspamd_accept_from_socket (fd, &addr)) == -1) { + rspamd_accept_from_socket (fd, &addr)) == -1) { msg_warn ("accept failed: %s", strerror (errno)); return; } @@ -278,8 +278,8 @@ lua_accept_socket (gint fd, short what, void *arg) } msg_info ("accepted connection from %s port %d", - rspamd_inet_address_to_string (&addr), - rspamd_inet_address_get_port (&addr)); + rspamd_inet_address_to_string (&addr), + rspamd_inet_address_get_port (&addr)); /* Call finalizer function */ lua_rawgeti (L, LUA_REGISTRYINDEX, ctx->cbref_accept); @@ -299,7 +299,7 @@ lua_accept_socket (gint fd, short what, void *arg) static gboolean rspamd_lua_worker_parser (ucl_object_t *obj, gpointer ud) { - struct rspamd_lua_worker_ctx *ctx = ud; + struct rspamd_lua_worker_ctx *ctx = ud; ctx->opts = obj; @@ -309,20 +309,24 @@ rspamd_lua_worker_parser (ucl_object_t *obj, gpointer ud) gpointer init_lua_worker (struct rspamd_config *cfg) { - struct rspamd_lua_worker_ctx *ctx; - GQuark type; + struct rspamd_lua_worker_ctx *ctx; + GQuark type; type = g_quark_try_string ("lua"); ctx = g_malloc0 (sizeof (struct rspamd_lua_worker_ctx)); - ctx->params = g_hash_table_new_full (rspamd_str_hash, rspamd_str_equal, g_free, (GDestroyNotify)g_list_free); + ctx->params = g_hash_table_new_full (rspamd_str_hash, + rspamd_str_equal, + g_free, + (GDestroyNotify)g_list_free); rspamd_rcl_register_worker_option (cfg, type, "file", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct rspamd_lua_worker_ctx, file), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct rspamd_lua_worker_ctx, file), 0); - rspamd_rcl_register_worker_parser (cfg, type, rspamd_lua_worker_parser, ctx); + rspamd_rcl_register_worker_parser (cfg, type, rspamd_lua_worker_parser, + ctx); return ctx; } @@ -333,21 +337,25 @@ init_lua_worker (struct rspamd_config *cfg) void start_lua_worker (struct rspamd_worker *worker) { - struct rspamd_lua_worker_ctx *ctx = worker->ctx, **pctx; - lua_State *L; + struct rspamd_lua_worker_ctx *ctx = worker->ctx, **pctx; + lua_State *L; #ifdef WITH_PROFILER - extern void _start (void), etext (void); + extern void _start (void), etext (void); monstartup ((u_long) & _start, (u_long) & etext); #endif - ctx->ev_base = rspamd_prepare_worker (worker, "lua_worker", lua_accept_socket); + ctx->ev_base = rspamd_prepare_worker (worker, + "lua_worker", + lua_accept_socket); L = worker->srv->cfg->lua_state; ctx->L = L; ctx->cfg = worker->srv->cfg; - ctx->resolver = dns_resolver_init (worker->srv->logger, ctx->ev_base, worker->srv->cfg); + ctx->resolver = dns_resolver_init (worker->srv->logger, + ctx->ev_base, + worker->srv->cfg); /* Open worker's lib */ luaopen_lua_worker (L); @@ -357,7 +365,8 @@ start_lua_worker (struct rspamd_worker *worker) exit (EXIT_SUCCESS); } if (access (ctx->file, R_OK) == -1) { - msg_err ("Error reading lua script %s: %s", ctx->file, strerror (errno)); + msg_err ("Error reading lua script %s: %s", ctx->file, + strerror (errno)); exit (EXIT_SUCCESS); } @@ -367,7 +376,8 @@ start_lua_worker (struct rspamd_worker *worker) *pctx = ctx; if (luaL_dofile (L, ctx->file) != 0) { - msg_err ("Error executing lua script %s: %s", ctx->file, lua_tostring (L, -1)); + msg_err ("Error executing lua script %s: %s", ctx->file, + lua_tostring (L, -1)); exit (EXIT_SUCCESS); } @@ -388,7 +398,8 @@ start_lua_worker (struct rspamd_worker *worker) lua_setclass (L, "rspamd{worker}", -1); *pctx = ctx; if (lua_pcall (L, 1, 0, 0) != 0) { - msg_info ("call to worker finalizer failed: %s", lua_tostring (L, -1)); + msg_info ("call to worker finalizer failed: %s", lua_tostring (L, + -1)); } /* Free resources */ luaL_unref (L, LUA_REGISTRYINDEX, ctx->cbref_fin); diff --git a/src/main.c b/src/main.c index 83c072ccf..6e9f75e7a 100644 --- a/src/main.c +++ b/src/main.c @@ -52,59 +52,73 @@ /* 10 seconds after getting termination signal to terminate all workers with SIGKILL */ #define HARD_TERMINATION_TIME 10 -static struct rspamd_worker *fork_worker (struct rspamd_main *, struct rspamd_worker_conf *); -static gboolean load_rspamd_config (struct rspamd_config *cfg, gboolean init_modules); -static void init_cfg_cache (struct rspamd_config *cfg); - -sig_atomic_t do_restart = 0; -sig_atomic_t do_reopen_log = 0; -sig_atomic_t do_terminate = 0; -sig_atomic_t child_dead = 0; -sig_atomic_t got_alarm = 0; +static struct rspamd_worker * fork_worker (struct rspamd_main *, + struct rspamd_worker_conf *); +static gboolean load_rspamd_config (struct rspamd_config *cfg, + gboolean init_modules); +static void init_cfg_cache (struct rspamd_config *cfg); + +sig_atomic_t do_restart = 0; +sig_atomic_t do_reopen_log = 0; +sig_atomic_t do_terminate = 0; +sig_atomic_t child_dead = 0; +sig_atomic_t got_alarm = 0; #ifdef HAVE_SA_SIGINFO -GQueue *signals_info = NULL; +GQueue *signals_info = NULL; #endif -static gboolean config_test = FALSE; -static gboolean no_fork = FALSE; -static gchar **cfg_names = NULL; -static gchar **lua_tests = NULL; -static gchar **sign_configs = NULL; -static gchar *privkey = NULL; -static gchar *rspamd_user = NULL; -static gchar *rspamd_group = NULL; -static gchar *rspamd_pidfile = NULL; -static gboolean dump_cache = FALSE; -static gboolean is_debug = FALSE; -static gboolean is_insecure = FALSE; +static gboolean config_test = FALSE; +static gboolean no_fork = FALSE; +static gchar **cfg_names = NULL; +static gchar **lua_tests = NULL; +static gchar **sign_configs = NULL; +static gchar *privkey = NULL; +static gchar *rspamd_user = NULL; +static gchar *rspamd_group = NULL; +static gchar *rspamd_pidfile = NULL; +static gboolean dump_cache = FALSE; +static gboolean is_debug = FALSE; +static gboolean is_insecure = FALSE; /* List of workers that are pending to start */ -static GList *workers_pending = NULL; +static GList *workers_pending = NULL; /* List of unrelated forked processes */ -static GArray *other_workers = NULL; +static GArray *other_workers = NULL; /* List of active listen sockets indexed by worker type */ -static GHashTable *listen_sockets = NULL; +static GHashTable *listen_sockets = NULL; -struct rspamd_main *rspamd_main; +struct rspamd_main *rspamd_main; /* Commandline options */ -static GOptionEntry entries[] = +static GOptionEntry entries[] = { - { "config-test", 't', 0, G_OPTION_ARG_NONE, &config_test, "Do config test and exit", NULL }, - { "no-fork", 'f', 0, G_OPTION_ARG_NONE, &no_fork, "Do not daemonize main process", NULL }, - { "config", 'c', 0, G_OPTION_ARG_FILENAME_ARRAY, &cfg_names, "Specify config file(s)", NULL }, - { "user", 'u', 0, G_OPTION_ARG_STRING, &rspamd_user, "User to run rspamd as", NULL }, - { "group", 'g', 0, G_OPTION_ARG_STRING, &rspamd_group, "Group to run rspamd as", NULL }, - { "pid", 'p', 0, G_OPTION_ARG_STRING, &rspamd_pidfile, "Path to pidfile", NULL }, - { "dump-cache", 'C', 0, G_OPTION_ARG_NONE, &dump_cache, "Dump symbols cache stats and exit", NULL }, - { "debug", 'd', 0, G_OPTION_ARG_NONE, &is_debug, "Force debug output", NULL }, - { "insecure", 'i', 0, G_OPTION_ARG_NONE, &is_insecure, "Ignore running workers as privileged users (insecure)", NULL }, - { "test-lua", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &lua_tests, "Specify lua file(s) to test", NULL }, - { "sign-config", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &sign_configs, "Specify config file(s) to sign", NULL }, - { "private-key", 0, 0, G_OPTION_ARG_FILENAME, &privkey, "Specify private key to sign", NULL }, - { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } + { "config-test", 't', 0, G_OPTION_ARG_NONE, &config_test, + "Do config test and exit", NULL }, + { "no-fork", 'f', 0, G_OPTION_ARG_NONE, &no_fork, + "Do not daemonize main process", NULL }, + { "config", 'c', 0, G_OPTION_ARG_FILENAME_ARRAY, &cfg_names, + "Specify config file(s)", NULL }, + { "user", 'u', 0, G_OPTION_ARG_STRING, &rspamd_user, + "User to run rspamd as", NULL }, + { "group", 'g', 0, G_OPTION_ARG_STRING, &rspamd_group, + "Group to run rspamd as", NULL }, + { "pid", 'p', 0, G_OPTION_ARG_STRING, &rspamd_pidfile, "Path to pidfile", + NULL }, + { "dump-cache", 'C', 0, G_OPTION_ARG_NONE, &dump_cache, + "Dump symbols cache stats and exit", NULL }, + { "debug", 'd', 0, G_OPTION_ARG_NONE, &is_debug, "Force debug output", + NULL }, + { "insecure", 'i', 0, G_OPTION_ARG_NONE, &is_insecure, + "Ignore running workers as privileged users (insecure)", NULL }, + { "test-lua", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &lua_tests, + "Specify lua file(s) to test", NULL }, + { "sign-config", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &sign_configs, + "Specify config file(s) to sign", NULL }, + { "private-key", 0, 0, G_OPTION_ARG_FILENAME, &privkey, + "Specify private key to sign", NULL }, + { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } }; @@ -152,17 +166,17 @@ static const gchar * chldsigcode (gint code) { switch (code) { #ifdef CLD_EXITED - case CLD_EXITED: - return "Child exited normally"; - case CLD_KILLED: - return "Child has terminated abnormally but did not create a core file"; - case CLD_DUMPED: - return "Child has terminated abnormally and created a core file"; - case CLD_TRAPPED: - return "Traced child has trapped"; + case CLD_EXITED: + return "Child exited normally"; + case CLD_KILLED: + return "Child has terminated abnormally but did not create a core file"; + case CLD_DUMPED: + return "Child has terminated abnormally and created a core file"; + case CLD_TRAPPED: + return "Traced child has trapped"; #endif - default: - return "Unknown reason"; + default: + return "Unknown reason"; } } @@ -175,11 +189,11 @@ print_signals_info (void) while ((inf = g_queue_pop_head (signals_info))) { if (inf->si_signo == SIGCHLD) { msg_info ("got SIGCHLD from child: %P; reason: '%s'", - inf->si_pid, chldsigcode (inf->si_code)); + inf->si_pid, chldsigcode (inf->si_code)); } else { msg_info ("got signal: '%s'; received from pid: %P; uid: %ul", - g_strsignal (inf->si_signo), inf->si_pid, (gulong)inf->si_uid); + g_strsignal (inf->si_signo), inf->si_pid, (gulong)inf->si_uid); } g_free (inf); } @@ -190,13 +204,14 @@ print_signals_info (void) static void read_cmd_line (gint argc, gchar **argv, struct rspamd_config *cfg) { - GError *error = NULL; - GOptionContext *context; - guint i, cfg_num; - pid_t r; + GError *error = NULL; + GOptionContext *context; + guint i, cfg_num; + pid_t r; context = g_option_context_new ("- run rspamd daemon"); - g_option_context_set_summary (context, "Summary:\n Rspamd daemon version " RVERSION "\n Release id: " RID); + g_option_context_set_summary (context, + "Summary:\n Rspamd daemon version " RVERSION "\n Release id: " RID); g_option_context_add_main_entries (context, entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { fprintf (stderr, "option parsing failed: %s\n", error->message); @@ -213,7 +228,7 @@ read_cmd_line (gint argc, gchar **argv, struct rspamd_config *cfg) else { cfg->cfg_name = cfg_names[0]; } - for (i = 1; i < cfg_num; i ++) { + for (i = 1; i < cfg_num; i++) { r = fork (); if (r == 0) { /* Spawning new main process */ @@ -221,7 +236,10 @@ read_cmd_line (gint argc, gchar **argv, struct rspamd_config *cfg) (void)setsid (); } else if (r == -1) { - fprintf (stderr, "fork failed while spawning process for %s configuration file: %s\n", cfg_names[i], strerror (errno)); + fprintf (stderr, + "fork failed while spawning process for %s configuration file: %s\n", + cfg_names[i], + strerror (errno)); } else { /* Save pid to the list of other main processes, we need it to ignore SIGCHLD from them */ @@ -235,15 +253,16 @@ read_cmd_line (gint argc, gchar **argv, struct rspamd_config *cfg) static void detect_priv (struct rspamd_main *rspamd) { - struct passwd *pwd; - struct group *grp; - uid_t euid; + struct passwd *pwd; + struct group *grp; + uid_t euid; euid = geteuid (); if (euid == 0) { if (!rspamd->cfg->rspamd_user && !is_insecure) { - msg_err ("cannot run rspamd workers as root user, please add -u and -g options to select a proper unprivilleged user or specify --insecure flag"); + msg_err ( + "cannot run rspamd workers as root user, please add -u and -g options to select a proper unprivilleged user or specify --insecure flag"); exit (EXIT_FAILURE); } else if (is_insecure) { @@ -255,13 +274,15 @@ detect_priv (struct rspamd_main *rspamd) rspamd->is_privilleged = TRUE; pwd = getpwnam (rspamd->cfg->rspamd_user); if (pwd == NULL) { - msg_err ("user specified does not exists (%s), aborting", strerror (errno)); + msg_err ("user specified does not exists (%s), aborting", + strerror (errno)); exit (-errno); } if (rspamd->cfg->rspamd_group) { grp = getgrnam (rspamd->cfg->rspamd_group); if (grp == NULL) { - msg_err ("group specified does not exists (%s), aborting", strerror (errno)); + msg_err ("group specified does not exists (%s), aborting", + strerror (errno)); exit (-errno); } rspamd->workers_gid = grp->gr_gid; @@ -284,16 +305,20 @@ drop_priv (struct rspamd_main *rspamd) { if (rspamd->is_privilleged) { if (setgid (rspamd->workers_gid) == -1) { - msg_err ("cannot setgid to %d (%s), aborting", (gint)rspamd->workers_gid, strerror (errno)); + msg_err ("cannot setgid to %d (%s), aborting", + (gint)rspamd->workers_gid, + strerror (errno)); exit (-errno); } if (rspamd->cfg->rspamd_user && - initgroups (rspamd->cfg->rspamd_user, rspamd->workers_gid) == -1) { + initgroups (rspamd->cfg->rspamd_user, rspamd->workers_gid) == -1) { msg_err ("initgroups failed (%s), aborting", strerror (errno)); exit (-errno); } if (setuid (rspamd->workers_uid) == -1) { - msg_err ("cannot setuid to %d (%s), aborting", (gint)rspamd->workers_uid, strerror (errno)); + msg_err ("cannot setuid to %d (%s), aborting", + (gint)rspamd->workers_uid, + strerror (errno)); exit (-errno); } } @@ -319,9 +344,9 @@ config_logger (struct rspamd_config *cfg, gpointer ud) static void parse_filters_str (struct rspamd_config *cfg, const gchar *str) { - gchar **strvec, **p; - struct filter *cur; - module_t **pmodule; + gchar **strvec, **p; + struct filter *cur; + module_t **pmodule; if (str == NULL) { return; @@ -339,8 +364,10 @@ parse_filters_str (struct rspamd_config *cfg, const gchar *str) pmodule = &modules[0]; while (*pmodule) { g_strstrip (*p); - if ((*pmodule)->name != NULL && g_ascii_strcasecmp ((*pmodule)->name, *p) == 0) { - cur = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct filter)); + if ((*pmodule)->name != NULL && + g_ascii_strcasecmp ((*pmodule)->name, *p) == 0) { + cur = rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct filter)); cur->type = C_FILTER; msg_debug ("found C filter %s", *p); cur->func_name = rspamd_mempool_strdup (cfg->cfg_pool, *p); @@ -349,7 +376,7 @@ parse_filters_str (struct rspamd_config *cfg, const gchar *str) break; } - pmodule ++; + pmodule++; } if (cur != NULL) { /* Go to next iteration */ @@ -365,24 +392,27 @@ parse_filters_str (struct rspamd_config *cfg, const gchar *str) static void reread_config (struct rspamd_main *rspamd) { - struct rspamd_config *tmp_cfg; - gchar *cfg_file; - GList *l; - struct filter *filt; + struct rspamd_config *tmp_cfg; + gchar *cfg_file; + GList *l; + struct filter *filt; tmp_cfg = (struct rspamd_config *)g_malloc (sizeof (struct rspamd_config)); if (tmp_cfg) { bzero (tmp_cfg, sizeof (struct rspamd_config)); tmp_cfg->cfg_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); rspamd_config_defaults (tmp_cfg); - cfg_file = rspamd_mempool_strdup (tmp_cfg->cfg_pool, rspamd->cfg->cfg_name); + cfg_file = rspamd_mempool_strdup (tmp_cfg->cfg_pool, + rspamd->cfg->cfg_name); /* Save some variables */ tmp_cfg->cfg_name = cfg_file; tmp_cfg->lua_state = init_lua (tmp_cfg); - rspamd_mempool_add_destructor (tmp_cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_close, tmp_cfg->lua_state); + rspamd_mempool_add_destructor (tmp_cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_close, tmp_cfg->lua_state); - if (! load_rspamd_config (tmp_cfg, FALSE)) { - rspamd_set_logger (rspamd_main->cfg, g_quark_try_string ("main"), rspamd_main); + if (!load_rspamd_config (tmp_cfg, FALSE)) { + rspamd_set_logger (rspamd_main->cfg, g_quark_try_string ( + "main"), rspamd_main); msg_err ("cannot parse new config file, revert to old one"); rspamd_config_free (tmp_cfg); } @@ -398,9 +428,12 @@ reread_config (struct rspamd_main *rspamd) } /* Pre-init of cache */ rspamd->cfg->cache = g_new0 (struct symbols_cache, 1); - rspamd->cfg->cache->static_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + rspamd->cfg->cache->static_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); rspamd->cfg->cache->cfg = rspamd->cfg; - rspamd_main->cfg->cache->items_by_symbol = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); + rspamd_main->cfg->cache->items_by_symbol = g_hash_table_new ( + rspamd_str_hash, + rspamd_str_equal); /* Perform modules configuring */ l = g_list_first (rspamd->cfg->filters); @@ -422,31 +455,35 @@ reread_config (struct rspamd_main *rspamd) static void set_worker_limits (struct rspamd_worker_conf *cf) { - struct rlimit rlmt; + struct rlimit rlmt; if (cf->rlimit_nofile != 0) { rlmt.rlim_cur = (rlim_t) cf->rlimit_nofile; rlmt.rlim_max = (rlim_t) cf->rlimit_nofile; - if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) { - msg_warn ("cannot set files rlimit: %d, %s", cf->rlimit_nofile, strerror (errno)); - } + if (setrlimit (RLIMIT_NOFILE, &rlmt) == -1) { + msg_warn ("cannot set files rlimit: %d, %s", + cf->rlimit_nofile, + strerror (errno)); + } } if (cf->rlimit_maxcore != 0) { rlmt.rlim_cur = (rlim_t) cf->rlimit_maxcore; rlmt.rlim_max = (rlim_t) cf->rlimit_maxcore; - if (setrlimit(RLIMIT_CORE, &rlmt) == -1) { - msg_warn ("cannot set max core rlimit: %d, %s", cf->rlimit_maxcore, strerror (errno)); - } + if (setrlimit (RLIMIT_CORE, &rlmt) == -1) { + msg_warn ("cannot set max core rlimit: %d, %s", + cf->rlimit_maxcore, + strerror (errno)); + } } } -static struct rspamd_worker * +static struct rspamd_worker * fork_worker (struct rspamd_main *rspamd, struct rspamd_worker_conf *cf) { - struct rspamd_worker *cur; + struct rspamd_worker *cur; /* Starting worker process */ cur = (struct rspamd_worker *)g_malloc (sizeof (struct rspamd_worker)); if (cur) { @@ -493,7 +530,8 @@ fork_worker (struct rspamd_main *rspamd, struct rspamd_worker_conf *cf) break; default: /* Insert worker into worker's table, pid is index */ - g_hash_table_insert (rspamd->workers, GSIZE_TO_POINTER (cur->pid), cur); + g_hash_table_insert (rspamd->workers, GSIZE_TO_POINTER ( + cur->pid), cur); break; } } @@ -505,7 +543,7 @@ static void set_alarm (guint seconds) { #ifdef HAVE_SETITIMER - static struct itimerval itv; + static struct itimerval itv; itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; @@ -530,10 +568,15 @@ delay_fork (struct rspamd_worker_conf *cf) static GList * create_listen_socket (const gchar *addr, gint port, gint listen_type) { - gint listen_sock = -1; - GList *result, *cur; + gint listen_sock = -1; + GList *result, *cur; /* Create listen sockets */ - result = make_universal_sockets_list (addr, port, listen_type, TRUE, TRUE, TRUE); + result = make_universal_sockets_list (addr, + port, + listen_type, + TRUE, + TRUE, + TRUE); cur = result; while (cur != NULL) { @@ -593,8 +636,8 @@ systemd_get_socket (gint number) static void fork_delayed (struct rspamd_main *rspamd) { - GList *cur; - struct rspamd_worker_conf *cf; + GList *cur; + struct rspamd_worker_conf *cf; while (workers_pending != NULL) { cur = workers_pending; @@ -609,7 +652,7 @@ fork_delayed (struct rspamd_main *rspamd) static inline uintptr_t make_listen_key (gint ai, const gchar *addr, gint port) { - uintptr_t res = 0; + uintptr_t res = 0; res = murmur32_hash (addr, strlen (addr)); res += murmur32_hash ((guchar *)&ai, sizeof (gint)); @@ -621,10 +664,10 @@ make_listen_key (gint ai, const gchar *addr, gint port) static void spawn_workers (struct rspamd_main *rspamd) { - GList *cur, *ls; - struct rspamd_worker_conf *cf; - gint i, key; - gpointer p; + GList *cur, *ls; + struct rspamd_worker_conf *cf; + gint i, key; + gpointer p; struct rspamd_worker_bind_conf *bcf; cur = rspamd->cfg->workers; @@ -637,22 +680,31 @@ spawn_workers (struct rspamd_main *rspamd) } else { if (cf->worker->has_socket) { - LL_FOREACH (cf->bind_conf, bcf) { - key = make_listen_key (bcf->ai, bcf->bind_host, bcf->bind_port); - if ((p = g_hash_table_lookup (listen_sockets, GINT_TO_POINTER (key))) == NULL) { + LL_FOREACH (cf->bind_conf, bcf) + { + key = make_listen_key (bcf->ai, + bcf->bind_host, + bcf->bind_port); + if ((p = + g_hash_table_lookup (listen_sockets, + GINT_TO_POINTER (key))) == NULL) { if (!bcf->is_systemd) { /* Create listen socket */ - ls = create_listen_socket (bcf->bind_host, bcf->bind_port, + ls = create_listen_socket (bcf->bind_host, + bcf->bind_port, cf->worker->listen_type); } else { ls = systemd_get_socket (bcf->ai); } if (ls == NULL) { - msg_err ("cannot listen on socket %s: %s", bcf->bind_host, strerror (errno)); + msg_err ("cannot listen on socket %s: %s", + bcf->bind_host, + strerror (errno)); exit (-errno); } - g_hash_table_insert (listen_sockets, GINT_TO_POINTER (key), ls); + g_hash_table_insert (listen_sockets, + GINT_TO_POINTER (key), ls); } else { /* We had socket for this type of worker */ @@ -667,7 +719,8 @@ spawn_workers (struct rspamd_main *rspamd) if (cf->worker->unique) { if (cf->count > 1) { - msg_err ("cannot spawn more than 1 %s worker, so spawn one", cf->worker->name); + msg_err ("cannot spawn more than 1 %s worker, so spawn one", + cf->worker->name); } fork_worker (rspamd, cf); } @@ -688,7 +741,7 @@ spawn_workers (struct rspamd_main *rspamd) static void kill_old_workers (gpointer key, gpointer value, gpointer unused) { - struct rspamd_worker *w = value; + struct rspamd_worker *w = value; kill (w->pid, SIGUSR2); msg_info ("send signal to worker %P", w->pid); @@ -697,8 +750,8 @@ kill_old_workers (gpointer key, gpointer value, gpointer unused) static gboolean wait_for_workers (gpointer key, gpointer value, gpointer unused) { - struct rspamd_worker *w = value; - gint res = 0; + struct rspamd_worker *w = value; + gint res = 0; if (got_alarm) { got_alarm = 0; @@ -721,8 +774,9 @@ wait_for_workers (gpointer key, gpointer value, gpointer unused) } } - msg_info ("%s process %P terminated %s", g_quark_to_string (w->type), w->pid, - got_alarm ? "hardly" : "softly"); + msg_info ("%s process %P terminated %s", g_quark_to_string ( + w->type), w->pid, + got_alarm ? "hardly" : "softly"); g_free (w->cf); g_free (w); @@ -732,7 +786,7 @@ wait_for_workers (gpointer key, gpointer value, gpointer unused) static void reopen_log_handler (gpointer key, gpointer value, gpointer unused) { - struct rspamd_worker *w = value; + struct rspamd_worker *w = value; if (kill (w->pid, SIGUSR1) == -1) { msg_err ("kill failed for pid %P: %s", w->pid, strerror (errno)); @@ -742,10 +796,10 @@ reopen_log_handler (gpointer key, gpointer value, gpointer unused) static void preload_statfiles (struct rspamd_main *rspamd) { - struct rspamd_classifier_config *cf; - struct rspamd_statfile_config *st; - stat_file_t *stf; - GList *cur_cl, *cur_st; + struct rspamd_classifier_config *cf; + struct rspamd_statfile_config *st; + stat_file_t *stf; + GList *cur_cl, *cur_st; cur_cl = rspamd->cfg->classifiers; while (cur_cl) { @@ -755,7 +809,10 @@ preload_statfiles (struct rspamd_main *rspamd) cur_st = cf->statfiles; while (cur_st) { st = cur_st->data; - stf = statfile_pool_open (rspamd->statfile_pool, st->path, st->size, FALSE); + stf = statfile_pool_open (rspamd->statfile_pool, + st->path, + st->size, + FALSE); if (stf == NULL) { msg_warn ("preload of %s from %s failed", st->symbol, st->path); } @@ -769,19 +826,20 @@ preload_statfiles (struct rspamd_main *rspamd) static gboolean load_rspamd_config (struct rspamd_config *cfg, gboolean init_modules) { - GList *l; - struct filter *filt; - struct module_ctx *cur_module = NULL; + GList *l; + struct filter *filt; + struct module_ctx *cur_module = NULL; - if (! rspamd_config_read (cfg, cfg->cfg_name, NULL, - config_logger, rspamd_main)) { + if (!rspamd_config_read (cfg, cfg->cfg_name, NULL, + config_logger, rspamd_main)) { return FALSE; } /* Strictly set temp dir */ if (!cfg->temp_dir) { msg_warn ("tempdir is not set, trying to use $TMPDIR"); - cfg->temp_dir = rspamd_mempool_strdup (cfg->cfg_pool, getenv ("TMPDIR")); + cfg->temp_dir = + rspamd_mempool_strdup (cfg->cfg_pool, getenv ("TMPDIR")); if (!cfg->temp_dir) { msg_warn ("$TMPDIR is empty too, using /tmp as default"); @@ -792,7 +850,7 @@ load_rspamd_config (struct rspamd_config *cfg, gboolean init_modules) /* Do post-load actions */ rspamd_config_post_load (cfg); parse_filters_str (cfg, cfg->filters_str); - + if (init_modules) { /* Init C modules */ l = g_list_first (cfg->filters); @@ -800,80 +858,102 @@ load_rspamd_config (struct rspamd_config *cfg, gboolean init_modules) while (l) { filt = l->data; if (filt->module) { - cur_module = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct module_ctx)); + cur_module = + rspamd_mempool_alloc (cfg->cfg_pool, + sizeof (struct module_ctx)); if (filt->module->module_init_func (cfg, &cur_module) == 0) { - g_hash_table_insert (cfg->c_modules, (gpointer) filt->module->name, cur_module); + g_hash_table_insert (cfg->c_modules, + (gpointer) filt->module->name, + cur_module); } } l = g_list_next (l); } } - + return TRUE; } static void -init_cfg_cache (struct rspamd_config *cfg) +init_cfg_cache (struct rspamd_config *cfg) { - if (!init_symbols_cache (cfg->cfg_pool, cfg->cache, cfg, cfg->cache_filename, FALSE)) { + if (!init_symbols_cache (cfg->cfg_pool, cfg->cache, cfg, + cfg->cache_filename, FALSE)) { exit (EXIT_FAILURE); } } static void -print_symbols_cache (struct rspamd_config *cfg) +print_symbols_cache (struct rspamd_config *cfg) { - GList *cur; - struct cache_item *item; - gint i; + GList *cur; + struct cache_item *item; + gint i; - if (!init_symbols_cache (cfg->cfg_pool, cfg->cache, cfg, cfg->cache_filename, TRUE)) { + if (!init_symbols_cache (cfg->cfg_pool, cfg->cache, cfg, + cfg->cache_filename, TRUE)) { exit (EXIT_FAILURE); } if (cfg->cache) { printf ("Symbols cache\n"); - printf ("-----------------------------------------------------------------\n"); - printf ("| Pri | Symbol | Weight | Frequency | Avg. time |\n"); + printf ( + "-----------------------------------------------------------------\n"); + printf ( + "| Pri | Symbol | Weight | Frequency | Avg. time |\n"); i = 0; cur = cfg->cache->negative_items; while (cur) { item = cur->data; if (!item->is_callback) { - printf ("-----------------------------------------------------------------\n"); - printf ("| %3d | %22s | %6.1f | %9d | %9.3f |\n", i, item->s->symbol, item->s->weight, item->s->frequency, item->s->avg_time); + printf ( + "-----------------------------------------------------------------\n"); + printf ("| %3d | %22s | %6.1f | %9d | %9.3f |\n", + i, + item->s->symbol, + item->s->weight, + item->s->frequency, + item->s->avg_time); } cur = g_list_next (cur); - i ++; + i++; } cur = cfg->cache->static_items; while (cur) { item = cur->data; if (!item->is_callback) { - printf ("-----------------------------------------------------------------\n"); - printf ("| %3d | %22s | %6.1f | %9d | %9.3f |\n", i, item->s->symbol, item->s->weight, item->s->frequency, item->s->avg_time); + printf ( + "-----------------------------------------------------------------\n"); + printf ("| %3d | %22s | %6.1f | %9d | %9.3f |\n", + i, + item->s->symbol, + item->s->weight, + item->s->frequency, + item->s->avg_time); } cur = g_list_next (cur); - i ++; + i++; } - printf ("-----------------------------------------------------------------\n"); + printf ( + "-----------------------------------------------------------------\n"); } } static gint perform_lua_tests (struct rspamd_config *cfg) { - gint i, tests_num, res = EXIT_SUCCESS; - gchar *cur_script; - lua_State *L = cfg->lua_state; + gint i, tests_num, res = EXIT_SUCCESS; + gchar *cur_script; + lua_State *L = cfg->lua_state; tests_num = g_strv_length (lua_tests); - for (i = 0; i < tests_num; i ++) { + for (i = 0; i < tests_num; i++) { if (luaL_loadfile (L, lua_tests[i]) != 0) { - msg_err ("load of %s failed: %s", lua_tests[i], lua_tostring (L, -1)); + msg_err ("load of %s failed: %s", lua_tests[i], + lua_tostring (L, -1)); res = EXIT_FAILURE; continue; } @@ -887,13 +967,15 @@ perform_lua_tests (struct rspamd_config *cfg) /* do the call (0 arguments, N result) */ if (lua_pcall (L, 0, LUA_MULTRET, 0) != 0) { - msg_info ("init of %s failed: %s", lua_tests[i], lua_tostring (L, -1)); + msg_info ("init of %s failed: %s", lua_tests[i], lua_tostring (L, + -1)); res = EXIT_FAILURE; continue; } if (lua_gettop (L) != 0) { if (lua_tonumber (L, -1) == -1) { - msg_info ("%s returned -1 that indicates configuration error", lua_tests[i]); + msg_info ("%s returned -1 that indicates configuration error", + lua_tests[i]); res = EXIT_FAILURE; continue; } @@ -915,51 +997,51 @@ perform_configs_sign (void) msg_err ("must have openssl at least 1.0.0 to perform this action"); return EXIT_FAILURE; # else - gint i, tests_num, res = EXIT_SUCCESS, fd; - guint diglen; - gchar *cur_file, in_file[PATH_MAX], - out_file[PATH_MAX], dig[EVP_MAX_MD_SIZE]; - gsize siglen; - struct stat st; - gpointer map, sig; - EVP_PKEY *key = NULL; - BIO *fbio; - EVP_PKEY_CTX *key_ctx = NULL; - EVP_MD_CTX *sign_ctx = NULL; + gint i, tests_num, res = EXIT_SUCCESS, fd; + guint diglen; + gchar *cur_file, in_file[PATH_MAX], + out_file[PATH_MAX], dig[EVP_MAX_MD_SIZE]; + gsize siglen; + struct stat st; + gpointer map, sig; + EVP_PKEY *key = NULL; + BIO *fbio; + EVP_PKEY_CTX *key_ctx = NULL; + EVP_MD_CTX *sign_ctx = NULL; /* Load private key */ fbio = BIO_new_file (privkey, "r"); if (fbio == NULL) { msg_err ("cannot open private key %s, %s", privkey, - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); return ERR_get_error (); } if (!PEM_read_bio_PrivateKey (fbio, &key, rspamd_read_passphrase, NULL)) { msg_err ("cannot read private key %s, %s", privkey, - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); return ERR_get_error (); } key_ctx = EVP_PKEY_CTX_new (key, NULL); if (key_ctx == NULL) { msg_err ("cannot parse private key %s, %s", privkey, - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); return ERR_get_error (); } if (EVP_PKEY_sign_init (key_ctx) <= 0) { msg_err ("cannot parse private key %s, %s", privkey, - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); return ERR_get_error (); } if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) { msg_err ("cannot init private key %s, %s", privkey, - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); return ERR_get_error (); } if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) { msg_err ("cannot init signature private key %s, %s", privkey, - ERR_error_string (ERR_get_error (), NULL)); + ERR_error_string (ERR_get_error (), NULL)); return ERR_get_error (); } @@ -967,7 +1049,7 @@ perform_configs_sign (void) tests_num = g_strv_length (sign_configs); - for (i = 0; i < tests_num; i ++) { + for (i = 0; i < tests_num; i++) { cur_file = sign_configs[i]; if (realpath (cur_file, in_file) == NULL) { msg_err ("cannot resolve %s: %s", cur_file, strerror (errno)); @@ -982,7 +1064,9 @@ perform_configs_sign (void) continue; } - if ((map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if ((map = + mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, + 0)) == MAP_FAILED) { close (fd); msg_err ("cannot mmap %s: %s", in_file, strerror (errno)); continue; @@ -997,15 +1081,19 @@ perform_configs_sign (void) munmap (map, st.st_size); if (EVP_PKEY_sign (key_ctx, NULL, &siglen, dig, diglen) <= 0) { - msg_err ("cannot sign %s using private key %s, %s", in_file, privkey, - ERR_error_string (ERR_get_error (), NULL)); + msg_err ("cannot sign %s using private key %s, %s", + in_file, + privkey, + ERR_error_string (ERR_get_error (), NULL)); continue; } sig = OPENSSL_malloc (siglen); if (EVP_PKEY_sign (key_ctx, sig, &siglen, dig, diglen) <= 0) { - msg_err ("cannot sign %s using private key %s, %s", in_file, privkey, - ERR_error_string (ERR_get_error (), NULL)); + msg_err ("cannot sign %s using private key %s, %s", + in_file, + privkey, + ERR_error_string (ERR_get_error (), NULL)); OPENSSL_free (sig); continue; } @@ -1013,12 +1101,14 @@ perform_configs_sign (void) rspamd_snprintf (out_file, sizeof (out_file), "%s.sig", in_file); fd = open (out_file, O_WRONLY | O_CREAT | O_TRUNC, 00644); if (fd == -1) { - msg_err ("cannot open output file %s: %s", out_file, strerror (errno)); + msg_err ("cannot open output file %s: %s", out_file, strerror ( + errno)); OPENSSL_free (sig); continue; } if (write (fd, sig, siglen) == -1) { - msg_err ("cannot write to output file %s: %s", out_file, strerror (errno)); + msg_err ("cannot write to output file %s: %s", out_file, + strerror (errno)); } OPENSSL_free (sig); close (fd); @@ -1038,15 +1128,15 @@ perform_configs_sign (void) gint main (gint argc, gchar **argv, gchar **env) { - gint res = 0, i; - struct sigaction signals; - struct rspamd_worker *cur; - struct rlimit rlim; - struct filter *filt; - pid_t wrk; - GList *l; - worker_t **pworker; - GQuark type; + gint res = 0, i; + struct sigaction signals; + struct rspamd_worker *cur; + struct rlimit rlim; + struct filter *filt; + pid_t wrk; + GList *l; + worker_t **pworker; + GQuark type; #ifdef HAVE_SA_SIGINFO signals_info = g_queue_new (); @@ -1055,8 +1145,10 @@ main (gint argc, gchar **argv, gchar **env) g_thread_init (NULL); #endif rspamd_main = (struct rspamd_main *)g_malloc0 (sizeof (struct rspamd_main)); - rspamd_main->server_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); - rspamd_main->cfg = (struct rspamd_config *)g_malloc0 (sizeof (struct rspamd_config)); + rspamd_main->server_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); + rspamd_main->cfg = + (struct rspamd_config *)g_malloc0 (sizeof (struct rspamd_config)); if (!rspamd_main || !rspamd_main->cfg) { fprintf (stderr, "Cannot allocate memory\n"); @@ -1067,10 +1159,12 @@ main (gint argc, gchar **argv, gchar **env) init_title (argc, argv, env); #endif - rspamd_main->stat = rspamd_mempool_alloc_shared (rspamd_main->server_pool, sizeof (struct rspamd_stat)); + rspamd_main->stat = rspamd_mempool_alloc_shared (rspamd_main->server_pool, + sizeof (struct rspamd_stat)); memset (rspamd_main->stat, 0, sizeof (struct rspamd_stat)); - rspamd_main->cfg->cfg_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + rspamd_main->cfg->cfg_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); rspamd_config_defaults (rspamd_main->cfg); memset (&signals, 0, sizeof (struct sigaction)); @@ -1090,10 +1184,10 @@ main (gint argc, gchar **argv, gchar **env) #ifdef HAVE_SETLOCALE /* Set locale setting to C locale to avoid problems in future */ - setlocale (LC_ALL, "C"); - setlocale (LC_CTYPE, "C"); + setlocale (LC_ALL, "C"); + setlocale (LC_CTYPE, "C"); setlocale (LC_MESSAGES, "C"); - setlocale (LC_TIME, "C"); + setlocale (LC_TIME, "C"); #endif #ifdef HAVE_OPENSSL @@ -1114,25 +1208,32 @@ main (gint argc, gchar **argv, gchar **env) detect_priv (rspamd_main); rspamd_main->cfg->lua_state = init_lua (rspamd_main->cfg); - rspamd_mempool_add_destructor (rspamd_main->cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_close, rspamd_main->cfg->lua_state); + rspamd_mempool_add_destructor (rspamd_main->cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_close, rspamd_main->cfg->lua_state); pworker = &workers[0]; while (*pworker) { /* Init string quarks */ (void)g_quark_from_static_string ((*pworker)->name); - pworker ++; + pworker++; } /* Init counters */ - rspamd_main->counters = rspamd_hash_new_shared (rspamd_main->server_pool, rspamd_str_hash, rspamd_str_equal, 64); + rspamd_main->counters = rspamd_hash_new_shared (rspamd_main->server_pool, + rspamd_str_hash, + rspamd_str_equal, + 64); /* Init listen sockets hash */ listen_sockets = g_hash_table_new (g_direct_hash, g_direct_equal); /* Pre-init of cache */ rspamd_main->cfg->cache = g_new0 (struct symbols_cache, 1); - rspamd_main->cfg->cache->static_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + rspamd_main->cfg->cache->static_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); rspamd_main->cfg->cache->cfg = rspamd_main->cfg; - rspamd_main->cfg->cache->items_by_symbol = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); + rspamd_main->cfg->cache->items_by_symbol = g_hash_table_new ( + rspamd_str_hash, + rspamd_str_equal); /* If we want to test lua skip everything except it */ if (lua_tests != NULL && lua_tests[0] != NULL) { @@ -1145,7 +1246,7 @@ main (gint argc, gchar **argv, gchar **env) } /* Load config */ - if (! load_rspamd_config (rspamd_main->cfg, TRUE)) { + if (!load_rspamd_config (rspamd_main->cfg, TRUE)) { exit (EXIT_FAILURE); } @@ -1153,7 +1254,7 @@ main (gint argc, gchar **argv, gchar **env) if (rspamd_pidfile != NULL) { rspamd_main->cfg->pid_file = rspamd_pidfile; } - + /* Force debug log */ if (is_debug) { rspamd_main->cfg->log_level = G_LOG_LEVEL_DEBUG; @@ -1163,7 +1264,7 @@ main (gint argc, gchar **argv, gchar **env) /* Init events to test modules */ event_init (); res = TRUE; - if (! init_lua_filters (rspamd_main->cfg)) { + if (!init_lua_filters (rspamd_main->cfg)) { res = FALSE; } /* Perform modules configuring */ @@ -1181,7 +1282,8 @@ main (gint argc, gchar **argv, gchar **env) /* Insert classifiers symbols */ (void)rspamd_config_insert_classify_symbols (rspamd_main->cfg); - if (! validate_cache (rspamd_main->cfg->cache, rspamd_main->cfg, FALSE)) { + if (!validate_cache (rspamd_main->cfg->cache, rspamd_main->cfg, + FALSE)) { res = FALSE; } if (dump_cache) { @@ -1201,7 +1303,9 @@ main (gint argc, gchar **argv, gchar **env) rspamd_main->history = rspamd_roll_history_new (rspamd_main->server_pool); msg_info ("rspamd " RVERSION " is starting, build id: " RID); - rspamd_main->cfg->cfg_name = rspamd_mempool_strdup (rspamd_main->cfg->cfg_pool, rspamd_main->cfg->cfg_name); + rspamd_main->cfg->cfg_name = rspamd_mempool_strdup ( + rspamd_main->cfg->cfg_pool, + rspamd_main->cfg->cfg_name); /* Daemonize */ if (!rspamd_main->cfg->no_fork && daemon (0, 0) == -1) { @@ -1226,13 +1330,14 @@ main (gint argc, gchar **argv, gchar **env) setproctitle ("main process"); /* Init statfile pool */ - rspamd_main->statfile_pool = statfile_pool_new (rspamd_main->server_pool, rspamd_main->cfg->mlock_statfile_pool); + rspamd_main->statfile_pool = statfile_pool_new (rspamd_main->server_pool, + rspamd_main->cfg->mlock_statfile_pool); event_init (); g_mime_init (0); /* Init lua filters */ - if (! init_lua_filters (rspamd_main->cfg)) { + if (!init_lua_filters (rspamd_main->cfg)) { msg_err ("error loading lua plugins"); exit (EXIT_FAILURE); } @@ -1268,7 +1373,8 @@ main (gint argc, gchar **argv, gchar **env) /* Maybe read roll history */ if (rspamd_main->cfg->history_file) { - rspamd_roll_history_load (rspamd_main->history, rspamd_main->cfg->history_file); + rspamd_roll_history_load (rspamd_main->history, + rspamd_main->cfg->history_file); } /* Spawn workers */ @@ -1276,7 +1382,7 @@ main (gint argc, gchar **argv, gchar **env) spawn_workers (rspamd_main); /* Signal processing cycle */ - for (;;) { + for (;; ) { msg_debug ("calling sigsuspend"); sigemptyset (&signals.sa_mask); sigsuspend (&signals.sa_mask); @@ -1294,21 +1400,32 @@ main (gint argc, gchar **argv, gchar **env) msg_debug ("catch SIGCHLD signal, finding terminated worker"); /* Remove dead child form children list */ wrk = waitpid (0, &res, 0); - if ((cur = g_hash_table_lookup (rspamd_main->workers, GSIZE_TO_POINTER (wrk))) != NULL) { + if ((cur = + g_hash_table_lookup (rspamd_main->workers, + GSIZE_TO_POINTER (wrk))) != NULL) { /* Unlink dead process from queue and hash table */ - g_hash_table_remove (rspamd_main->workers, GSIZE_TO_POINTER (wrk)); + g_hash_table_remove (rspamd_main->workers, GSIZE_TO_POINTER ( + wrk)); if (WIFEXITED (res) && WEXITSTATUS (res) == 0) { /* Normal worker termination, do not fork one more */ - msg_info ("%s process %P terminated normally", g_quark_to_string (cur->type), cur->pid); + msg_info ("%s process %P terminated normally", + g_quark_to_string (cur->type), + cur->pid); } else { if (WIFSIGNALED (res)) { - msg_warn ("%s process %P terminated abnormally by signal: %d", g_quark_to_string (cur->type), cur->pid, WTERMSIG (res)); + msg_warn ( + "%s process %P terminated abnormally by signal: %d", + g_quark_to_string (cur->type), + cur->pid, + WTERMSIG (res)); } else { - msg_warn ("%s process %P terminated abnormally", g_quark_to_string (cur->type), cur->pid); + msg_warn ("%s process %P terminated abnormally", + g_quark_to_string (cur->type), + cur->pid); } /* Fork another worker in replace of dead one */ delay_fork (cur->cf); @@ -1317,7 +1434,7 @@ main (gint argc, gchar **argv, gchar **env) g_free (cur); } else { - for (i = 0; i < (gint)other_workers->len; i ++) { + for (i = 0; i < (gint)other_workers->len; i++) { if (g_array_index (other_workers, pid_t, i) == wrk) { g_array_remove_index_fast (other_workers, i); msg_info ("related process %P terminated", wrk); @@ -1327,7 +1444,9 @@ main (gint argc, gchar **argv, gchar **env) } if (do_restart) { do_restart = 0; - reopen_log_priv (rspamd_main->logger, rspamd_main->workers_uid, rspamd_main->workers_gid); + reopen_log_priv (rspamd_main->logger, + rspamd_main->workers_uid, + rspamd_main->workers_gid); msg_info ("rspamd " RVERSION " is restarting"); g_hash_table_foreach (rspamd_main->workers, kill_old_workers, NULL); remove_all_maps (rspamd_main->cfg); @@ -1336,8 +1455,11 @@ main (gint argc, gchar **argv, gchar **env) } if (do_reopen_log) { do_reopen_log = 0; - reopen_log_priv (rspamd_main->logger, rspamd_main->workers_uid, rspamd_main->workers_gid); - g_hash_table_foreach (rspamd_main->workers, reopen_log_handler, NULL); + reopen_log_priv (rspamd_main->logger, + rspamd_main->workers_uid, + rspamd_main->workers_gid); + g_hash_table_foreach (rspamd_main->workers, reopen_log_handler, + NULL); } if (got_alarm) { got_alarm = 0; @@ -1352,7 +1474,7 @@ main (gint argc, gchar **argv, gchar **env) sigaddset (&signals.sa_mask, SIGTERM); sigaction (SIGALRM, &signals, NULL); sigaction (SIGTERM, &signals, NULL); - sigaction (SIGINT, &signals, NULL); + sigaction (SIGINT, &signals, NULL); sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL); /* Set alarm for hard termination */ set_alarm (HARD_TERMINATION_TIME); @@ -1361,7 +1483,8 @@ main (gint argc, gchar **argv, gchar **env) /* Maybe save roll history */ if (rspamd_main->cfg->history_file) { - rspamd_roll_history_save (rspamd_main->history, rspamd_main->cfg->history_file); + rspamd_roll_history_save (rspamd_main->history, + rspamd_main->cfg->history_file); } msg_info ("terminating..."); @@ -1382,6 +1505,6 @@ main (gint argc, gchar **argv, gchar **env) return (res); } -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/main.h b/src/main.h index df3792d13..577cd5c42 100644 --- a/src/main.h +++ b/src/main.h @@ -43,21 +43,21 @@ #define CR '\r' #define LF '\n' -/** - * Worker process structure +/** + * Worker process structure */ struct rspamd_worker { - pid_t pid; /**< pid of worker */ - gboolean is_initialized; /**< is initialized */ - gboolean is_dying; /**< if worker is going to shutdown */ - gboolean pending; /**< if worker is pending to run */ - struct rspamd_main *srv; /**< pointer to server structure */ - GQuark type; /**< process type */ - struct event sig_ev_usr1; /**< signals event */ - struct event sig_ev_usr2; /**< signals event */ - GList *accept_events; /**< socket events */ - struct rspamd_worker_conf *cf; /**< worker config data */ - gpointer ctx; /**< worker's specific data */ + pid_t pid; /**< pid of worker */ + gboolean is_initialized; /**< is initialized */ + gboolean is_dying; /**< if worker is going to shutdown */ + gboolean pending; /**< if worker is pending to run */ + struct rspamd_main *srv; /**< pointer to server structure */ + GQuark type; /**< process type */ + struct event sig_ev_usr1; /**< signals event */ + struct event sig_ev_usr2; /**< signals event */ + GList *accept_events; /**< socket events */ + struct rspamd_worker_conf *cf; /**< worker config data */ + gpointer ctx; /**< worker's specific data */ }; /** @@ -73,40 +73,40 @@ struct mime_part; struct rspamd_dns_resolver; struct rspamd_task; -/** +/** * Server statistics */ struct rspamd_stat { - guint messages_scanned; /**< total number of messages scanned */ - guint actions_stat[METRIC_ACTION_NOACTION + 1]; /**< statistic for each action */ - guint connections_count; /**< total connections count */ - guint control_connections_count; /**< connections count to control interface */ - guint messages_learned; /**< messages learned */ - guint fuzzy_hashes; /**< number of fuzzy hashes stored */ - guint fuzzy_hashes_expired; /**< number of fuzzy hashes expired */ + guint messages_scanned; /**< total number of messages scanned */ + guint actions_stat[METRIC_ACTION_NOACTION + 1]; /**< statistic for each action */ + guint connections_count; /**< total connections count */ + guint control_connections_count; /**< connections count to control interface */ + guint messages_learned; /**< messages learned */ + guint fuzzy_hashes; /**< number of fuzzy hashes stored */ + guint fuzzy_hashes_expired; /**< number of fuzzy hashes expired */ }; /** * Struct that determine main server object (for logging purposes) */ struct rspamd_main { - struct rspamd_config *cfg; /**< pointer to config structure */ - pid_t pid; /**< main pid */ + struct rspamd_config *cfg; /**< pointer to config structure */ + pid_t pid; /**< main pid */ /* Pid file structure */ - rspamd_pidfh_t *pfh; /**< struct pidfh for pidfile */ - GQuark type; /**< process type */ - guint ev_initialized; /**< is event system is initialized */ - struct rspamd_stat *stat; /**< pointer to statistics */ + rspamd_pidfh_t *pfh; /**< struct pidfh for pidfile */ + GQuark type; /**< process type */ + guint ev_initialized; /**< is event system is initialized */ + struct rspamd_stat *stat; /**< pointer to statistics */ - rspamd_mempool_t *server_pool; /**< server's memory pool */ - statfile_pool_t *statfile_pool; /**< shared statfiles pool */ + rspamd_mempool_t *server_pool; /**< server's memory pool */ + statfile_pool_t *statfile_pool; /**< shared statfiles pool */ GHashTable *workers; /**< workers pool indexed by pid */ - rspamd_hash_t *counters; /**< symbol cache counters */ + rspamd_hash_t *counters; /**< symbol cache counters */ rspamd_logger_t *logger; - uid_t workers_uid; /**< worker's uid running to */ - gid_t workers_gid; /**< worker's gid running to */ - gboolean is_privilleged; /**< true if run in privilleged mode */ - struct roll_history *history; /**< rolling history */ + uid_t workers_uid; /**< worker's uid running to */ + gid_t workers_gid; /**< worker's gid running to */ + gboolean is_privilleged; /**< true if run in privilleged mode */ + struct roll_history *history; /**< rolling history */ }; struct counter_data { @@ -127,10 +127,11 @@ struct process_exception { */ struct controller_command; struct controller_session; -typedef gboolean (*controller_func_t)(gchar **args, struct controller_session *session); +typedef gboolean (*controller_func_t)(gchar **args, + struct controller_session *session); struct controller_session { - struct rspamd_worker *worker; /**< pointer to worker structure (controller in fact) */ + struct rspamd_worker *worker; /**< pointer to worker structure (controller in fact) */ enum { STATE_COMMAND, STATE_HEADER, @@ -142,45 +143,48 @@ struct controller_session { STATE_OTHER, STATE_WAIT, STATE_WEIGHTS - } state; /**< current session state */ - gint sock; /**< socket descriptor */ + } state; /**< current session state */ + gint sock; /**< socket descriptor */ /* Access to authorized commands */ - gboolean authorized; /**< whether this session is authorized */ - gboolean restful; /**< whether this session is a restful session */ - GHashTable *kwargs; /**< keyword arguments for restful command */ - struct controller_command *cmd; /**< real command */ - rspamd_mempool_t *session_pool; /**< memory pool for session */ - struct rspamd_config *cfg; /**< pointer to config file */ - gchar *learn_rcpt; /**< recipient for learning */ - gchar *learn_from; /**< from address for learning */ + gboolean authorized; /**< whether this session is authorized */ + gboolean restful; /**< whether this session is a restful session */ + GHashTable *kwargs; /**< keyword arguments for restful command */ + struct controller_command *cmd; /**< real command */ + rspamd_mempool_t *session_pool; /**< memory pool for session */ + struct rspamd_config *cfg; /**< pointer to config file */ + gchar *learn_rcpt; /**< recipient for learning */ + gchar *learn_from; /**< from address for learning */ struct rspamd_classifier_config *learn_classifier; - gchar *learn_symbol; /**< symbol to train */ - double learn_multiplier; /**< multiplier for learning */ - rspamd_io_dispatcher_t *dispatcher; /**< IO dispatcher object */ - f_str_t *learn_buf; /**< learn input */ - GList *parts; /**< extracted mime parts */ - gint in_class; /**< positive or negative learn */ + gchar *learn_symbol; /**< symbol to train */ + double learn_multiplier; /**< multiplier for learning */ + rspamd_io_dispatcher_t *dispatcher; /**< IO dispatcher object */ + f_str_t *learn_buf; /**< learn input */ + GList *parts; /**< extracted mime parts */ + gint in_class; /**< positive or negative learn */ gboolean (*other_handler)(struct controller_session *session, - f_str_t *in); /**< other command handler to execute at the end of processing */ - void *other_data; /**< and its data */ - controller_func_t custom_handler; /**< custom command handler */ - struct rspamd_async_session* s; /**< async session object */ + f_str_t *in); /**< other command handler to execute at the end of processing */ + void *other_data; /**< and its data */ + controller_func_t custom_handler; /**< custom command handler */ + struct rspamd_async_session * s; /**< async session object */ struct rspamd_task *learn_task; - struct rspamd_dns_resolver *resolver; /**< DNS resolver */ - struct event_base *ev_base; /**< Event base */ + struct rspamd_dns_resolver *resolver; /**< DNS resolver */ + struct event_base *ev_base; /**< Event base */ }; /** * Common structure representing C module context */ struct module_ctx { - gint (*filter)(struct rspamd_task *task); /**< pointer to headers process function */ + gint (*filter)(struct rspamd_task *task); /**< pointer to headers process function */ }; /** * Register custom controller function */ -void register_custom_controller_command (const gchar *name, controller_func_t handler, gboolean privilleged, gboolean require_message); +void register_custom_controller_command (const gchar *name, + controller_func_t handler, + gboolean privilleged, + gboolean require_message); /** * If set, reopen log file on next write @@ -189,6 +193,6 @@ extern struct rspamd_main *rspamd_main; #endif -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/plugins/chartable.c b/src/plugins/chartable.c index e5ea0fb71..8e5bfac5a 100644 --- a/src/plugins/chartable.c +++ b/src/plugins/chartable.c @@ -54,17 +54,17 @@ module_t chartable_module = { }; struct chartable_ctx { - gint (*filter) (struct rspamd_task * task); - const gchar *symbol; - double threshold; + gint (*filter) (struct rspamd_task * task); + const gchar *symbol; + double threshold; - rspamd_mempool_t *chartable_pool; + rspamd_mempool_t *chartable_pool; }; -static struct chartable_ctx *chartable_module_ctx = NULL; +static struct chartable_ctx *chartable_module_ctx = NULL; -static gint chartable_mime_filter (struct rspamd_task *task); -static void chartable_symbol_callback (struct rspamd_task *task, void *unused); +static gint chartable_mime_filter (struct rspamd_task *task); +static void chartable_symbol_callback (struct rspamd_task *task, void *unused); gint chartable_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) @@ -72,7 +72,8 @@ chartable_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) chartable_module_ctx = g_malloc (sizeof (struct chartable_ctx)); chartable_module_ctx->filter = chartable_mime_filter; - chartable_module_ctx->chartable_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + chartable_module_ctx->chartable_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); *ctx = (struct module_ctx *)chartable_module_ctx; @@ -83,16 +84,18 @@ chartable_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) gint chartable_module_config (struct rspamd_config *cfg) { - const ucl_object_t *value; - gint res = TRUE; + const ucl_object_t *value; + gint res = TRUE; - if ((value = rspamd_config_get_module_opt (cfg, "chartable", "symbol")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "chartable", "symbol")) != NULL) { chartable_module_ctx->symbol = ucl_obj_tostring (value); } else { chartable_module_ctx->symbol = DEFAULT_SYMBOL; - } - if ((value = rspamd_config_get_module_opt (cfg, "chartable", "threshold")) != NULL) { + } + if ((value = + rspamd_config_get_module_opt (cfg, "chartable", "threshold")) != NULL) { if (!ucl_obj_todouble_safe (value, &chartable_module_ctx->threshold)) { msg_warn ("invalid numeric value"); chartable_module_ctx->threshold = DEFAULT_THRESHOLD; @@ -102,7 +105,11 @@ chartable_module_config (struct rspamd_config *cfg) chartable_module_ctx->threshold = DEFAULT_THRESHOLD; } - register_symbol (&cfg->cache, chartable_module_ctx->symbol, 1, chartable_symbol_callback, NULL); + register_symbol (&cfg->cache, + chartable_module_ctx->symbol, + 1, + chartable_symbol_callback, + NULL); return res; } @@ -116,27 +123,31 @@ chartable_module_reconfig (struct rspamd_config *cfg) return chartable_module_config (cfg); } -static gboolean +static gboolean check_part (struct mime_text_part *part, gboolean raw_mode) { - guchar *p, *p1; - gunichar c, t; - GUnicodeScript scc, sct; - guint32 mark = 0, total = 0, max = 0, i; - guint32 remain = part->content->len; - guint32 scripts[G_UNICODE_SCRIPT_NKO]; - GUnicodeScript sel = 0; + guchar *p, *p1; + gunichar c, t; + GUnicodeScript scc, sct; + guint32 mark = 0, total = 0, max = 0, i; + guint32 remain = part->content->len; + guint32 scripts[G_UNICODE_SCRIPT_NKO]; + GUnicodeScript sel = 0; p = part->content->data; if (part->is_raw || raw_mode) { while (remain > 1) { - if ((g_ascii_isalpha (*p) && (*(p + 1) & 0x80)) || ((*p & 0x80) && g_ascii_isalpha (*(p + 1)))) { + if ((g_ascii_isalpha (*p) && + (*(p + 1) & 0x80)) || + ((*p & 0x80) && g_ascii_isalpha (*(p + 1)))) { mark++; total++; } /* Current and next symbols are of one class */ - else if (((*p & 0x80) && (*(p + 1) & 0x80)) || (g_ascii_isalpha (*p) && g_ascii_isalpha (*(p + 1)))) { + else if (((*p & 0x80) && + (*(p + 1) & 0x80)) || + (g_ascii_isalpha (*p) && g_ascii_isalpha (*(p + 1)))) { total++; } p++; @@ -147,14 +158,14 @@ check_part (struct mime_text_part *part, gboolean raw_mode) memset (&scripts, 0, sizeof (scripts)); while (remain > 0) { c = g_utf8_get_char_validated (p, remain); - if (c == (gunichar) -2 || c == (gunichar) -1) { + if (c == (gunichar) - 2 || c == (gunichar) - 1) { /* Invalid characters detected, stop processing */ return FALSE; } scc = g_unichar_get_script (c); if (scc < (gint)G_N_ELEMENTS (scripts)) { - scripts[scc] ++; + scripts[scc]++; } p1 = g_utf8_next_char (p); remain -= p1 - p; @@ -162,7 +173,7 @@ check_part (struct mime_text_part *part, gboolean raw_mode) if (remain > 0) { t = g_utf8_get_char_validated (p, remain); - if (t == (gunichar) -2 || t == (gunichar) -1) { + if (t == (gunichar) - 2 || t == (gunichar) - 1) { /* Invalid characters detected, stop processing */ return FALSE; } @@ -180,7 +191,7 @@ check_part (struct mime_text_part *part, gboolean raw_mode) } } /* Detect the mostly charset of this part */ - for (i = 0; i < G_N_ELEMENTS (scripts); i ++) { + for (i = 0; i < G_N_ELEMENTS (scripts); i++) { if (scripts[i] > max) { max = scripts[i]; sel = i; @@ -199,8 +210,8 @@ check_part (struct mime_text_part *part, gboolean raw_mode) static void chartable_symbol_callback (struct rspamd_task *task, void *unused) { - GList *cur; - struct mime_text_part *part; + GList *cur; + struct mime_text_part *part; cur = g_list_first (task->text_parts); while (cur) { diff --git a/src/plugins/dkim_check.c b/src/plugins/dkim_check.c index 78743ebf1..6a162af40 100644 --- a/src/plugins/dkim_check.c +++ b/src/plugins/dkim_check.c @@ -55,24 +55,24 @@ #define DEFAULT_TIME_JITTER 60 struct dkim_ctx { - gint (*filter) (struct rspamd_task * task); - const gchar *symbol_reject; - const gchar *symbol_tempfail; - const gchar *symbol_allow; - - rspamd_mempool_t *dkim_pool; - radix_tree_t *whitelist_ip; - GHashTable *dkim_domains; - guint strict_multiplier; - guint time_jitter; - rspamd_lru_hash_t *dkim_hash; - gboolean trusted_only; - gboolean skip_multi; + gint (*filter) (struct rspamd_task * task); + const gchar *symbol_reject; + const gchar *symbol_tempfail; + const gchar *symbol_allow; + + rspamd_mempool_t *dkim_pool; + radix_tree_t *whitelist_ip; + GHashTable *dkim_domains; + guint strict_multiplier; + guint time_jitter; + rspamd_lru_hash_t *dkim_hash; + gboolean trusted_only; + gboolean skip_multi; }; -static struct dkim_ctx *dkim_module_ctx = NULL; +static struct dkim_ctx *dkim_module_ctx = NULL; -static void dkim_symbol_callback (struct rspamd_task *task, void *unused); +static void dkim_symbol_callback (struct rspamd_task *task, void *unused); /* Initialization */ gint dkim_module_init (struct rspamd_config *cfg, struct module_ctx **ctx); @@ -92,7 +92,8 @@ dkim_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) { dkim_module_ctx = g_malloc0 (sizeof (struct dkim_ctx)); - dkim_module_ctx->dkim_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + dkim_module_ctx->dkim_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); *ctx = (struct module_ctx *)dkim_module_ctx; @@ -102,79 +103,96 @@ dkim_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) gint dkim_module_config (struct rspamd_config *cfg) { - const ucl_object_t *value; - gint res = TRUE; - guint cache_size, cache_expire; - gboolean got_trusted = FALSE; + const ucl_object_t *value; + gint res = TRUE; + guint cache_size, cache_expire; + gboolean got_trusted = FALSE; dkim_module_ctx->whitelist_ip = radix_tree_create (); - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_reject")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "symbol_reject")) != NULL) { dkim_module_ctx->symbol_reject = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_reject = DEFAULT_SYMBOL_REJECT; } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_tempfail")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", + "symbol_tempfail")) != NULL) { dkim_module_ctx->symbol_tempfail = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_tempfail = DEFAULT_SYMBOL_TEMPFAIL; } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_allow")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "symbol_allow")) != NULL) { dkim_module_ctx->symbol_allow = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_allow = DEFAULT_SYMBOL_ALLOW; } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "dkim_cache_size")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", + "dkim_cache_size")) != NULL) { cache_size = ucl_obj_toint (value); } else { cache_size = DEFAULT_CACHE_SIZE; } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "dkim_cache_expire")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", + "dkim_cache_expire")) != NULL) { cache_expire = ucl_obj_todouble (value); } else { cache_expire = DEFAULT_CACHE_MAXAGE; } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "time_jitter")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "time_jitter")) != NULL) { dkim_module_ctx->time_jitter = ucl_obj_todouble (value); } else { dkim_module_ctx->time_jitter = DEFAULT_TIME_JITTER; } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "whitelist")) != NULL) { - if (! add_map (cfg, ucl_obj_tostring (value), - "DKIM whitelist", read_radix_list, fin_radix_list, - (void **)&dkim_module_ctx->whitelist_ip)) { - msg_warn ("cannot load whitelist from %s", ucl_obj_tostring (value)); + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "whitelist")) != NULL) { + if (!add_map (cfg, ucl_obj_tostring (value), + "DKIM whitelist", read_radix_list, fin_radix_list, + (void **)&dkim_module_ctx->whitelist_ip)) { + msg_warn ("cannot load whitelist from %s", + ucl_obj_tostring (value)); } } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "domains")) != NULL) { - if (! add_map (cfg, ucl_obj_tostring (value), - "DKIM domains", read_kv_list, fin_kv_list, - (void **)&dkim_module_ctx->dkim_domains)) { - msg_warn ("cannot load dkim domains list from %s", ucl_obj_tostring (value)); + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "domains")) != NULL) { + if (!add_map (cfg, ucl_obj_tostring (value), + "DKIM domains", read_kv_list, fin_kv_list, + (void **)&dkim_module_ctx->dkim_domains)) { + msg_warn ("cannot load dkim domains list from %s", + ucl_obj_tostring (value)); } else { got_trusted = TRUE; } } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "strict_multiplier")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", + "strict_multiplier")) != NULL) { dkim_module_ctx->strict_multiplier = ucl_obj_toint (value); } else { dkim_module_ctx->strict_multiplier = 1; } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "trusted_only")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "trusted_only")) != NULL) { dkim_module_ctx->trusted_only = ucl_obj_toboolean (value); } else { dkim_module_ctx->trusted_only = FALSE; } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "skip_multi")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "skip_multi")) != NULL) { dkim_module_ctx->skip_multi = ucl_obj_toboolean (value); } else { @@ -182,19 +200,33 @@ dkim_module_config (struct rspamd_config *cfg) } if (dkim_module_ctx->trusted_only && !got_trusted) { - msg_err ("trusted_only option is set and no trusted domains are defined; disabling dkim module completely as it is useless in this case"); + msg_err ( + "trusted_only option is set and no trusted domains are defined; disabling dkim module completely as it is useless in this case"); } else { - register_symbol (&cfg->cache, dkim_module_ctx->symbol_reject, 1, dkim_symbol_callback, NULL); - register_virtual_symbol (&cfg->cache, dkim_module_ctx->symbol_tempfail, 1); - register_virtual_symbol (&cfg->cache, dkim_module_ctx->symbol_allow, 1); - - dkim_module_ctx->dkim_hash = rspamd_lru_hash_new (rspamd_strcase_hash, rspamd_strcase_equal, - cache_size, cache_expire, g_free, (GDestroyNotify)rspamd_dkim_key_free); + register_symbol (&cfg->cache, + dkim_module_ctx->symbol_reject, + 1, + dkim_symbol_callback, + NULL); + register_virtual_symbol (&cfg->cache, + dkim_module_ctx->symbol_tempfail, + 1); + register_virtual_symbol (&cfg->cache, + dkim_module_ctx->symbol_allow, + 1); + + dkim_module_ctx->dkim_hash = rspamd_lru_hash_new (rspamd_strcase_hash, + rspamd_strcase_equal, + cache_size, + cache_expire, + g_free, + (GDestroyNotify)rspamd_dkim_key_free); #ifndef HAVE_OPENSSL - msg_warn ("openssl is not found so dkim rsa check is disabled, only check body hash, it is NOT safe to trust these results"); + msg_warn ( + "openssl is not found so dkim rsa check is disabled, only check body hash, it is NOT safe to trust these results"); #endif } @@ -209,7 +241,8 @@ dkim_module_reconfig (struct rspamd_config *cfg) if (dkim_module_ctx->dkim_domains) { g_hash_table_destroy (dkim_module_ctx->dkim_domains); } - dkim_module_ctx->dkim_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + dkim_module_ctx->dkim_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); return dkim_module_config (cfg); } @@ -220,14 +253,14 @@ dkim_module_reconfig (struct rspamd_config *cfg) static gboolean dkim_module_parse_strict (const gchar *value, gint *allow, gint *deny) { - const gchar *colon; - gulong val; + const gchar *colon; + gulong val; colon = strchr (value, ':'); if (colon) { if (rspamd_strtoul (value, colon - value, &val)) { *deny = val; - colon ++; + colon++; if (rspamd_strtoul (colon, strlen (colon), &val)) { *allow = val; return TRUE; @@ -238,25 +271,38 @@ dkim_module_parse_strict (const gchar *value, gint *allow, gint *deny) } static void -dkim_module_check (struct rspamd_task *task, rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key) +dkim_module_check (struct rspamd_task *task, + rspamd_dkim_context_t *ctx, + rspamd_dkim_key_t *key) { - gint res, score_allow = 1, score_deny = 1; - const gchar *strict_value; + gint res, score_allow = 1, score_deny = 1; + const gchar *strict_value; - msg_debug ("check dkim signature for %s domain from %s", ctx->domain, ctx->dns_key); + msg_debug ("check dkim signature for %s domain from %s", + ctx->domain, + ctx->dns_key); res = rspamd_dkim_check (ctx, key, task); if (dkim_module_ctx->dkim_domains != NULL) { /* Perform strict check */ - if ((strict_value = g_hash_table_lookup (dkim_module_ctx->dkim_domains, ctx->domain)) != NULL) { - if (!dkim_module_parse_strict (strict_value, &score_allow, &score_deny)) { + if ((strict_value = + g_hash_table_lookup (dkim_module_ctx->dkim_domains, + ctx->domain)) != NULL) { + if (!dkim_module_parse_strict (strict_value, &score_allow, + &score_deny)) { score_allow = dkim_module_ctx->strict_multiplier; score_deny = dkim_module_ctx->strict_multiplier; - msg_debug ("no specific score found for %s domain, using %d for it", ctx->domain, score_deny); + msg_debug ( + "no specific score found for %s domain, using %d for it", + ctx->domain, + score_deny); } else { - msg_debug ("specific score found for %s domain: using %d for deny and %d for allow", - ctx->dns_key, score_deny, score_allow); + msg_debug ( + "specific score found for %s domain: using %d for deny and %d for allow", + ctx->dns_key, + score_deny, + score_allow); } } } @@ -273,15 +319,20 @@ dkim_module_check (struct rspamd_task *task, rspamd_dkim_context_t *ctx, rspamd_ } static void -dkim_module_key_handler (rspamd_dkim_key_t *key, gsize keylen, rspamd_dkim_context_t *ctx, gpointer ud, GError *err) +dkim_module_key_handler (rspamd_dkim_key_t *key, + gsize keylen, + rspamd_dkim_context_t *ctx, + gpointer ud, + GError *err) { - struct rspamd_task *task = ud; + struct rspamd_task *task = ud; if (key != NULL) { /* Add new key to the lru cache */ - rspamd_lru_hash_insert (dkim_module_ctx->dkim_hash, g_strdup (ctx->dns_key), - key, task->tv.tv_sec, key->ttl); + rspamd_lru_hash_insert (dkim_module_ctx->dkim_hash, + g_strdup (ctx->dns_key), + key, task->tv.tv_sec, key->ttl); dkim_module_check (task, ctx, key); } else { @@ -289,7 +340,8 @@ dkim_module_key_handler (rspamd_dkim_key_t *key, gsize keylen, rspamd_dkim_conte msg_info ("cannot get key for domain %s", ctx->dns_key); if (err != NULL) { insert_result (task, dkim_module_ctx->symbol_tempfail, 1, - g_list_prepend (NULL, rspamd_mempool_strdup (task->task_pool, err->message))); + g_list_prepend (NULL, + rspamd_mempool_strdup (task->task_pool, err->message))); } else { @@ -305,19 +357,23 @@ dkim_module_key_handler (rspamd_dkim_key_t *key, gsize keylen, rspamd_dkim_conte static void dkim_symbol_callback (struct rspamd_task *task, void *unused) { - GList *hlist; - rspamd_dkim_context_t *ctx; - rspamd_dkim_key_t *key; - GError *err = NULL; + GList *hlist; + rspamd_dkim_context_t *ctx; + rspamd_dkim_key_t *key; + GError *err = NULL; /* First check if a message has its signature */ - hlist = message_get_header (task->task_pool, task->message, DKIM_SIGNHEADER, FALSE); + hlist = message_get_header (task->task_pool, + task->message, + DKIM_SIGNHEADER, + FALSE); if (hlist != NULL) { /* Check whitelist */ msg_debug ("dkim signature found"); if (task->from_addr.af == AF_INET || - radix32tree_find (dkim_module_ctx->whitelist_ip, - ntohl (task->from_addr.addr.s4.sin_addr.s_addr)) == RADIX_NO_VALUE) { + radix32tree_find (dkim_module_ctx->whitelist_ip, + ntohl (task->from_addr.addr.s4.sin_addr.s_addr)) == + RADIX_NO_VALUE) { /* Parse signature */ msg_debug ("create dkim signature"); /* @@ -326,32 +382,45 @@ dkim_symbol_callback (struct rspamd_task *task, void *unused) */ if (dkim_module_ctx->skip_multi) { if (hlist->next != NULL) { - msg_info ("<%s> skip dkim check as it has several dkim signatures", task->message_id); + msg_info ( + "<%s> skip dkim check as it has several dkim signatures", + task->message_id); return; } } hlist = g_list_last (hlist); - ctx = rspamd_create_dkim_context (hlist->data, task->task_pool, dkim_module_ctx->time_jitter, &err); + ctx = rspamd_create_dkim_context (hlist->data, + task->task_pool, + dkim_module_ctx->time_jitter, + &err); if (ctx == NULL) { msg_info ("cannot parse DKIM context: %s", err->message); g_error_free (err); } else { /* Get key */ - if (dkim_module_ctx->trusted_only && (dkim_module_ctx->dkim_domains == NULL || - g_hash_table_lookup (dkim_module_ctx->dkim_domains, ctx->domain) == NULL)) { + if (dkim_module_ctx->trusted_only && + (dkim_module_ctx->dkim_domains == NULL || + g_hash_table_lookup (dkim_module_ctx->dkim_domains, + ctx->domain) == NULL)) { msg_debug ("skip dkim check for %s domain", ctx->domain); return; } - key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_hash, ctx->dns_key, task->tv.tv_sec); + key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_hash, + ctx->dns_key, + task->tv.tv_sec); if (key != NULL) { debug_task ("found key for %s in cache", ctx->dns_key); dkim_module_check (task, ctx, key); } else { debug_task ("request key for %s from DNS", ctx->dns_key); - task->dns_requests ++; - rspamd_get_dkim_key (ctx, task->resolver, task->s, dkim_module_key_handler, task); + task->dns_requests++; + rspamd_get_dkim_key (ctx, + task->resolver, + task->s, + dkim_module_key_handler, + task); } } } diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c index 1ee1013e6..97b253d9c 100644 --- a/src/plugins/fuzzy_check.c +++ b/src/plugins/fuzzy_check.c @@ -29,7 +29,7 @@ * - symbol (string): symbol to insert (default: 'R_FUZZY') * - max_score (double): maximum score to that weights of hashes would be normalized (default: 0 - no normalization) * - * - fuzzy_map (string): a string that contains map in format { fuzzy_key => [ symbol, weight ] } where fuzzy_key is number of + * - fuzzy_map (string): a string that contains map in format { fuzzy_key => [ symbol, weight ] } where fuzzy_key is number of * fuzzy list. This string itself should be in format 1:R_FUZZY_SAMPLE1:10,2:R_FUZZY_SAMPLE2:1 etc, where first number is fuzzy * key, second is symbol to insert and third - weight for normalization * @@ -133,10 +133,12 @@ static const gchar hex_digits[] = "0123456789abcdef"; static void fuzzy_symbol_callback (struct rspamd_task *task, void *unused); /* Initialization */ -gint fuzzy_check_module_init (struct rspamd_config *cfg, struct module_ctx **ctx); +gint fuzzy_check_module_init (struct rspamd_config *cfg, + struct module_ctx **ctx); gint fuzzy_check_module_config (struct rspamd_config *cfg); gint fuzzy_check_module_reconfig (struct rspamd_config *cfg); -static gint fuzzy_attach_controller (struct module_ctx *ctx, GHashTable *commands); +static gint fuzzy_attach_controller (struct module_ctx *ctx, + GHashTable *commands); module_t fuzzy_check_module = { "fuzzy_check", @@ -147,14 +149,17 @@ module_t fuzzy_check_module = { }; static void -parse_flags (struct fuzzy_rule *rule, struct rspamd_config *cfg, const ucl_object_t *val) +parse_flags (struct fuzzy_rule *rule, + struct rspamd_config *cfg, + const ucl_object_t *val) { const ucl_object_t *elt; struct fuzzy_mapping *map; const gchar *sym = NULL; if (val->type == UCL_STRING) { - msg_err ("string mappings are deprecated and no longer supported, use new style configuration"); + msg_err ( + "string mappings are deprecated and no longer supported, use new style configuration"); } else if (val->type == UCL_OBJECT) { elt = ucl_object_find_key (val, "symbol"); @@ -162,7 +167,9 @@ parse_flags (struct fuzzy_rule *rule, struct rspamd_config *cfg, const ucl_objec sym = ucl_object_key (val); } if (sym != NULL) { - map = rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, sizeof (struct fuzzy_mapping)); + map = + rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, + sizeof (struct fuzzy_mapping)); map->symbol = sym; elt = ucl_object_find_key (val, "flag"); if (elt != NULL && ucl_obj_toint_safe (elt, &map->fuzzy_flag)) { @@ -174,7 +181,8 @@ parse_flags (struct fuzzy_rule *rule, struct rspamd_config *cfg, const ucl_objec map->weight = rule->max_score; } /* Add flag to hash table */ - g_hash_table_insert (rule->mappings, GINT_TO_POINTER (map->fuzzy_flag), map); + g_hash_table_insert (rule->mappings, + GINT_TO_POINTER (map->fuzzy_flag), map); register_virtual_symbol (&cfg->cache, map->symbol, 1.0); } else { @@ -193,10 +201,10 @@ parse_flags (struct fuzzy_rule *rule, struct rspamd_config *cfg, const ucl_objec static GList * parse_mime_types (const gchar *str) { - gchar **strvec, *p; - gint num, i; - struct fuzzy_mime_type *type; - GList *res = NULL; + gchar **strvec, *p; + gint num, i; + struct fuzzy_mime_type *type; + GList *res = NULL; strvec = g_strsplit_set (str, ",", 0); num = g_strv_length (strvec); @@ -204,9 +212,13 @@ parse_mime_types (const gchar *str) g_strstrip (strvec[i]); if ((p = strchr (strvec[i], '/')) != NULL) { *p = 0; - type = rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, sizeof (struct fuzzy_mime_type)); - type->type = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, strvec[i]); - type->subtype = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, p + 1); + type = + rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, + sizeof (struct fuzzy_mime_type)); + type->type = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, + strvec[i]); + type->subtype = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, + p + 1); res = g_list_prepend (res, type); } else { @@ -215,7 +227,8 @@ parse_mime_types (const gchar *str) } if (res != NULL) { - rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, (rspamd_mempool_destruct_t)g_list_free, res); + rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, + (rspamd_mempool_destruct_t)g_list_free, res); } return res; @@ -224,8 +237,8 @@ parse_mime_types (const gchar *str) static gboolean fuzzy_check_content_type (struct fuzzy_rule *rule, GMimeContentType *type) { - struct fuzzy_mime_type *ft; - GList *cur; + struct fuzzy_mime_type *ft; + GList *cur; cur = rule->mime_types; while (cur) { @@ -242,24 +255,27 @@ fuzzy_check_content_type (struct fuzzy_rule *rule, GMimeContentType *type) static void parse_servers_string (struct fuzzy_rule *rule, const gchar *str) { - gchar **strvec; - gint i, num; - struct storage_server *cur; + gchar **strvec; + gint i, num; + struct storage_server *cur; strvec = g_strsplit_set (str, ",", 0); num = g_strv_length (strvec); - rule->servers = rspamd_mempool_alloc0 (fuzzy_module_ctx->fuzzy_pool, sizeof (struct storage_server) * num); + rule->servers = rspamd_mempool_alloc0 (fuzzy_module_ctx->fuzzy_pool, + sizeof (struct storage_server) * num); for (i = 0; i < num; i++) { g_strstrip (strvec[i]); cur = &rule->servers[rule->servers_num]; - if (rspamd_parse_host_port (fuzzy_module_ctx->fuzzy_pool, strvec[i], &cur->addr, &cur->port)) { + if (rspamd_parse_host_port (fuzzy_module_ctx->fuzzy_pool, strvec[i], + &cur->addr, &cur->port)) { if (cur->port == 0) { cur->port = DEFAULT_PORT; } - cur->name = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, strvec[i]); + cur->name = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, + strvec[i]); rule->servers_num++; } } @@ -286,10 +302,10 @@ fuzzy_to_string (fuzzy_hash_t *h) { static gchar strbuf [FUZZY_HASHLEN * 2 + 1]; const int max_print = 5; - gint i; + gint i; guint8 byte; - for (i = 0; i < max_print; i ++) { + for (i = 0; i < max_print; i++) { byte = h->hash_pipe[i]; if (byte == '\0') { break; @@ -316,7 +332,9 @@ fuzzy_rule_new (const char *default_symbol, rspamd_mempool_t *pool) rule->mappings = g_hash_table_new (g_direct_hash, g_direct_equal); rule->symbol = default_symbol; - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t)g_hash_table_unref, rule->mappings); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t)g_hash_table_unref, + rule->mappings); rule->read_only = FALSE; return rule; @@ -334,13 +352,15 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj) return -1; } - rule = fuzzy_rule_new (fuzzy_module_ctx->default_symbol, fuzzy_module_ctx->fuzzy_pool); + rule = fuzzy_rule_new (fuzzy_module_ctx->default_symbol, + fuzzy_module_ctx->fuzzy_pool); if ((value = ucl_object_find_key (obj, "mime_types")) != NULL) { if (value->type == UCL_ARRAY) { value = value->value.av; } - LL_FOREACH (value, cur) { + LL_FOREACH (value, cur) + { rule->mime_types = g_list_concat (rule->mime_types, parse_mime_types (ucl_obj_tostring (cur))); } @@ -363,7 +383,8 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj) if (value->type == UCL_ARRAY) { value = value->value.av; } - LL_FOREACH (value, cur) { + LL_FOREACH (value, cur) + { parse_servers_string (rule, ucl_obj_tostring (cur)); } } @@ -374,11 +395,14 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj) } if (rule->servers_num == 0) { - msg_err ("no servers defined for fuzzy rule with symbol: %s", rule->symbol); + msg_err ("no servers defined for fuzzy rule with symbol: %s", + rule->symbol); return -1; } else { - fuzzy_module_ctx->fuzzy_rules = g_list_prepend (fuzzy_module_ctx->fuzzy_rules, rule); + fuzzy_module_ctx->fuzzy_rules = g_list_prepend ( + fuzzy_module_ctx->fuzzy_rules, + rule); if (rule->symbol != fuzzy_module_ctx->default_symbol) { register_virtual_symbol (&cfg->cache, rule->symbol, 1.0); } @@ -392,7 +416,8 @@ fuzzy_check_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) { fuzzy_module_ctx = g_malloc0 (sizeof (struct fuzzy_ctx)); - fuzzy_module_ctx->fuzzy_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + fuzzy_module_ctx->fuzzy_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); fuzzy_module_ctx->cfg = cfg; *ctx = (struct module_ctx *)fuzzy_module_ctx; @@ -403,52 +428,64 @@ fuzzy_check_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) gint fuzzy_check_module_config (struct rspamd_config *cfg) { - const ucl_object_t *value, *cur; - gint res = TRUE; + const ucl_object_t *value, *cur; + gint res = TRUE; - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "symbol")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", "symbol")) != NULL) { fuzzy_module_ctx->default_symbol = ucl_obj_tostring (value); } else { fuzzy_module_ctx->default_symbol = DEFAULT_SYMBOL; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "min_length")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "min_length")) != NULL) { fuzzy_module_ctx->min_hash_len = ucl_obj_toint (value); } else { fuzzy_module_ctx->min_hash_len = 0; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "min_bytes")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "min_bytes")) != NULL) { fuzzy_module_ctx->min_bytes = ucl_obj_toint (value); } else { fuzzy_module_ctx->min_bytes = 0; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "min_height")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "min_height")) != NULL) { fuzzy_module_ctx->min_height = ucl_obj_toint (value); } else { fuzzy_module_ctx->min_height = 0; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "min_width")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "min_width")) != NULL) { fuzzy_module_ctx->min_width = ucl_obj_toint (value); } else { fuzzy_module_ctx->min_width = 0; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "timeout")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", "timeout")) != NULL) { fuzzy_module_ctx->io_timeout = ucl_obj_todouble (value) * 1000; } else { fuzzy_module_ctx->io_timeout = DEFAULT_IO_TIMEOUT; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "whitelist")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "whitelist")) != NULL) { fuzzy_module_ctx->whitelist = radix_tree_create (); if (!add_map (cfg, ucl_obj_tostring (value), - "Fuzzy whitelist", read_radix_list, fin_radix_list, - (void **)&fuzzy_module_ctx->whitelist)) { + "Fuzzy whitelist", read_radix_list, fin_radix_list, + (void **)&fuzzy_module_ctx->whitelist)) { msg_err ("cannot add whitelist '%s'", ucl_obj_tostring (value)); } } @@ -456,8 +493,10 @@ fuzzy_check_module_config (struct rspamd_config *cfg) fuzzy_module_ctx->whitelist = NULL; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "rule")) != NULL) { - LL_FOREACH (value, cur) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", "rule")) != NULL) { + LL_FOREACH (value, cur) + { if (fuzzy_parse_rule (cfg, cur) == -1) { return -1; } @@ -466,7 +505,7 @@ fuzzy_check_module_config (struct rspamd_config *cfg) if (fuzzy_module_ctx->fuzzy_rules != NULL) { register_callback_symbol (&cfg->cache, fuzzy_module_ctx->default_symbol, - 1.0, fuzzy_symbol_callback, NULL); + 1.0, fuzzy_symbol_callback, NULL); } else { msg_warn ("fuzzy module is enabled but no rules are defined"); @@ -480,9 +519,10 @@ fuzzy_check_module_reconfig (struct rspamd_config *cfg) { rspamd_mempool_delete (fuzzy_module_ctx->fuzzy_pool); - fuzzy_module_ctx->fuzzy_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + fuzzy_module_ctx->fuzzy_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); fuzzy_module_ctx->cfg = cfg; - + return fuzzy_check_module_config (cfg); } @@ -490,7 +530,7 @@ fuzzy_check_module_reconfig (struct rspamd_config *cfg) static void fuzzy_io_fin (void *ud) { - struct fuzzy_client_session *session = ud; + struct fuzzy_client_session *session = ud; event_del (&session->ev); close (session->fd); @@ -500,13 +540,13 @@ fuzzy_io_fin (void *ud) static void fuzzy_io_callback (gint fd, short what, void *arg) { - struct fuzzy_client_session *session = arg; - struct fuzzy_cmd cmd; - struct fuzzy_mapping *map; - gchar buf[62], *err_str; - const gchar *symbol; - gint value = 0, flag = 0, r; - double nval; + struct fuzzy_client_session *session = arg; + struct fuzzy_cmd cmd; + struct fuzzy_mapping *map; + gchar buf[62], *err_str; + const gchar *symbol; + gint value = 0, flag = 0, r; + double nval; if (what == EV_WRITE) { /* Send command to storage */ @@ -540,7 +580,9 @@ fuzzy_io_callback (gint fd, short what, void *arg) } *err_str = '\0'; /* Get mapping by flag */ - if ((map = g_hash_table_lookup (session->rule->mappings, GINT_TO_POINTER (flag))) == NULL) { + if ((map = + g_hash_table_lookup (session->rule->mappings, + GINT_TO_POINTER (flag))) == NULL) { /* Default symbol and default weight */ symbol = session->rule->symbol; nval = fuzzy_normalize (value, session->rule->max_score); @@ -550,37 +592,53 @@ fuzzy_io_callback (gint fd, short what, void *arg) symbol = map->symbol; nval = fuzzy_normalize (value, map->weight); } - msg_info ("<%s>, found fuzzy hash '%s' with weight: %.2f, in list: %s:%d%s", - session->task->message_id, fuzzy_to_string (session->h), nval, symbol, - flag, map == NULL ? "(unknown)" : ""); + msg_info ( + "<%s>, found fuzzy hash '%s' with weight: %.2f, in list: %s:%d%s", + session->task->message_id, + fuzzy_to_string (session->h), + nval, + symbol, + flag, + map == NULL ? "(unknown)" : ""); if (map != NULL || !session->rule->skip_unknown) { - rspamd_snprintf (buf, sizeof (buf), "%d: %d / %.2f", flag, value, nval); - insert_result_single (session->task, symbol, nval, g_list_prepend (NULL, - rspamd_mempool_strdup (session->task->task_pool, buf))); + rspamd_snprintf (buf, + sizeof (buf), + "%d: %d / %.2f", + flag, + value, + nval); + insert_result_single (session->task, + symbol, + nval, + g_list_prepend (NULL, + rspamd_mempool_strdup (session->task->task_pool, buf))); } } goto ok; } else { errno = ETIMEDOUT; - goto err; + goto err; } return; - err: - msg_err ("got error on IO with server %s, %d, %s", session->server->name, errno, strerror (errno)); - ok: +err: + msg_err ("got error on IO with server %s, %d, %s", + session->server->name, + errno, + strerror (errno)); +ok: remove_normal_event (session->task->s, fuzzy_io_fin, session); } static void fuzzy_learn_callback (gint fd, short what, void *arg) { - struct fuzzy_learn_session *session = arg; - struct fuzzy_cmd cmd; - gchar buf[512]; - const gchar *cmd_name; + struct fuzzy_learn_session *session = arg; + struct fuzzy_cmd cmd; + gchar buf[512]; + const gchar *cmd_name; cmd_name = (session->cmd == FUZZY_WRITE ? "add" : "delete"); if (what == EV_WRITE) { @@ -593,41 +651,52 @@ fuzzy_learn_callback (gint fd, short what, void *arg) if (write (fd, &cmd, sizeof (struct fuzzy_cmd)) == -1) { if (*(session->err) == NULL) { g_set_error (session->err, - g_quark_from_static_string ("fuzzy check"), - errno, "write socket error: %s", strerror (errno)); + g_quark_from_static_string ("fuzzy check"), + errno, "write socket error: %s", strerror (errno)); } goto err; } else { event_del (&session->ev); - event_set (&session->ev, fd, EV_READ, fuzzy_learn_callback, session); + event_set (&session->ev, fd, EV_READ, fuzzy_learn_callback, + session); event_add (&session->ev, &session->tv); } } else if (what == EV_READ) { if (read (fd, buf, sizeof (buf)) == -1) { - msg_info ("cannot %s fuzzy hash for message <%s>, list %s:%d", cmd_name, - session->task->message_id, session->rule->symbol, session->flag); + msg_info ("cannot %s fuzzy hash for message <%s>, list %s:%d", + cmd_name, + session->task->message_id, + session->rule->symbol, + session->flag); if (*(session->err) == NULL) { g_set_error (session->err, - g_quark_from_static_string ("fuzzy check"), - errno, "read socket error: %s", strerror (errno)); + g_quark_from_static_string ("fuzzy check"), + errno, "read socket error: %s", strerror (errno)); } goto err; } else if (buf[0] == 'O' && buf[1] == 'K') { - msg_info ("%s fuzzy hash '%s', list: %s:%d for message <%s>", cmd_name, - fuzzy_to_string (session->h), session->rule->symbol, - session->flag, session->task->message_id); + msg_info ("%s fuzzy hash '%s', list: %s:%d for message <%s>", + cmd_name, + fuzzy_to_string (session->h), + session->rule->symbol, + session->flag, + session->task->message_id); goto ok; } else { - msg_info ("cannot %s fuzzy hash '%s' for message <%s>, list %s:%d", cmd_name, - fuzzy_to_string (session->h), session->task->message_id, - session->rule->symbol, session->flag); + msg_info ("cannot %s fuzzy hash '%s' for message <%s>, list %s:%d", + cmd_name, + fuzzy_to_string (session->h), + session->task->message_id, + session->rule->symbol, + session->flag); if (*(session->err) == NULL) { g_set_error (session->err, - g_quark_from_static_string ("fuzzy check"), EINVAL, "%s fuzzy error", cmd_name); + g_quark_from_static_string ( + "fuzzy check"), EINVAL, "%s fuzzy error", cmd_name); } goto ok; } @@ -636,16 +705,17 @@ fuzzy_learn_callback (gint fd, short what, void *arg) errno = ETIMEDOUT; if (*(session->err) == NULL) { g_set_error (session->err, - g_quark_from_static_string ("fuzzy check"), EINVAL, "%s fuzzy, IO timeout", cmd_name); + g_quark_from_static_string ( + "fuzzy check"), EINVAL, "%s fuzzy, IO timeout", cmd_name); } - goto err; + goto err; } return; err: msg_err ("got error in IO with server %s, %d, %s", - session->server->name, errno, strerror (errno)); + session->server->name, errno, strerror (errno)); rspamd_http_connection_unref (session->http_entry->conn); rspamd_task_free (session->task, TRUE); event_del (&session->ev); @@ -655,42 +725,63 @@ ok: if (--(*(session->saved)) == 0) { if (*(session->err) != NULL) { rspamd_controller_send_error (session->http_entry, - (*session->err)->code, (*session->err)->message); + (*session->err)->code, (*session->err)->message); g_error_free (*session->err); } else { rspamd_controller_send_string (session->http_entry, - "{\"success\":true}"); + "{\"success\":true}"); } } } static inline void -register_fuzzy_call (struct rspamd_task *task, struct fuzzy_rule *rule, fuzzy_hash_t *h) +register_fuzzy_call (struct rspamd_task *task, + struct fuzzy_rule *rule, + fuzzy_hash_t *h) { - struct fuzzy_client_session *session; - struct storage_server *selected; - gint sock; + struct fuzzy_client_session *session; + struct storage_server *selected; + gint sock; /* Get upstream */ #ifdef HAVE_CLOCK_GETTIME - selected = (struct storage_server *)get_upstream_by_hash (rule->servers, rule->servers_num, - sizeof (struct storage_server), task->ts.tv_sec, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, - h->hash_pipe, sizeof (h->hash_pipe)); + selected = (struct storage_server *)get_upstream_by_hash (rule->servers, + rule->servers_num, + sizeof (struct storage_server), + task->ts.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS, + h->hash_pipe, + sizeof (h->hash_pipe)); #else - selected = (struct storage_server *)get_upstream_by_hash (rule->servers, rule->servers_num, - sizeof (struct storage_server), task->tv.tv_sec, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, h->hash_pipe, sizeof (h->hash_pipe)); + selected = (struct storage_server *)get_upstream_by_hash (rule->servers, + rule->servers_num, + sizeof (struct storage_server), + task->tv.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS, + h->hash_pipe, + sizeof (h->hash_pipe)); #endif if (selected) { - if ((sock = make_universal_socket (selected->addr, selected->port, SOCK_DGRAM, TRUE, FALSE, FALSE)) == -1) { - msg_warn ("cannot connect to %s, %d, %s", selected->name, errno, strerror (errno)); + if ((sock = + make_universal_socket (selected->addr, selected->port, SOCK_DGRAM, + TRUE, FALSE, FALSE)) == -1) { + msg_warn ("cannot connect to %s, %d, %s", + selected->name, + errno, + strerror (errno)); } else { /* Create session for a socket */ - session = rspamd_mempool_alloc (task->task_pool, sizeof (struct fuzzy_client_session)); - event_set (&session->ev, sock, EV_WRITE, fuzzy_io_callback, session); + session = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct fuzzy_client_session)); + event_set (&session->ev, sock, EV_WRITE, fuzzy_io_callback, + session); msec_to_tv (fuzzy_module_ctx->io_timeout, &session->tv); session->state = 0; session->h = h; @@ -699,7 +790,10 @@ register_fuzzy_call (struct rspamd_task *task, struct fuzzy_rule *rule, fuzzy_ha session->server = selected; session->rule = rule; event_add (&session->ev, &session->tv); - register_async_event (task->s, fuzzy_io_fin, session, g_quark_from_static_string ("fuzzy check")); + register_async_event (task->s, + fuzzy_io_fin, + session, + g_quark_from_static_string ("fuzzy check")); } } } @@ -707,13 +801,13 @@ register_fuzzy_call (struct rspamd_task *task, struct fuzzy_rule *rule, fuzzy_ha static void fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) { - struct mime_text_part *part; - struct mime_part *mime_part; - struct rspamd_image *image; - gchar *checksum; - gsize hashlen; - GList *cur; - fuzzy_hash_t *fake_fuzzy; + struct mime_text_part *part; + struct mime_part *mime_part; + struct rspamd_image *image; + gchar *checksum; + gsize hashlen; + GList *cur; + fuzzy_hash_t *fake_fuzzy; cur = task->text_parts; @@ -727,7 +821,7 @@ fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) /* Check length of part */ if (fuzzy_module_ctx->min_bytes > part->content->len) { msg_info ("<%s>, part is shorter than %d symbols, skip fuzzy check", - task->message_id, fuzzy_module_ctx->min_bytes); + task->message_id, fuzzy_module_ctx->min_bytes); cur = g_list_next (cur); continue; } @@ -735,14 +829,17 @@ fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) hashlen = strlen (part->fuzzy->hash_pipe); if (hashlen == 0) { msg_info ("<%s>, part hash empty, skip fuzzy check", - task->message_id, fuzzy_module_ctx->min_hash_len); + task->message_id, fuzzy_module_ctx->min_hash_len); cur = g_list_next (cur); continue; } if (fuzzy_module_ctx->min_hash_len != 0 && - hashlen * part->fuzzy->block_size < fuzzy_module_ctx->min_hash_len) { - msg_info ("<%s>, part hash is shorter than %d symbols, skip fuzzy check", - task->message_id, fuzzy_module_ctx->min_hash_len); + hashlen * part->fuzzy->block_size < + fuzzy_module_ctx->min_hash_len) { + msg_info ( + "<%s>, part hash is shorter than %d symbols, skip fuzzy check", + task->message_id, + fuzzy_module_ctx->min_hash_len); cur = g_list_next (cur); continue; } @@ -757,12 +854,18 @@ fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) while (cur) { image = cur->data; if (image->data->len > 0) { - if (fuzzy_module_ctx->min_height <= 0 || image->height >= fuzzy_module_ctx->min_height) { - if (fuzzy_module_ctx->min_width <= 0 || image->width >= fuzzy_module_ctx->min_width) { - checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, image->data->data, image->data->len); + if (fuzzy_module_ctx->min_height <= 0 || image->height >= + fuzzy_module_ctx->min_height) { + if (fuzzy_module_ctx->min_width <= 0 || image->width >= + fuzzy_module_ctx->min_width) { + checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, + image->data->data, + image->data->len); /* Construct fake fuzzy hash */ - fake_fuzzy = rspamd_mempool_alloc0 (task->task_pool, sizeof (fuzzy_hash_t)); - rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, sizeof (fake_fuzzy->hash_pipe)); + fake_fuzzy = rspamd_mempool_alloc0 (task->task_pool, + sizeof (fuzzy_hash_t)); + rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, + sizeof (fake_fuzzy->hash_pipe)); register_fuzzy_call (task, rule, fake_fuzzy); g_free (checksum); } @@ -774,15 +877,20 @@ fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) cur = task->parts; while (cur) { mime_part = cur->data; - if (mime_part->content->len > 0 && fuzzy_check_content_type (rule, mime_part->type)) { - if (fuzzy_module_ctx->min_bytes <= 0 || mime_part->content->len >= fuzzy_module_ctx->min_bytes) { - checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, - mime_part->content->data, mime_part->content->len); - /* Construct fake fuzzy hash */ - fake_fuzzy = rspamd_mempool_alloc0 (task->task_pool, sizeof (fuzzy_hash_t)); - rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, sizeof (fake_fuzzy->hash_pipe)); - register_fuzzy_call (task, rule, fake_fuzzy); - g_free (checksum); + if (mime_part->content->len > 0 && + fuzzy_check_content_type (rule, mime_part->type)) { + if (fuzzy_module_ctx->min_bytes <= 0 || mime_part->content->len >= + fuzzy_module_ctx->min_bytes) { + checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, + mime_part->content->data, mime_part->content->len); + /* Construct fake fuzzy hash */ + fake_fuzzy = + rspamd_mempool_alloc0 (task->task_pool, + sizeof (fuzzy_hash_t)); + rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, + sizeof (fake_fuzzy->hash_pipe)); + register_fuzzy_call (task, rule, fake_fuzzy); + g_free (checksum); } } cur = g_list_next (cur); @@ -799,9 +907,11 @@ fuzzy_symbol_callback (struct rspamd_task *task, void *unused) /* Check whitelist */ if (fuzzy_module_ctx->whitelist && task->from_addr.af == AF_INET) { if (radix32tree_find (fuzzy_module_ctx->whitelist, - ntohl (task->from_addr.addr.s4.sin_addr.s_addr)) != RADIX_NO_VALUE) { + ntohl (task->from_addr.addr.s4.sin_addr.s_addr)) != + RADIX_NO_VALUE) { msg_info ("<%s>, address %s is whitelisted, skip fuzzy check", - task->message_id, rspamd_inet_address_to_string (&task->from_addr)); + task->message_id, + rspamd_inet_address_to_string (&task->from_addr)); return; } } @@ -816,41 +926,54 @@ fuzzy_symbol_callback (struct rspamd_task *task, void *unused) static inline gboolean register_fuzzy_controller_call (struct rspamd_http_connection_entry *entry, - struct fuzzy_rule *rule, struct rspamd_task *task, fuzzy_hash_t *h, - gint cmd, gint value, gint flag, gint *saved, GError **err) + struct fuzzy_rule *rule, struct rspamd_task *task, fuzzy_hash_t *h, + gint cmd, gint value, gint flag, gint *saved, GError **err) { - struct fuzzy_learn_session *s; - struct storage_server *selected; - gint sock; + struct fuzzy_learn_session *s; + struct storage_server *selected; + gint sock; /* Get upstream */ #ifdef HAVE_CLOCK_GETTIME - selected = (struct storage_server *)get_upstream_by_hash (rule->servers, rule->servers_num, - sizeof (struct storage_server), task->ts.tv_sec, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, - h->hash_pipe, sizeof (h->hash_pipe)); + selected = (struct storage_server *)get_upstream_by_hash (rule->servers, + rule->servers_num, + sizeof (struct storage_server), + task->ts.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS, + h->hash_pipe, + sizeof (h->hash_pipe)); #else - selected = (struct storage_server *)get_upstream_by_hash (rule->servers, rule->servers_num, - sizeof (struct storage_server), task->tv.tv_sec, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, - h->hash_pipe, sizeof (h->hash_pipe)); + selected = (struct storage_server *)get_upstream_by_hash (rule->servers, + rule->servers_num, + sizeof (struct storage_server), + task->tv.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS, + h->hash_pipe, + sizeof (h->hash_pipe)); #endif if (selected) { /* Create UDP socket */ if ((sock = make_universal_socket (selected->addr, selected->port, - SOCK_DGRAM, TRUE, FALSE, FALSE)) == -1) { + SOCK_DGRAM, TRUE, FALSE, FALSE)) == -1) { return FALSE; } else { /* Socket is made, create session */ - s = rspamd_mempool_alloc (task->task_pool, sizeof (struct fuzzy_learn_session)); + s = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct fuzzy_learn_session)); event_set (&s->ev, sock, EV_WRITE, fuzzy_learn_callback, s); event_base_set (entry->rt->ev_base, &s->ev); msec_to_tv (fuzzy_module_ctx->io_timeout, &s->tv); s->task = task; - s->h = rspamd_mempool_alloc (task->task_pool, sizeof (fuzzy_hash_t)); + s->h = + rspamd_mempool_alloc (task->task_pool, sizeof (fuzzy_hash_t)); memcpy (s->h, h, sizeof (fuzzy_hash_t)); - s->http_entry =entry; + s->http_entry = entry; s->server = selected; s->cmd = cmd; s->value = value; @@ -871,38 +994,46 @@ register_fuzzy_controller_call (struct rspamd_http_connection_entry *entry, } static int -fuzzy_process_rule (struct rspamd_http_connection_entry *entry, struct fuzzy_rule *rule, - struct rspamd_task *task, GError **err, gint cmd, gint flag, gint value, gint *saved) +fuzzy_process_rule (struct rspamd_http_connection_entry *entry, + struct fuzzy_rule *rule, + struct rspamd_task *task, + GError **err, + gint cmd, + gint flag, + gint value, + gint *saved) { - struct mime_text_part *part; - struct mime_part *mime_part; - struct rspamd_image *image; - GList *cur; - gchar *checksum; - fuzzy_hash_t fake_fuzzy; - gint processed = 0; + struct mime_text_part *part; + struct mime_part *mime_part; + struct rspamd_image *image; + GList *cur; + gchar *checksum; + fuzzy_hash_t fake_fuzzy; + gint processed = 0; /* Plan new event for writing */ cur = task->text_parts; while (cur) { part = cur->data; - if (part->is_empty || part->fuzzy == NULL || part->fuzzy->hash_pipe[0] == '\0' || - (fuzzy_module_ctx->min_bytes > 0 && part->content->len < fuzzy_module_ctx->min_bytes)) { + if (part->is_empty || part->fuzzy == NULL || + part->fuzzy->hash_pipe[0] == '\0' || + (fuzzy_module_ctx->min_bytes > 0 && part->content->len < + fuzzy_module_ctx->min_bytes)) { /* Skip empty parts */ cur = g_list_next (cur); continue; } - if (! register_fuzzy_controller_call (entry, rule, task, - part->fuzzy, cmd, value, flag, saved, err)) { + if (!register_fuzzy_controller_call (entry, rule, task, + part->fuzzy, cmd, value, flag, saved, err)) { goto err; } - if (! register_fuzzy_controller_call (entry, rule, task, - part->double_fuzzy, cmd, value, flag, saved, err)) { + if (!register_fuzzy_controller_call (entry, rule, task, + part->double_fuzzy, cmd, value, flag, saved, err)) { /* Cannot write hash */ goto err; } - processed ++; + processed++; cur = g_list_next (cur); } @@ -911,22 +1042,30 @@ fuzzy_process_rule (struct rspamd_http_connection_entry *entry, struct fuzzy_rul while (cur) { image = cur->data; if (image->data->len > 0) { - if (fuzzy_module_ctx->min_height <= 0 || image->height >= fuzzy_module_ctx->min_height) { - if (fuzzy_module_ctx->min_width <= 0 || image->width >= fuzzy_module_ctx->min_width) { - checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, image->data->data, image->data->len); + if (fuzzy_module_ctx->min_height <= 0 || image->height >= + fuzzy_module_ctx->min_height) { + if (fuzzy_module_ctx->min_width <= 0 || image->width >= + fuzzy_module_ctx->min_width) { + checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, + image->data->data, + image->data->len); /* Construct fake fuzzy hash */ fake_fuzzy.block_size = 0; - memset (fake_fuzzy.hash_pipe, 0, sizeof (fake_fuzzy.hash_pipe)); - rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, sizeof (fake_fuzzy.hash_pipe)); - if (! register_fuzzy_controller_call (entry, rule, task, - &fake_fuzzy, cmd, value, flag, saved, err)) { + memset (fake_fuzzy.hash_pipe, 0, + sizeof (fake_fuzzy.hash_pipe)); + rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, + sizeof (fake_fuzzy.hash_pipe)); + if (!register_fuzzy_controller_call (entry, rule, task, + &fake_fuzzy, cmd, value, flag, saved, err)) { g_free (checksum); goto err; } - msg_info ("save hash of image: [%s] to list: %d", checksum, flag); + msg_info ("save hash of image: [%s] to list: %d", + checksum, + flag); g_free (checksum); - processed ++; + processed++; } } } @@ -936,23 +1075,26 @@ fuzzy_process_rule (struct rspamd_http_connection_entry *entry, struct fuzzy_rul cur = task->parts; while (cur) { mime_part = cur->data; - if (mime_part->content->len > 0 && fuzzy_check_content_type (rule, mime_part->type)) { - if (fuzzy_module_ctx->min_bytes <= 0 || mime_part->content->len >= fuzzy_module_ctx->min_bytes) { + if (mime_part->content->len > 0 && + fuzzy_check_content_type (rule, mime_part->type)) { + if (fuzzy_module_ctx->min_bytes <= 0 || mime_part->content->len >= + fuzzy_module_ctx->min_bytes) { checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, mime_part->content->data, mime_part->content->len); /* Construct fake fuzzy hash */ fake_fuzzy.block_size = 0; memset (fake_fuzzy.hash_pipe, 0, sizeof (fake_fuzzy.hash_pipe)); - rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, sizeof (fake_fuzzy.hash_pipe)); - if (! register_fuzzy_controller_call (entry, rule, task, - &fake_fuzzy, cmd, value, flag, saved, err)) { + rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, + sizeof (fake_fuzzy.hash_pipe)); + if (!register_fuzzy_controller_call (entry, rule, task, + &fake_fuzzy, cmd, value, flag, saved, err)) { goto err; } msg_info ("save hash of part of type: %s/%s: [%s] to list %d", - mime_part->type->type, mime_part->type->subtype, - checksum, flag); + mime_part->type->type, mime_part->type->subtype, + checksum, flag); g_free (checksum); - processed ++; + processed++; } } cur = g_list_next (cur); @@ -967,8 +1109,8 @@ err: static void fuzzy_process_handler (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, gint cmd, gint value, gint flag, - struct fuzzy_ctx *ctx) + struct rspamd_http_message *msg, gint cmd, gint value, gint flag, + struct fuzzy_ctx *ctx) { struct fuzzy_rule *rule; gboolean processed = FALSE, res = TRUE; @@ -990,7 +1132,8 @@ fuzzy_process_handler (struct rspamd_http_connection_entry *conn_ent, if (r == -1) { msg_warn ("cannot process message for fuzzy"); rspamd_task_free (task, FALSE); - rspamd_controller_send_error (conn_ent, 400, "Message processing error"); + rspamd_controller_send_error (conn_ent, 400, + "Message processing error"); return; } cur = fuzzy_module_ctx->fuzzy_rules; @@ -1003,7 +1146,8 @@ fuzzy_process_handler (struct rspamd_http_connection_entry *conn_ent, } /* Check for flag */ - if (g_hash_table_lookup (rule->mappings, GINT_TO_POINTER (flag)) == NULL) { + if (g_hash_table_lookup (rule->mappings, + GINT_TO_POINTER (flag)) == NULL) { cur = g_list_next (cur); continue; } @@ -1039,11 +1183,11 @@ fuzzy_process_handler (struct rspamd_http_connection_entry *conn_ent, static gboolean fuzzy_controller_handler (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, struct module_ctx *ctx, gint cmd) + struct rspamd_http_message *msg, struct module_ctx *ctx, gint cmd) { const gchar *arg; gchar *err_str; - gint value = 1, flag = 0; + gint value = 1, flag = 0; /* Get size */ arg = rspamd_http_message_find_header (msg, "Value"); @@ -1066,25 +1210,25 @@ fuzzy_controller_handler (struct rspamd_http_connection_entry *conn_ent, } fuzzy_process_handler (conn_ent, msg, cmd, value, flag, - (struct fuzzy_ctx *)ctx); + (struct fuzzy_ctx *)ctx); return 0; } static gboolean fuzzy_add_handler (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, struct module_ctx *ctx) + struct rspamd_http_message *msg, struct module_ctx *ctx) { return fuzzy_controller_handler (conn_ent, msg, - ctx, FUZZY_WRITE); + ctx, FUZZY_WRITE); } static gboolean fuzzy_delete_handler (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, struct module_ctx *ctx) + struct rspamd_http_message *msg, struct module_ctx *ctx) { return fuzzy_controller_handler (conn_ent, msg, - ctx, FUZZY_DEL); + ctx, FUZZY_DEL); } static int diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index bddde5383..31d4943fd 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -40,62 +40,82 @@ #define DEFAULT_STATFILE_PREFIX "./" struct regexp_module_item { - struct expression *expr; - const gchar *symbol; - guint32 avg_time; - gpointer lua_function; + struct expression *expr; + const gchar *symbol; + guint32 avg_time; + gpointer lua_function; }; struct autolearn_data { - gchar *statfile_name; - gchar *symbol; - float weight; + gchar *statfile_name; + gchar *symbol; + float weight; }; struct regexp_ctx { - gint (*filter) (struct rspamd_task * task); - GHashTable *autolearn_symbols; - gchar *statfile_prefix; - - rspamd_mempool_t *regexp_pool; - rspamd_mempool_t *dynamic_pool; - gsize max_size; - gsize max_threads; - GThreadPool *workers; + gint (*filter) (struct rspamd_task * task); + GHashTable *autolearn_symbols; + gchar *statfile_prefix; + + rspamd_mempool_t *regexp_pool; + rspamd_mempool_t *dynamic_pool; + gsize max_size; + gsize max_threads; + GThreadPool *workers; }; struct regexp_json_buf { - gchar *buf; - gchar *pos; - size_t buflen; - struct rspamd_config *cfg; + gchar *buf; + gchar *pos; + size_t buflen; + struct rspamd_config *cfg; }; /* Lua regexp module for checking rspamd regexps */ LUA_FUNCTION_DEF (regexp, match); -static const struct luaL_reg regexplib_m[] = { +static const struct luaL_reg regexplib_m[] = { LUA_INTERFACE_DEF (regexp, match), {"__tostring", lua_class_tostring}, {NULL, NULL} }; -static struct regexp_ctx *regexp_module_ctx = NULL; -static GMutex *workers_mtx = NULL; - -static gint regexp_common_filter (struct rspamd_task *task); -static void process_regexp_item_threaded (gpointer data, gpointer user_data); -static gboolean rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_raw_header_exists (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unused); -static gboolean rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *unused); -static gboolean rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void *unused); -static gboolean rspamd_has_content_part (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_has_content_part_len (struct rspamd_task *task, GList * args, void *unused); -static void process_regexp_item (struct rspamd_task *task, void *user_data); +static struct regexp_ctx *regexp_module_ctx = NULL; +static GMutex *workers_mtx = NULL; + +static gint regexp_common_filter (struct rspamd_task *task); +static void process_regexp_item_threaded (gpointer data, gpointer user_data); +static gboolean rspamd_regexp_match_number (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_raw_header_exists (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_check_smtp_data (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_regexp_occurs_number (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_content_type_is_type (struct rspamd_task * task, + GList * args, + void *unused); +static gboolean rspamd_content_type_is_subtype (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_content_type_has_param (struct rspamd_task * task, + GList * args, + void *unused); +static gboolean rspamd_content_type_compare_param (struct rspamd_task * task, + GList * args, + void *unused); +static gboolean rspamd_has_content_part (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_has_content_part_len (struct rspamd_task *task, + GList * args, + void *unused); +static void process_regexp_item (struct rspamd_task *task, void *user_data); /* Initialization */ @@ -113,13 +133,15 @@ module_t regexp_module = { /* Task cache functions */ #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) -static GStaticMutex task_cache_mtx = G_STATIC_MUTEX_INIT; +static GStaticMutex task_cache_mtx = G_STATIC_MUTEX_INIT; #else G_LOCK_DEFINE (task_cache_mtx); #endif void -task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 result) +task_cache_add (struct rspamd_task *task, + struct rspamd_regexp *re, + gint32 result) { if (result == 0) { result = -1; @@ -130,7 +152,8 @@ task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 resul #else G_LOCK (task_cache_mtx); #endif - g_hash_table_insert (task->re_cache, re->regexp_text, GINT_TO_POINTER (result)); + g_hash_table_insert (task->re_cache, re->regexp_text, + GINT_TO_POINTER (result)); #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) g_static_mutex_unlock (&task_cache_mtx); #else @@ -141,8 +164,8 @@ task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 resul gint32 task_cache_check (struct rspamd_task *task, struct rspamd_regexp *re) { - gpointer res; - gint32 r; + gpointer res; + gint32 r; #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) g_static_mutex_lock (&task_cache_mtx); @@ -178,11 +201,11 @@ luaopen_regexp (lua_State * L) return 1; } -static void +static void regexp_dynamic_insert_result (struct rspamd_task *task, void *user_data) { - gchar *symbol = user_data; - + gchar *symbol = user_data; + insert_result (task, symbol, 1, NULL); } @@ -222,18 +245,18 @@ op_less_equal (gint a, gint b) static gboolean parse_regexp_ipmask (const gchar *begin, struct dynamic_map_item *addr) { - const gchar *pos; - gchar ip_buf[sizeof ("255.255.255.255")], mask_buf[3], *p; - gint state = 0, dots = 0; - - bzero (ip_buf, sizeof (ip_buf)); + const gchar *pos; + gchar ip_buf[sizeof ("255.255.255.255")], mask_buf[3], *p; + gint state = 0, dots = 0; + + bzero (ip_buf, sizeof (ip_buf)); bzero (mask_buf, sizeof (mask_buf)); pos = begin; p = ip_buf; if (*pos == '!') { addr->negative = TRUE; - pos ++; + pos++; } else { addr->negative = FALSE; @@ -241,45 +264,45 @@ parse_regexp_ipmask (const gchar *begin, struct dynamic_map_item *addr) while (*pos) { switch (state) { - case 0: - state = 1; - p = ip_buf; - dots = 0; - break; - case 1: - /* Begin parse ip */ - if (p - ip_buf >= (gint)sizeof (ip_buf) || dots > 3) { - return FALSE; - } - if (g_ascii_isdigit (*pos)) { - *p ++ = *pos ++; - } - else if (*pos == '.') { - *p ++ = *pos ++; - dots ++; - } - else if (*pos == '/') { - pos ++; - p = mask_buf; - state = 2; - } - else { - /* Invalid character */ - return FALSE; - } - break; - case 2: - /* Parse mask */ - if (p - mask_buf > 2) { - return FALSE; - } - if (g_ascii_isdigit (*pos)) { - *p ++ = *pos ++; - } - else { - return FALSE; - } - break; + case 0: + state = 1; + p = ip_buf; + dots = 0; + break; + case 1: + /* Begin parse ip */ + if (p - ip_buf >= (gint)sizeof (ip_buf) || dots > 3) { + return FALSE; + } + if (g_ascii_isdigit (*pos)) { + *p++ = *pos++; + } + else if (*pos == '.') { + *p++ = *pos++; + dots++; + } + else if (*pos == '/') { + pos++; + p = mask_buf; + state = 2; + } + else { + /* Invalid character */ + return FALSE; + } + break; + case 2: + /* Parse mask */ + if (p - mask_buf > 2) { + return FALSE; + } + if (g_ascii_isdigit (*pos)) { + *p++ = *pos++; + } + else { + return FALSE; + } + break; } } @@ -303,11 +326,14 @@ parse_regexp_ipmask (const gchar *begin, struct dynamic_map_item *addr) } /* Process regexp expression */ -static gboolean -read_regexp_expression (rspamd_mempool_t * pool, struct regexp_module_item *chain, - const gchar *symbol, const gchar *line, gboolean raw_mode) +static gboolean +read_regexp_expression (rspamd_mempool_t * pool, + struct regexp_module_item *chain, + const gchar *symbol, + const gchar *line, + gboolean raw_mode) { - struct expression *e, *cur; + struct expression *e, *cur; e = parse_expression (pool, (gchar *)line); if (e == NULL) { @@ -318,9 +344,13 @@ read_regexp_expression (rspamd_mempool_t * pool, struct regexp_module_item *chai cur = e; while (cur) { if (cur->type == EXPR_REGEXP) { - cur->content.operand = parse_regexp (pool, cur->content.operand, raw_mode); + cur->content.operand = parse_regexp (pool, + cur->content.operand, + raw_mode); if (cur->content.operand == NULL) { - msg_warn ("cannot parse regexp, skip expression %s = \"%s\"", symbol, line); + msg_warn ("cannot parse regexp, skip expression %s = \"%s\"", + symbol, + line); return FALSE; } cur->type = EXPR_REGEXP_PARSED; @@ -333,11 +363,14 @@ read_regexp_expression (rspamd_mempool_t * pool, struct regexp_module_item *chai /* Callbacks for reading json dynamic rules */ -gchar * -json_regexp_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +gchar * +json_regexp_read_cb (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { - struct regexp_json_buf *jb; - gint free, off; + struct regexp_json_buf *jb; + gint free, off; if (data->cur_data == NULL) { jb = g_malloc (sizeof (struct regexp_json_buf)); @@ -376,16 +409,16 @@ json_regexp_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct ma void json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) { - struct regexp_json_buf *jb; - guint nelts, i, j; - json_t *js, *cur_elt, *cur_nm, *it_val; - json_error_t je; - gchar *cur_rule, *cur_symbol; - double score; - struct regexp_module_item *cur_item; - GList *cur_networks = NULL; - struct dynamic_map_item *cur_nitem; - rspamd_mempool_t *new_pool; + struct regexp_json_buf *jb; + guint nelts, i, j; + json_t *js, *cur_elt, *cur_nm, *it_val; + json_error_t je; + gchar *cur_rule, *cur_symbol; + double score; + struct regexp_module_item *cur_item; + GList *cur_networks = NULL; + struct dynamic_map_item *cur_nitem; + rspamd_mempool_t *new_pool; if (data->prev_data) { jb = data->prev_data; @@ -413,7 +446,9 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) js = json_loads (jb->buf, &je); if (!js) { - msg_err ("cannot load json data: parse error %s, on line %d", je.text, je.line); + msg_err ("cannot load json data: parse error %s, on line %d", + je.text, + je.line); return; } @@ -422,9 +457,9 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) msg_err ("loaded json is not an array"); return; } - + new_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); - + remove_dynamic_rules (jb->cfg->cache); if (regexp_module_ctx->dynamic_pool != NULL) { rspamd_mempool_delete (regexp_module_ctx->dynamic_pool); @@ -447,14 +482,15 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) msg_err ("factor is not a number or not exists, but is required"); continue; } - score = json_number_value (cur_nm); + score = json_number_value (cur_nm); /* Symbol param */ cur_nm = json_object_get (cur_elt, "symbol"); if (cur_nm == NULL || !json_is_string (cur_nm)) { msg_err ("symbol is not a string or not exists, but is required"); continue; } - cur_symbol = rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); + cur_symbol = + rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); /* Enabled flag */ cur_nm = json_object_get (cur_elt, "enabled"); if (cur_nm != NULL && json_is_boolean (cur_nm)) { @@ -467,7 +503,8 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) /* Rule */ cur_nm = json_object_get (cur_elt, "rule"); if (cur_nm != NULL && json_is_string (cur_nm)) { - cur_rule = rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); + cur_rule = + rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); } /* Networks array */ cur_nm = json_object_get (cur_elt, "networks"); @@ -475,8 +512,11 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) for (j = 0; j < json_array_size (cur_nm); j++) { it_val = json_array_get (cur_nm, i); if (it_val && json_is_string (it_val)) { - cur_nitem = rspamd_mempool_alloc (new_pool, sizeof (struct dynamic_map_item)); - if (parse_regexp_ipmask (json_string_value (it_val), cur_nitem)) { + cur_nitem = + rspamd_mempool_alloc (new_pool, + sizeof (struct dynamic_map_item)); + if (parse_regexp_ipmask (json_string_value (it_val), + cur_nitem)) { cur_networks = g_list_prepend (cur_networks, cur_nitem); } } @@ -484,10 +524,19 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) } if (cur_rule) { /* Dynamic rule has rule option */ - cur_item = rspamd_mempool_alloc0 (new_pool, sizeof (struct regexp_module_item)); + cur_item = + rspamd_mempool_alloc0 (new_pool, + sizeof (struct regexp_module_item)); cur_item->symbol = cur_symbol; - if (read_regexp_expression (new_pool, cur_item, cur_symbol, cur_rule, jb->cfg->raw_mode)) { - register_dynamic_symbol (new_pool, &jb->cfg->cache, cur_symbol, score, process_regexp_item, cur_item, cur_networks); + if (read_regexp_expression (new_pool, cur_item, cur_symbol, + cur_rule, jb->cfg->raw_mode)) { + register_dynamic_symbol (new_pool, + &jb->cfg->cache, + cur_symbol, + score, + process_regexp_item, + cur_item, + cur_networks); } else { msg_warn ("cannot parse dynamic rule"); @@ -495,7 +544,13 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) } else { /* Just rule that is allways true (for whitelisting for example) */ - register_dynamic_symbol (new_pool, &jb->cfg->cache, cur_symbol, score, regexp_dynamic_insert_result, cur_symbol, cur_networks); + register_dynamic_symbol (new_pool, + &jb->cfg->cache, + cur_symbol, + score, + regexp_dynamic_insert_result, + cur_symbol, + cur_networks); } if (cur_networks) { g_list_free (cur_networks); @@ -510,22 +565,44 @@ regexp_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) { regexp_module_ctx = g_malloc (sizeof (struct regexp_ctx)); - regexp_module_ctx->regexp_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + regexp_module_ctx->regexp_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); regexp_module_ctx->dynamic_pool = NULL; - regexp_module_ctx->autolearn_symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); + regexp_module_ctx->autolearn_symbols = g_hash_table_new (rspamd_str_hash, + rspamd_str_equal); regexp_module_ctx->workers = NULL; *ctx = (struct module_ctx *)regexp_module_ctx; - register_expression_function ("regexp_match_number", rspamd_regexp_match_number, NULL); - register_expression_function ("regexp_occurs_number", rspamd_regexp_occurs_number, NULL); - register_expression_function ("raw_header_exists", rspamd_raw_header_exists, NULL); - register_expression_function ("check_smtp_data", rspamd_check_smtp_data, NULL); - register_expression_function ("content_type_is_type", rspamd_content_type_is_type, NULL); - register_expression_function ("content_type_is_subtype", rspamd_content_type_is_subtype, NULL); - register_expression_function ("content_type_has_param", rspamd_content_type_has_param, NULL); - register_expression_function ("content_type_compare_param", rspamd_content_type_compare_param, NULL); - register_expression_function ("has_content_part", rspamd_has_content_part, NULL); - register_expression_function ("has_content_part_len", rspamd_has_content_part_len, NULL); + register_expression_function ("regexp_match_number", + rspamd_regexp_match_number, + NULL); + register_expression_function ("regexp_occurs_number", + rspamd_regexp_occurs_number, + NULL); + register_expression_function ("raw_header_exists", + rspamd_raw_header_exists, + NULL); + register_expression_function ("check_smtp_data", + rspamd_check_smtp_data, + NULL); + register_expression_function ("content_type_is_type", + rspamd_content_type_is_type, + NULL); + register_expression_function ("content_type_is_subtype", + rspamd_content_type_is_subtype, + NULL); + register_expression_function ("content_type_has_param", + rspamd_content_type_has_param, + NULL); + register_expression_function ("content_type_compare_param", + rspamd_content_type_compare_param, + NULL); + register_expression_function ("has_content_part", + rspamd_has_content_part, + NULL); + register_expression_function ("has_content_part_len", + rspamd_has_content_part_len, + NULL); (void)luaopen_regexp (cfg->lua_state); @@ -533,18 +610,22 @@ regexp_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) } -/* +/* * Parse string in format: * SYMBOL:statfile:weight */ void -parse_autolearn_param (const gchar *param, const gchar *value, struct rspamd_config *cfg) +parse_autolearn_param (const gchar *param, + const gchar *value, + struct rspamd_config *cfg) { - struct autolearn_data *d; - gchar *p; + struct autolearn_data *d; + gchar *p; p = rspamd_mempool_strdup (regexp_module_ctx->regexp_pool, value); - d = rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, sizeof (struct autolearn_data)); + d = + rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, + sizeof (struct autolearn_data)); d->symbol = strsep (&p, ":"); if (d->symbol) { @@ -552,7 +633,9 @@ parse_autolearn_param (const gchar *param, const gchar *value, struct rspamd_con if (d->statfile_name) { if (p != NULL && *p != '\0') { d->weight = strtod (p, NULL); - g_hash_table_insert (regexp_module_ctx->autolearn_symbols, d->symbol, d); + g_hash_table_insert (regexp_module_ctx->autolearn_symbols, + d->symbol, + d); } } else { @@ -567,11 +650,11 @@ parse_autolearn_param (const gchar *param, const gchar *value, struct rspamd_con gint regexp_module_config (struct rspamd_config *cfg) { - struct regexp_module_item *cur_item; - const ucl_object_t *sec, *value; - ucl_object_iter_t it = NULL; - gint res = TRUE; - struct regexp_json_buf *jb, **pjb; + struct regexp_module_item *cur_item; + const ucl_object_t *sec, *value; + ucl_object_iter_t it = NULL; + gint res = TRUE; + struct regexp_json_buf *jb, **pjb; sec = ucl_object_find_key (cfg->rcl_obj, "regexp"); @@ -585,44 +668,61 @@ regexp_module_config (struct rspamd_config *cfg) regexp_module_ctx->workers = NULL; while ((value = ucl_iterate_object (sec, &it, true)) != NULL) { - if (g_ascii_strncasecmp (ucl_object_key (value), "autolearn", sizeof ("autolearn") - 1) == 0) { - parse_autolearn_param (ucl_object_key (value), ucl_obj_tostring (value), cfg); + if (g_ascii_strncasecmp (ucl_object_key (value), "autolearn", + sizeof ("autolearn") - 1) == 0) { + parse_autolearn_param (ucl_object_key (value), + ucl_obj_tostring (value), cfg); } - else if (g_ascii_strncasecmp (ucl_object_key (value), "dynamic_rules", sizeof ("dynamic_rules") - 1) == 0) { + else if (g_ascii_strncasecmp (ucl_object_key (value), "dynamic_rules", + sizeof ("dynamic_rules") - 1) == 0) { jb = g_malloc (sizeof (struct regexp_json_buf)); pjb = g_malloc (sizeof (struct regexp_json_buf *)); jb->buf = NULL; jb->cfg = cfg; *pjb = jb; if (!add_map (cfg, ucl_obj_tostring (value), - "Dynamic regexp rules", json_regexp_read_cb, json_regexp_fin_cb, - (void **)pjb)) { + "Dynamic regexp rules", json_regexp_read_cb, json_regexp_fin_cb, + (void **)pjb)) { msg_err ("cannot add map %s", ucl_obj_tostring (value)); } } - else if (g_ascii_strncasecmp (ucl_object_key (value), "max_size", sizeof ("max_size") - 1) == 0) { + else if (g_ascii_strncasecmp (ucl_object_key (value), "max_size", + sizeof ("max_size") - 1) == 0) { regexp_module_ctx->max_size = ucl_obj_toint (value); } - else if (g_ascii_strncasecmp (ucl_object_key (value), "max_threads", sizeof ("max_threads") - 1) == 0) { + else if (g_ascii_strncasecmp (ucl_object_key (value), "max_threads", + sizeof ("max_threads") - 1) == 0) { regexp_module_ctx->max_threads = ucl_obj_toint (value); } else if (value->type == UCL_STRING) { - cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); + cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, + sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); - if (!read_regexp_expression (regexp_module_ctx->regexp_pool, cur_item, ucl_object_key (value), - ucl_obj_tostring (value), cfg->raw_mode)) { + if (!read_regexp_expression (regexp_module_ctx->regexp_pool, + cur_item, ucl_object_key (value), + ucl_obj_tostring (value), cfg->raw_mode)) { res = FALSE; } - register_symbol (&cfg->cache, cur_item->symbol, 1, process_regexp_item, cur_item); + register_symbol (&cfg->cache, + cur_item->symbol, + 1, + process_regexp_item, + cur_item); } else if (value->type == UCL_USERDATA) { - cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); + cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, + sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); cur_item->lua_function = value->value.ud; - register_symbol (&cfg->cache, cur_item->symbol, 1, process_regexp_item, cur_item); + register_symbol (&cfg->cache, + cur_item->symbol, + 1, + process_regexp_item, + cur_item); } else { - msg_warn ("unknown type of attribute %s for regexp module", ucl_object_key (value)); + msg_warn ("unknown type of attribute %s for regexp module", + ucl_object_key (value)); } } @@ -633,63 +733,72 @@ gint regexp_module_reconfig (struct rspamd_config *cfg) { rspamd_mempool_delete (regexp_module_ctx->regexp_pool); - regexp_module_ctx->regexp_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + regexp_module_ctx->regexp_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); return regexp_module_config (cfg); } struct url_regexp_param { - struct rspamd_task *task; - GRegex *regexp; - struct rspamd_regexp *re; - gboolean found; + struct rspamd_task *task; + GRegex *regexp; + struct rspamd_regexp *re; + gboolean found; }; -static gboolean +static gboolean tree_url_callback (gpointer key, gpointer value, void *data) { - struct url_regexp_param *param = data; - struct uri *url = value; - GError *err = NULL; + struct url_regexp_param *param = data; + struct uri *url = value; + GError *err = NULL; - if (g_regex_match_full (param->regexp, struri (url), -1, 0, 0, NULL, &err) == TRUE) { + if (g_regex_match_full (param->regexp, struri (url), -1, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (param->re->is_test)) { - msg_info ("process test regexp %s for url %s returned TRUE", struri (url)); + msg_info ("process test regexp %s for url %s returned TRUE", + struri (url)); } task_cache_add (param->task, param->re, 1); param->found = TRUE; return TRUE; } else if (G_UNLIKELY (param->re->is_test)) { - msg_info ("process test regexp %s for url %s returned FALSE", struri (url)); + msg_info ("process test regexp %s for url %s returned FALSE", + struri (url)); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", param->re->regexp_text, err->message); + msg_info ("error occured while processing regexp \"%s\": %s", + param->re->regexp_text, + err->message); } return FALSE; } -static gsize -process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar *additional, - gint limit, int_compare_func f) +static gsize +process_regexp (struct rspamd_regexp *re, + struct rspamd_task *task, + const gchar *additional, + gint limit, + int_compare_func f) { - guint8 *ct; - gsize clen; - gint r, passed = 0, start, end, old; - gboolean matched = FALSE; - - GList *cur, *headerlist; - GRegex *regexp; - GMatchInfo *info; - GError *err = NULL; - struct url_regexp_param callback_param = { + guint8 *ct; + gsize clen; + gint r, passed = 0, start, end, old; + gboolean matched = FALSE; + + GList *cur, *headerlist; + GRegex *regexp; + GMatchInfo *info; + GError *err = NULL; + struct url_regexp_param callback_param = { .task = task, .re = re, .found = FALSE }; - struct mime_text_part *part; - struct raw_header *rh; + struct mime_text_part *part; + struct raw_header *rh; if (re == NULL) { msg_info ("invalid regexp passed"); @@ -698,16 +807,21 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar callback_param.regexp = re->regexp; if ((r = task_cache_check (task, re)) != -1) { - debug_task ("regexp /%s/ is found in cache, result: %d", re->regexp_text, r); + debug_task ("regexp /%s/ is found in cache, result: %d", + re->regexp_text, + r); return r == 1; } - + if (additional != NULL) { /* We have additional parameter defined, so ignore type of regexp expression and use it for parsing */ if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s with test %s", re->regexp_text, additional); + msg_info ("process test regexp %s with test %s", + re->regexp_text, + additional); } - if (g_regex_match_full (re->regexp, additional, strlen (additional), 0, 0, NULL, NULL) == TRUE) { + if (g_regex_match_full (re->regexp, additional, strlen (additional), 0, + 0, NULL, NULL) == TRUE) { if (G_UNLIKELY (re->is_test)) { msg_info ("result of regexp %s is true", re->regexp_text); } @@ -722,39 +836,53 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar switch (re->type) { case REGEXP_NONE: - msg_warn ("bad error detected: %s has invalid regexp type", re->regexp_text); + msg_warn ("bad error detected: %s has invalid regexp type", + re->regexp_text); return 0; case REGEXP_HEADER: /* Check header's name */ if (re->header == NULL) { - msg_info ("header regexp without header name: '%s'", re->regexp_text); + msg_info ("header regexp without header name: '%s'", + re->regexp_text); task_cache_add (task, re, 0); return 0; } - debug_task ("checking header regexp: %s = %s", re->header, re->regexp_text); + debug_task ("checking header regexp: %s = %s", + re->header, + re->regexp_text); /* Get list of specified headers */ - headerlist = message_get_header (task->task_pool, task->message, re->header, re->is_strong); + headerlist = message_get_header (task->task_pool, + task->message, + re->header, + re->is_strong); if (headerlist == NULL) { /* Header is not found */ if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s returned FALSE: no header found", re->regexp_text, re->header); + msg_info ( + "process test regexp %s for header %s returned FALSE: no header found", + re->regexp_text, + re->header); } task_cache_add (task, re, 0); return 0; } else { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, headerlist); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, headerlist); /* Check whether we have regexp for it */ if (re->regexp == NULL) { - debug_task ("regexp contains only header and it is found %s", re->header); + debug_task ("regexp contains only header and it is found %s", + re->header); task_cache_add (task, re, 1); return 1; } /* Iterate throught headers */ cur = headerlist; while (cur) { - debug_task ("found header \"%s\" with value \"%s\"", re->header, (const gchar *)cur->data); + debug_task ("found header \"%s\" with value \"%s\"", + re->header, + (const gchar *)cur->data); /* Try to match regexp */ if (!re->is_raw) { /* Validate input */ @@ -763,9 +891,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar continue; } } - if (cur->data && g_regex_match_full (re->regexp, cur->data, -1, 0, 0, NULL, &err) == TRUE) { + if (cur->data && + g_regex_match_full (re->regexp, cur->data, -1, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned TRUE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned TRUE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (f != NULL && limit > 1) { /* If we have limit count, increase passed count and compare with limit */ @@ -780,10 +914,17 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } } else if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned FALSE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned FALSE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ( + "error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } cur = g_list_next (cur); } @@ -803,8 +944,11 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar continue; } /* Skip too large parts */ - if (regexp_module_ctx->max_size != 0 && part->content->len > regexp_module_ctx->max_size) { - msg_info ("<%s> skip part of size %Hud", task->message_id, part->content->len); + if (regexp_module_ctx->max_size != 0 && part->content->len > + regexp_module_ctx->max_size) { + msg_info ("<%s> skip part of size %Hud", + task->message_id, + part->content->len); cur = g_list_next (cur); continue; } @@ -828,12 +972,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar /* If we have limit, apply regexp so much times as we can */ if (f != NULL && limit > 1) { end = 0; - while ((matched = g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, 0, &info, &err)) == TRUE) { + while ((matched = + g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, + 0, &info, &err)) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned TRUE", - re->regexp_text, - (gint)clen, - end); + msg_info ( + "process test regexp %s for mime part of length %d returned TRUE", + re->regexp_text, + (gint)clen, + end); } if (f (++passed, limit)) { task_cache_add (task, re, 1); @@ -842,7 +989,8 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar else { /* Match not found, skip further cycles */ old = end; - if (!g_match_info_fetch_pos (info, 0, &start, &end) || end <= 0) { + if (!g_match_info_fetch_pos (info, 0, &start, + &end) || end <= 0) { break; } end += old; @@ -852,10 +1000,13 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar g_match_info_free (info); } else { - if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, &err) == TRUE) { + if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned TRUE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for mime part of length %d returned TRUE", + re->regexp_text, + (gint)clen); } task_cache_add (task, re, 1); return 1; @@ -863,11 +1014,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } if (!matched && G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned FALSE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for mime part of length %d returned FALSE", + re->regexp_text, + (gint)clen); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ("error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } cur = g_list_next (cur); } @@ -879,17 +1034,22 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar ct = task->msg->str; clen = task->msg->len; - if (regexp_module_ctx->max_size != 0 && clen > regexp_module_ctx->max_size) { + if (regexp_module_ctx->max_size != 0 && clen > + regexp_module_ctx->max_size) { msg_info ("<%s> skip message of size %Hz", task->message_id, clen); return 0; } /* If we have limit, apply regexp so much times as we can */ if (f != NULL && limit > 1) { end = 0; - while ((matched = g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, 0, &info, &err)) == TRUE) { + while ((matched = + g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, 0, + &info, &err)) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned TRUE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for mime part of length %d returned TRUE", + re->regexp_text, + (gint)clen); } if (f (++passed, limit)) { task_cache_add (task, re, 1); @@ -898,7 +1058,8 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar else { /* Match not found, skip further cycles */ old = end; - if (!g_match_info_fetch_pos (info, 0, &start, &end) || end <= 0) { + if (!g_match_info_fetch_pos (info, 0, &start, + &end) || end <= 0) { break; } old += end; @@ -908,10 +1069,13 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar g_match_info_free (info); } else { - if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, &err) == TRUE) { + if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for message part of length %d returned TRUE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for message part of length %d returned TRUE", + re->regexp_text, + (gint)clen); } task_cache_add (task, re, 1); return 1; @@ -919,11 +1083,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } if (!matched && G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for message part of length %d returned FALSE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for message part of length %d returned FALSE", + re->regexp_text, + (gint)clen); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ("error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } task_cache_add (task, re, 0); return 0; @@ -949,21 +1117,29 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } return 0; case REGEXP_RAW_HEADER: - debug_task ("checking for raw header: %s with regexp: %s", re->header, re->regexp_text); + debug_task ("checking for raw header: %s with regexp: %s", + re->header, + re->regexp_text); /* Check header's name */ if (re->header == NULL) { - msg_info ("header regexp without header name: '%s'", re->regexp_text); + msg_info ("header regexp without header name: '%s'", + re->regexp_text); task_cache_add (task, re, 0); return 0; } - debug_task ("checking header regexp: %s = %s", re->header, re->regexp_text); + debug_task ("checking header regexp: %s = %s", + re->header, + re->regexp_text); /* Get list of specified headers */ headerlist = message_get_raw_header (task, re->header, re->is_strong); if (headerlist == NULL) { /* Header is not found */ if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s returned FALSE: no header found", re->regexp_text, re->header); + msg_info ( + "process test regexp %s for header %s returned FALSE: no header found", + re->regexp_text, + re->header); } task_cache_add (task, re, 0); return 0; @@ -971,14 +1147,17 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar else { /* Check whether we have regexp for it */ if (re->regexp == NULL) { - debug_task ("regexp contains only header and it is found %s", re->header); + debug_task ("regexp contains only header and it is found %s", + re->header); task_cache_add (task, re, 1); return 1; } /* Iterate throught headers */ cur = headerlist; while (cur) { - debug_task ("found header \"%s\" with value \"%s\"", re->header, (const gchar *)cur->data); + debug_task ("found header \"%s\" with value \"%s\"", + re->header, + (const gchar *)cur->data); rh = cur->data; /* Try to match regexp */ if (!re->is_raw) { @@ -988,9 +1167,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar continue; } } - if (rh->value && g_regex_match_full (re->regexp, rh->value, -1, 0, 0, NULL, &err) == TRUE) { + if (rh->value && + g_regex_match_full (re->regexp, rh->value, -1, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned TRUE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned TRUE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (f != NULL && limit > 1) { /* If we have limit count, increase passed count and compare with limit */ @@ -1005,10 +1190,17 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } } else if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned FALSE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned FALSE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ( + "error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } cur = g_list_next (cur); } @@ -1025,10 +1217,12 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } static gboolean -maybe_call_lua_function (const gchar *name, struct rspamd_task *task, lua_State *L) +maybe_call_lua_function (const gchar *name, + struct rspamd_task *task, + lua_State *L) { - struct rspamd_task **ptask; - gboolean res; + struct rspamd_task **ptask; + gboolean res; lua_getglobal (L, name); if (lua_isfunction (L, -1)) { @@ -1037,7 +1231,8 @@ maybe_call_lua_function (const gchar *name, struct rspamd_task *task, lua_State *ptask = task; /* Call function */ if (lua_pcall (L, 1, 1, 0) != 0) { - msg_info ("call to %s failed: %s", (gchar *)name, lua_tostring (L, -1)); + msg_info ("call to %s failed: %s", (gchar *)name, + lua_tostring (L, -1)); return FALSE; } res = lua_toboolean (L, -1); @@ -1050,12 +1245,12 @@ maybe_call_lua_function (const gchar *name, struct rspamd_task *task, lua_State return FALSE; } -static gboolean +static gboolean optimize_regexp_expression (struct expression **e, GQueue * stack, gboolean res) { - struct expression *it = (*e)->next; - gboolean ret = FALSE, is_nearest = TRUE; - gint skip_level = 0; + struct expression *it = (*e)->next; + gboolean ret = FALSE, is_nearest = TRUE; + gint skip_level = 0; /* Skip nearest logical operators from optimization */ if (!it || (it->type == EXPR_OPERATION && it->content.operation != '!')) { @@ -1106,22 +1301,29 @@ optimize_regexp_expression (struct expression **e, GQueue * stack, gboolean res) return ret; } -static gboolean -process_regexp_expression (struct expression *expr, const gchar *symbol, struct rspamd_task *task, - const gchar *additional, struct lua_locked_state *nL) +static gboolean +process_regexp_expression (struct expression *expr, + const gchar *symbol, + struct rspamd_task *task, + const gchar *additional, + struct lua_locked_state *nL) { - GQueue *stack; - gsize cur, op1, op2; - struct expression *it = expr; - struct rspamd_regexp *re; - gboolean try_optimize = TRUE; + GQueue *stack; + gsize cur, op1, op2; + struct expression *it = expr; + struct rspamd_regexp *re; + gboolean try_optimize = TRUE; stack = g_queue_new (); while (it) { if (it->type == EXPR_REGEXP_PARSED) { /* Find corresponding symbol */ - cur = process_regexp ((struct rspamd_regexp *)it->content.operand, task, additional, 0, NULL); + cur = process_regexp ((struct rspamd_regexp *)it->content.operand, + task, + additional, + 0, + NULL); debug_task ("regexp %s found", cur ? "is" : "is not"); if (try_optimize) { try_optimize = optimize_regexp_expression (&it, stack, cur); @@ -1133,13 +1335,21 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct else if (it->type == EXPR_FUNCTION) { if (nL) { rspamd_mutex_lock (nL->m); - cur = (gsize) call_expression_function ((struct expression_function *)it->content.operand, task, nL->L); + cur = + (gsize) call_expression_function ((struct + expression_function + *)it->content.operand, task, nL->L); rspamd_mutex_unlock (nL->m); } else { - cur = (gsize) call_expression_function ((struct expression_function *)it->content.operand, task, task->cfg->lua_state); - } - debug_task ("function %s returned %s", ((struct expression_function *)it->content.operand)->name, cur ? "true" : "false"); + cur = + (gsize) call_expression_function ((struct + expression_function + *)it->content.operand, task, task->cfg->lua_state); + } + debug_task ("function %s returned %s", + ((struct expression_function *)it->content.operand)->name, + cur ? "true" : "false"); if (try_optimize) { try_optimize = optimize_regexp_expression (&it, stack, cur); } @@ -1151,13 +1361,21 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct /* This may be lua function, try to call it */ if (nL) { rspamd_mutex_lock (nL->m); - cur = maybe_call_lua_function ((const gchar*)it->content.operand, task, nL->L); + cur = maybe_call_lua_function ( + (const gchar *)it->content.operand, + task, + nL->L); rspamd_mutex_unlock (nL->m); } else { - cur = maybe_call_lua_function ((const gchar*)it->content.operand, task, task->cfg->lua_state); - } - debug_task ("function %s returned %s", (const gchar *)it->content.operand, cur ? "true" : "false"); + cur = maybe_call_lua_function ( + (const gchar *)it->content.operand, + task, + task->cfg->lua_state); + } + debug_task ("function %s returned %s", + (const gchar *)it->content.operand, + cur ? "true" : "false"); if (try_optimize) { try_optimize = optimize_regexp_expression (&it, stack, cur); } @@ -1171,7 +1389,9 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct it = it->next; continue; } - re = parse_regexp (task->cfg->cfg_pool, it->content.operand, task->cfg->raw_mode); + re = parse_regexp (task->cfg->cfg_pool, + it->content.operand, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot parse regexp, skip expression"); g_queue_free (stack); @@ -1185,7 +1405,8 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct else if (it->type == EXPR_OPERATION) { if (g_queue_is_empty (stack)) { /* Queue has no operands for operation, exiting */ - msg_warn ("regexp expression seems to be invalid: empty stack while reading operation"); + msg_warn ( + "regexp expression seems to be invalid: empty stack while reading operation"); g_queue_free (stack); return FALSE; } @@ -1199,12 +1420,16 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct case '&': op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); - try_optimize = optimize_regexp_expression (&it, stack, op1 && op2); + try_optimize = optimize_regexp_expression (&it, + stack, + op1 && op2); break; case '|': op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); - try_optimize = optimize_regexp_expression (&it, stack, op1 || op2); + try_optimize = optimize_regexp_expression (&it, + stack, + op1 || op2); break; default: it = it->next; @@ -1223,7 +1448,9 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct } } else { - msg_warn ("regexp expression seems to be invalid: empty stack at the end of expression, symbol %s", symbol); + msg_warn ( + "regexp expression seems to be invalid: empty stack at the end of expression, symbol %s", + symbol); } g_queue_free (stack); @@ -1239,11 +1466,12 @@ struct regexp_threaded_ud { static void process_regexp_item_threaded (gpointer data, gpointer user_data) { - struct regexp_threaded_ud *ud = data; - struct lua_locked_state *nL = user_data; + struct regexp_threaded_ud *ud = data; + struct lua_locked_state *nL = user_data; /* Process expression */ - if (process_regexp_expression (ud->item->expr, ud->item->symbol, ud->task, NULL, nL)) { + if (process_regexp_expression (ud->item->expr, ud->item->symbol, ud->task, + NULL, nL)) { g_mutex_lock (workers_mtx); insert_result (ud->task, ud->item->symbol, 1, NULL); g_mutex_unlock (workers_mtx); @@ -1254,18 +1482,18 @@ process_regexp_item_threaded (gpointer data, gpointer user_data) static void process_regexp_item (struct rspamd_task *task, void *user_data) { - struct regexp_module_item *item = user_data; - gboolean res = FALSE; - struct regexp_threaded_ud *thr_ud; - GError *err = NULL; - struct lua_locked_state *nL; + struct regexp_module_item *item = user_data; + gboolean res = FALSE; + struct regexp_threaded_ud *thr_ud; + GError *err = NULL; + struct lua_locked_state *nL; if (!item->lua_function && regexp_module_ctx->max_threads > 1) { if (regexp_module_ctx->workers == NULL) { #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) # if GLIB_MINOR_VERSION > 20 - if (! g_thread_get_initialized ()) { + if (!g_thread_get_initialized ()) { g_thread_init (NULL); } # else @@ -1273,20 +1501,27 @@ process_regexp_item (struct rspamd_task *task, void *user_data) # endif workers_mtx = g_mutex_new (); #else - workers_mtx = rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, sizeof (GMutex)); + workers_mtx = rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, + sizeof (GMutex)); g_mutex_init (workers_mtx); #endif nL = init_lua_locked (task->cfg); luaopen_regexp (nL->L); - regexp_module_ctx->workers = g_thread_pool_new (process_regexp_item_threaded, - nL, regexp_module_ctx->max_threads, TRUE, &err); + regexp_module_ctx->workers = g_thread_pool_new ( + process_regexp_item_threaded, + nL, + regexp_module_ctx->max_threads, + TRUE, + &err); if (err != NULL) { msg_err ("thread pool creation failed: %s", err->message); regexp_module_ctx->max_threads = 0; return; } } - thr_ud = rspamd_mempool_alloc (task->task_pool, sizeof (struct regexp_threaded_ud)); + thr_ud = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct regexp_threaded_ud)); thr_ud->item = item; thr_ud->task = task; @@ -1294,7 +1529,8 @@ process_regexp_item (struct rspamd_task *task, void *user_data) register_async_thread (task->s); g_thread_pool_push (regexp_module_ctx->workers, thr_ud, &err); if (err != NULL) { - msg_err ("error pushing task to the regexp thread pool: %s", err->message); + msg_err ("error pushing task to the regexp thread pool: %s", + err->message); remove_async_thread (task->s); } } @@ -1302,25 +1538,28 @@ process_regexp_item (struct rspamd_task *task, void *user_data) /* Non-threaded version */ if (item->lua_function) { /* Just call function */ - if (lua_call_expression_func (item->lua_function, task, NULL, &res) && res) { + if (lua_call_expression_func (item->lua_function, task, NULL, + &res) && res) { insert_result (task, item->symbol, 1, NULL); } } else { /* Process expression */ - if (process_regexp_expression (item->expr, item->symbol, task, NULL, NULL)) { + if (process_regexp_expression (item->expr, item->symbol, task, NULL, + NULL)) { insert_result (task, item->symbol, 1, NULL); } } } } -static gboolean -rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused) +static gboolean +rspamd_regexp_match_number (struct rspamd_task *task, GList * args, + void *unused) { - gint param_count, res = 0; - struct expression_argument *arg; - GList *cur; + gint param_count, res = 0; + struct expression_argument *arg; + GList *cur; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1339,7 +1578,8 @@ rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused } } else { - if (process_regexp_expression (cur->data, "regexp_match_number", task, NULL, NULL)) { + if (process_regexp_expression (cur->data, "regexp_match_number", + task, NULL, NULL)) { res++; } if (res >= param_count) { @@ -1352,14 +1592,16 @@ rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused return res >= param_count; } -static gboolean -rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unused) +static gboolean +rspamd_regexp_occurs_number (struct rspamd_task *task, + GList * args, + void *unused) { - gint limit; - struct expression_argument *arg; - struct rspamd_regexp *re; - gchar *param, *err_str, op; - int_compare_func f = NULL; + gint limit; + struct expression_argument *arg; + struct rspamd_regexp *re; + gchar *param, *err_str, op; + int_compare_func f = NULL; if (args == NULL || args->next == NULL) { msg_warn ("wrong number of parameters to function, must be 2"); @@ -1382,13 +1624,13 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse op = '='; } else { - param ++; + param++; } switch (op) { case '>': if (*param == '=') { f = op_more_equal; - param ++; + param++; } else { f = op_more; @@ -1397,7 +1639,7 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse case '<': if (*param == '=') { f = op_less_equal; - param ++; + param++; } else { f = op_less; @@ -1407,7 +1649,9 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse f = op_equal; break; default: - msg_err ("wrong operation character: %c, assumed '=', '>', '<', '>=', '<=' or empty op", op); + msg_err ( + "wrong operation character: %c, assumed '=', '>', '<', '>=', '<=' or empty op", + op); return FALSE; } @@ -1419,10 +1663,10 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse return process_regexp (re, task, NULL, limit, f); } -static gboolean +static gboolean rspamd_raw_header_exists (struct rspamd_task *task, GList * args, void *unused) { - struct expression_argument *arg; + struct expression_argument *arg; if (args == NULL || task == NULL) { return FALSE; @@ -1438,15 +1682,19 @@ rspamd_raw_header_exists (struct rspamd_task *task, GList * args, void *unused) } static gboolean -match_smtp_data (struct rspamd_task *task, const gchar *re_text, const gchar *what) +match_smtp_data (struct rspamd_task *task, + const gchar *re_text, + const gchar *what) { - struct rspamd_regexp *re; - gint r; + struct rspamd_regexp *re; + gint r; if (*re_text == '/') { /* This is a regexp */ if ((re = re_cache_check (re_text, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, (gchar *)re_text, task->cfg->raw_mode); + re = parse_regexp (task->cfg->cfg_pool, + (gchar *)re_text, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1471,12 +1719,12 @@ match_smtp_data (struct rspamd_task *task, const gchar *re_text, const gchar *wh return FALSE; } -static gboolean +static gboolean rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) { - struct expression_argument *arg; - GList *cur, *rcpt_list = NULL; - gchar *type, *what = NULL; + struct expression_argument *arg; + GList *cur, *rcpt_list = NULL; + gchar *type, *what = NULL; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1492,59 +1740,59 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) else { type = arg->data; switch (*type) { - case 'f': - case 'F': - if (g_ascii_strcasecmp (type, "from") == 0) { - what = task->from; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 'h': - case 'H': - if (g_ascii_strcasecmp (type, "helo") == 0) { - what = task->helo; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 'u': - case 'U': - if (g_ascii_strcasecmp (type, "user") == 0) { - what = task->user; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 's': - case 'S': - if (g_ascii_strcasecmp (type, "subject") == 0) { - what = task->subject; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 'r': - case 'R': - if (g_ascii_strcasecmp (type, "rcpt") == 0) { - rcpt_list = task->rcpt; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - default: + case 'f': + case 'F': + if (g_ascii_strcasecmp (type, "from") == 0) { + what = task->from; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 'h': + case 'H': + if (g_ascii_strcasecmp (type, "helo") == 0) { + what = task->helo; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 'u': + case 'U': + if (g_ascii_strcasecmp (type, "user") == 0) { + what = task->user; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 's': + case 'S': + if (g_ascii_strcasecmp (type, "subject") == 0) { + what = task->subject; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 'r': + case 'R': + if (g_ascii_strcasecmp (type, "rcpt") == 0) { + rcpt_list = task->rcpt; + } + else { msg_warn ("bad argument to function: %s", type); return FALSE; + } + break; + default: + msg_warn ("bad argument to function: %s", type); + return FALSE; } } @@ -1552,7 +1800,7 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) /* Not enough data so regexp would NOT be found anyway */ return FALSE; } - + /* We would process only one more argument, others are ignored */ cur = args->next; if (cur) { @@ -1572,13 +1820,16 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) } else if (arg != NULL) { if (what != NULL) { - if (process_regexp_expression (arg->data, "regexp_check_smtp_data", task, what, NULL)) { + if (process_regexp_expression (arg->data, + "regexp_check_smtp_data", task, what, NULL)) { return TRUE; } } else { while (rcpt_list) { - if (process_regexp_expression (arg->data, "regexp_check_smtp_data", task, rcpt_list->data, NULL)) { + if (process_regexp_expression (arg->data, + "regexp_check_smtp_data", task, rcpt_list->data, + NULL)) { return TRUE; } rcpt_list = g_list_next (rcpt_list); @@ -1594,11 +1845,11 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) static gint lua_regexp_match (lua_State *L) { - void *ud = luaL_checkudata (L, 1, "rspamd{task}"); - struct rspamd_task *task; - const gchar *re_text; - struct rspamd_regexp *re; - gint r = 0; + void *ud = luaL_checkudata (L, 1, "rspamd{task}"); + struct rspamd_task *task; + const gchar *re_text; + struct rspamd_regexp *re; + gint r = 0; luaL_argcheck (L, ud != NULL, 1, "'task' expected"); task = ud ? *((struct rspamd_task **)ud) : NULL; @@ -1607,7 +1858,9 @@ lua_regexp_match (lua_State *L) /* This is a regexp */ if (task != NULL) { if ((re = re_cache_check (re_text, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, (gchar *)re_text, task->cfg->raw_mode); + re = parse_regexp (task->cfg->cfg_pool, + (gchar *)re_text, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1622,18 +1875,20 @@ lua_regexp_match (lua_State *L) } static gboolean -rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void *unused) +rspamd_content_type_compare_param (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_name, *param_pattern; - const gchar *param_data; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_name, *param_pattern; + const gchar *param_data; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1656,7 +1911,8 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1677,15 +1933,21 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { - if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) == NULL) { + for (;; ) { + if ((param_data = + g_mime_content_type_get_parameter ((GMimeContentType *)ct, + param_name)) == NULL) { result = FALSE; } else { if (*param_pattern == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if ((re = + re_cache_check (param_pattern, + task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_pattern, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1693,7 +1955,8 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void re_cache_add (param_pattern, re, task->cfg->cfg_pool); } if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, param_data, 0, NULL) == TRUE) { + if (g_regex_match (re->regexp, param_data, 0, + NULL) == TRUE) { task_cache_add (task, re, 1); return TRUE; } @@ -1711,7 +1974,7 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void } } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1733,16 +1996,18 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void } static gboolean -rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *unused) +rspamd_content_type_has_param (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_name; - const gchar *param_data; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_name; + const gchar *param_data; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1757,7 +2022,8 @@ rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *un if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1778,12 +2044,14 @@ rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *un #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { - if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) != NULL) { + for (;; ) { + if ((param_data = + g_mime_content_type_get_parameter ((GMimeContentType *)ct, + param_name)) != NULL) { return TRUE; } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1805,17 +2073,19 @@ rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *un } static gboolean -rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *unused) +rspamd_content_type_is_subtype (struct rspamd_task *task, + GList * args, + void *unused) { - gchar *param_pattern; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_pattern; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1830,7 +2100,8 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1851,11 +2122,15 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { + for (;; ) { if (*param_pattern == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if ((re = + re_cache_check (param_pattern, + task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_pattern, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1863,7 +2138,8 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un re_cache_add (param_pattern, re, task->cfg->cfg_pool); } if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, ct->subtype, 0, NULL) == TRUE) { + if (g_regex_match (re->regexp, ct->subtype, 0, + NULL) == TRUE) { task_cache_add (task, re, 1); return TRUE; } @@ -1880,7 +2156,7 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un } } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1902,17 +2178,19 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un } static gboolean -rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unused) +rspamd_content_type_is_type (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_pattern; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_pattern; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1928,7 +2206,8 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1949,11 +2228,15 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { + for (;; ) { if (*param_pattern == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if ((re = + re_cache_check (param_pattern, + task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_pattern, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1978,7 +2261,7 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus } } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1999,11 +2282,12 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus return FALSE; } -static gboolean -compare_subtype (struct rspamd_task *task, GMimeContentType * ct, gchar *subtype) +static gboolean +compare_subtype (struct rspamd_task *task, GMimeContentType * ct, + gchar *subtype) { - struct rspamd_regexp *re; - gint r; + struct rspamd_regexp *re; + gint r; if (subtype == NULL || ct == NULL) { msg_warn ("invalid parameters passed"); @@ -2012,7 +2296,9 @@ compare_subtype (struct rspamd_task *task, GMimeContentType * ct, gchar *subtype if (*subtype == '/') { /* This is regexp, so compile and create g_regexp object */ if ((re = re_cache_check (subtype, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, subtype, task->cfg->raw_mode); + re = + parse_regexp (task->cfg->cfg_pool, subtype, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -2040,7 +2326,7 @@ compare_subtype (struct rspamd_task *task, GMimeContentType * ct, gchar *subtype return FALSE; } -static gboolean +static gboolean compare_len (struct mime_part *part, guint min, guint max) { if (min == 0 && max == 0) { @@ -2059,13 +2345,17 @@ compare_len (struct mime_part *part, guint min, guint max) } static gboolean -common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *param_subtype, gint min_len, gint max_len) +common_has_content_part (struct rspamd_task * task, + gchar *param_type, + gchar *param_subtype, + gint min_len, + gint max_len) { - struct rspamd_regexp *re; - struct mime_part *part; - GList *cur; - GMimeContentType *ct; - gint r; + struct rspamd_regexp *re; + struct mime_part *part; + GList *cur; + GMimeContentType *ct; + gint r; cur = g_list_first (task->parts); while (cur) { @@ -2078,8 +2368,11 @@ common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *pa if (*param_type == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_type, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_type, task->cfg->raw_mode); + if ((re = + re_cache_check (param_type, task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_type, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); cur = g_list_next (cur); @@ -2088,7 +2381,8 @@ common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *pa re_cache_add (param_type, re, task->cfg->cfg_pool); } if ((r = task_cache_check (task, re)) == -1) { - if (ct->type && g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { + if (ct->type && + g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { if (param_subtype) { if (compare_subtype (task, ct, param_subtype)) { if (compare_len (part, min_len, max_len)) { @@ -2143,8 +2437,8 @@ common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *pa static gboolean rspamd_has_content_part (struct rspamd_task * task, GList * args, void *unused) { - gchar *param_type = NULL, *param_subtype = NULL; - struct expression_argument *arg; + gchar *param_type = NULL, *param_subtype = NULL; + struct expression_argument *arg; if (args == NULL) { msg_warn ("no parameters to function"); @@ -2163,11 +2457,13 @@ rspamd_has_content_part (struct rspamd_task * task, GList * args, void *unused) } static gboolean -rspamd_has_content_part_len (struct rspamd_task * task, GList * args, void *unused) +rspamd_has_content_part_len (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_type = NULL, *param_subtype = NULL; - gint min = 0, max = 0; - struct expression_argument *arg; + gchar *param_type = NULL, *param_subtype = NULL; + gint min = 0, max = 0; + struct expression_argument *arg; if (args == NULL) { msg_warn ("no parameters to function"); @@ -2186,7 +2482,9 @@ rspamd_has_content_part_len (struct rspamd_task * task, GList * args, void *unus errno = 0; min = strtoul (arg->data, NULL, 10); if (errno != 0) { - msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); + msg_warn ("invalid numeric value '%s': %s", + (gchar *)arg->data, + strerror (errno)); return FALSE; } args = args->next; @@ -2194,7 +2492,9 @@ rspamd_has_content_part_len (struct rspamd_task * task, GList * args, void *unus arg = get_function_arg (args->data, task, TRUE); max = strtoul (arg->data, NULL, 10); if (errno != 0) { - msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); + msg_warn ("invalid numeric value '%s': %s", + (gchar *)arg->data, + strerror (errno)); return FALSE; } } diff --git a/src/plugins/spf.c b/src/plugins/spf.c index 8b9e64754..bf0956e78 100644 --- a/src/plugins/spf.c +++ b/src/plugins/spf.c @@ -49,21 +49,21 @@ #define DEFAULT_CACHE_MAXAGE 86400 struct spf_ctx { - gint (*filter) (struct rspamd_task * task); - const gchar *symbol_fail; - const gchar *symbol_softfail; - const gchar *symbol_allow; - - rspamd_mempool_t *spf_pool; - radix_tree_t *whitelist_ip; - rspamd_lru_hash_t *spf_hash; + gint (*filter) (struct rspamd_task * task); + const gchar *symbol_fail; + const gchar *symbol_softfail; + const gchar *symbol_allow; + + rspamd_mempool_t *spf_pool; + radix_tree_t *whitelist_ip; + rspamd_lru_hash_t *spf_hash; }; -static struct spf_ctx *spf_module_ctx = NULL; +static struct spf_ctx *spf_module_ctx = NULL; -static void spf_symbol_callback (struct rspamd_task *task, void *unused); -static GList * spf_record_copy (GList *addrs); -static void spf_record_destroy (gpointer list); +static void spf_symbol_callback (struct rspamd_task *task, void *unused); +static GList * spf_record_copy (GList *addrs); +static void spf_record_destroy (gpointer list); /* Initialization */ gint spf_module_init (struct rspamd_config *cfg, struct module_ctx **ctx); @@ -83,7 +83,8 @@ spf_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) { spf_module_ctx = g_malloc (sizeof (struct spf_ctx)); - spf_module_ctx->spf_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + spf_module_ctx->spf_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); *ctx = (struct module_ctx *)spf_module_ctx; @@ -94,56 +95,71 @@ spf_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) gint spf_module_config (struct rspamd_config *cfg) { - const ucl_object_t *value; - gint res = TRUE; - guint cache_size, cache_expire; + const ucl_object_t *value; + gint res = TRUE; + guint cache_size, cache_expire; spf_module_ctx->whitelist_ip = radix_tree_create (); - - if ((value = rspamd_config_get_module_opt (cfg, "spf", "symbol_fail")) != NULL) { + + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "symbol_fail")) != NULL) { spf_module_ctx->symbol_fail = ucl_obj_tostring (value); } else { spf_module_ctx->symbol_fail = DEFAULT_SYMBOL_FAIL; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "symbol_softfail")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "symbol_softfail")) != NULL) { spf_module_ctx->symbol_softfail = ucl_obj_tostring (value); } else { spf_module_ctx->symbol_softfail = DEFAULT_SYMBOL_SOFTFAIL; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "symbol_allow")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "symbol_allow")) != NULL) { spf_module_ctx->symbol_allow = ucl_obj_tostring (value); } else { spf_module_ctx->symbol_allow = DEFAULT_SYMBOL_ALLOW; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "spf_cache_size")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "spf_cache_size")) != NULL) { cache_size = ucl_obj_toint (value); } else { cache_size = DEFAULT_CACHE_SIZE; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "spf_cache_expire")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", + "spf_cache_expire")) != NULL) { cache_expire = ucl_obj_toint (value); } else { cache_expire = DEFAULT_CACHE_MAXAGE; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "whitelist")) != NULL) { - if (! add_map (cfg, ucl_obj_tostring (value), - "SPF whitelist", read_radix_list, fin_radix_list, - (void **)&spf_module_ctx->whitelist_ip)) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "whitelist")) != NULL) { + if (!add_map (cfg, ucl_obj_tostring (value), + "SPF whitelist", read_radix_list, fin_radix_list, + (void **)&spf_module_ctx->whitelist_ip)) { msg_warn ("cannot load whitelist from %s", value); } } - register_symbol (&cfg->cache, spf_module_ctx->symbol_fail, 1, spf_symbol_callback, NULL); + register_symbol (&cfg->cache, + spf_module_ctx->symbol_fail, + 1, + spf_symbol_callback, + NULL); register_virtual_symbol (&cfg->cache, spf_module_ctx->symbol_softfail, 1); - register_virtual_symbol (&cfg->cache, spf_module_ctx->symbol_allow, 1); + register_virtual_symbol (&cfg->cache, spf_module_ctx->symbol_allow, 1); - spf_module_ctx->spf_hash = rspamd_lru_hash_new (rspamd_strcase_hash, rspamd_strcase_equal, - cache_size, cache_expire, g_free, spf_record_destroy); + spf_module_ctx->spf_hash = rspamd_lru_hash_new (rspamd_strcase_hash, + rspamd_strcase_equal, + cache_size, + cache_expire, + g_free, + spf_record_destroy); return res; } @@ -153,7 +169,8 @@ spf_module_reconfig (struct rspamd_config *cfg) { rspamd_mempool_delete (spf_module_ctx->spf_pool); radix_tree_free (spf_module_ctx->whitelist_ip); - spf_module_ctx->spf_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + spf_module_ctx->spf_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); return spf_module_config (cfg); } @@ -161,26 +178,30 @@ spf_module_reconfig (struct rspamd_config *cfg) static gboolean spf_check_element (struct spf_addr *addr, struct rspamd_task *task) { - gboolean res = FALSE; - guint8 *s, *d, t; - guint nbits, addrlen; - struct in_addr in4s, in4d; - struct in6_addr in6s, in6d; + gboolean res = FALSE; + guint8 *s, *d, t; + guint nbits, addrlen; + struct in_addr in4s, in4d; + struct in6_addr in6s, in6d; /* Basic comparing algorithm */ if ((addr->data.normal.ipv6 && task->from_addr.af == AF_INET6) || - (!addr->data.normal.ipv6 && task->from_addr.af == AF_INET)) { + (!addr->data.normal.ipv6 && task->from_addr.af == AF_INET)) { if (addr->data.normal.ipv6) { addrlen = sizeof (struct in6_addr); - memcpy (&in6s, &addr->data.normal.d.in6, sizeof (struct in6_addr)); - memcpy (&in6d, &task->from_addr.addr.s6.sin6_addr, sizeof (struct in6_addr)); + memcpy (&in6s, &addr->data.normal.d.in6, + sizeof (struct in6_addr)); + memcpy (&in6d, &task->from_addr.addr.s6.sin6_addr, + sizeof (struct in6_addr)); s = (guint8 *)&in6s; d = (guint8 *)&in6d; } else { addrlen = sizeof (struct in_addr); - memcpy (&in4s, &addr->data.normal.d.in4, sizeof (struct in_addr)); - memcpy (&in4d, &task->from_addr.addr.s4.sin_addr, sizeof (struct in_addr)); + memcpy (&in4s, &addr->data.normal.d.in4, + sizeof (struct in_addr)); + memcpy (&in4d, &task->from_addr.addr.s4.sin_addr, + sizeof (struct in_addr)); s = (guint8 *)&in4s; d = (guint8 *)&in4d; } @@ -189,12 +210,14 @@ spf_check_element (struct spf_addr *addr, struct rspamd_task *task) s += addrlen - 1; d += addrlen - 1; /* TODO: improve this cycle by masking by words */ - for (nbits = 0; nbits < addrlen * CHAR_BIT - addr->data.normal.mask; nbits ++) { + for (nbits = 0; + nbits < addrlen * CHAR_BIT - addr->data.normal.mask; + nbits++) { /* Skip bits from the beginning as we know that data is in network byte order */ if (nbits != 0 && nbits % 8 == 0) { /* Move pointer to the next byte */ - s --; - d --; + s--; + d--; t = 0x1; } *s |= t; @@ -220,17 +243,28 @@ spf_check_element (struct spf_addr *addr, struct rspamd_task *task) if (res) { switch (addr->mech) { case SPF_FAIL: - insert_result (task, spf_module_ctx->symbol_fail, 1, g_list_prepend (NULL, addr->spf_string)); + insert_result (task, + spf_module_ctx->symbol_fail, + 1, + g_list_prepend (NULL, addr->spf_string)); task->messages = g_list_prepend (task->messages, "(SPF): spf fail"); break; case SPF_SOFT_FAIL: case SPF_NEUTRAL: - insert_result (task, spf_module_ctx->symbol_softfail, 1, g_list_prepend (NULL, addr->spf_string)); - task->messages = g_list_prepend (task->messages, "(SPF): spf softfail"); + insert_result (task, + spf_module_ctx->symbol_softfail, + 1, + g_list_prepend (NULL, addr->spf_string)); + task->messages = g_list_prepend (task->messages, + "(SPF): spf softfail"); break; default: - insert_result (task, spf_module_ctx->symbol_allow, 1, g_list_prepend (NULL, addr->spf_string)); - task->messages = g_list_prepend (task->messages, "(SPF): spf allow"); + insert_result (task, + spf_module_ctx->symbol_allow, + 1, + g_list_prepend (NULL, addr->spf_string)); + task->messages = + g_list_prepend (task->messages, "(SPF): spf allow"); break; } return TRUE; @@ -242,8 +276,8 @@ spf_check_element (struct spf_addr *addr, struct rspamd_task *task) static gboolean spf_check_list (GList *list, struct rspamd_task *task) { - GList *cur; - struct spf_addr *addr; + GList *cur; + struct spf_addr *addr; cur = list; @@ -266,16 +300,19 @@ spf_check_list (GList *list, struct rspamd_task *task) return FALSE; } -static void +static void spf_plugin_callback (struct spf_record *record, struct rspamd_task *task) { - GList *l; + GList *l; if (record && record->addrs && record->sender_domain) { - if ((l = rspamd_lru_hash_lookup (spf_module_ctx->spf_hash, record->sender_domain, task->tv.tv_sec)) == NULL) { + if ((l = + rspamd_lru_hash_lookup (spf_module_ctx->spf_hash, + record->sender_domain, task->tv.tv_sec)) == NULL) { l = spf_record_copy (record->addrs); - rspamd_lru_hash_insert (spf_module_ctx->spf_hash, g_strdup (record->sender_domain), + rspamd_lru_hash_insert (spf_module_ctx->spf_hash, + g_strdup (record->sender_domain), l, task->tv.tv_sec, record->ttl); } spf_check_list (l, task); @@ -283,16 +320,18 @@ spf_plugin_callback (struct spf_record *record, struct rspamd_task *task) } -static void +static void spf_symbol_callback (struct rspamd_task *task, void *unused) { - gchar *domain; - GList *l; + gchar *domain; + GList *l; if (task->from_addr.af != AF_UNIX) { domain = get_spf_domain (task); if (domain) { - if ((l = rspamd_lru_hash_lookup (spf_module_ctx->spf_hash, domain, task->tv.tv_sec)) != NULL) { + if ((l = + rspamd_lru_hash_lookup (spf_module_ctx->spf_hash, domain, + task->tv.tv_sec)) != NULL) { spf_check_list (l, task); } else if (!resolve_spf (task, spf_plugin_callback)) { @@ -308,8 +347,8 @@ spf_symbol_callback (struct rspamd_task *task, void *unused) static GList * spf_record_copy (GList *addrs) { - GList *cur, *newl = NULL; - struct spf_addr *addr, *newa; + GList *cur, *newl = NULL; + struct spf_addr *addr, *newa; cur = addrs; @@ -341,8 +380,8 @@ spf_record_copy (GList *addrs) static void spf_record_destroy (gpointer list) { - GList *cur = list; - struct spf_addr *addr; + GList *cur = list; + struct spf_addr *addr; while (cur) { addr = cur->data; diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c index ef25c1d78..be5a60276 100644 --- a/src/plugins/surbl.c +++ b/src/plugins/surbl.c @@ -53,15 +53,15 @@ #include "surbl.h" -static struct surbl_ctx *surbl_module_ctx = NULL; +static struct surbl_ctx *surbl_module_ctx = NULL; static void surbl_test_url (struct rspamd_task *task, void *user_data); static void dns_callback (struct rdns_reply *reply, gpointer arg); static void process_dns_results (struct rspamd_task *task, - struct suffix_item *suffix, gchar *url, guint32 addr); + struct suffix_item *suffix, gchar *url, guint32 addr); -#define NO_REGEXP (gpointer)-1 +#define NO_REGEXP (gpointer) - 1 #define SURBL_ERROR surbl_error_quark () #define WHITELIST_ERROR 0 @@ -89,50 +89,63 @@ module_t surbl_module = { static void exception_insert (gpointer st, gconstpointer key, gpointer value) { - GHashTable **t = st; - gint level = 0; - const gchar *p = key; - f_str_t *val; - + GHashTable **t = st; + gint level = 0; + const gchar *p = key; + f_str_t *val; + while (*p) { if (*p == '.') { - level ++; + level++; } - p ++; + p++; } if (level >= MAX_LEVELS) { - msg_err ("invalid domain in exceptions list: %s, levels: %d", (gchar *)key, level); + msg_err ("invalid domain in exceptions list: %s, levels: %d", + (gchar *)key, + level); return; } - + val = g_malloc (sizeof (f_str_t)); val->begin = (gchar *)key; val->len = strlen (key); if (t[level] == NULL) { - t[level] = g_hash_table_new_full (fstr_strcase_hash, fstr_strcase_equal, g_free, NULL); + t[level] = g_hash_table_new_full (fstr_strcase_hash, + fstr_strcase_equal, + g_free, + NULL); } g_hash_table_insert (t[level], val, value); } static gchar * -read_exceptions_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +read_exceptions_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { if (data->cur_data == NULL) { - data->cur_data = rspamd_mempool_alloc0 (pool, sizeof (GHashTable *) * MAX_LEVELS); + data->cur_data = rspamd_mempool_alloc0 (pool, + sizeof (GHashTable *) * MAX_LEVELS); } - return abstract_parse_list (pool, chunk, len, data, (insert_func) exception_insert); + return abstract_parse_list (pool, + chunk, + len, + data, + (insert_func) exception_insert); } static void fin_exceptions_list (rspamd_mempool_t * pool, struct map_cb_data *data) { - GHashTable **t; - gint i; + GHashTable **t; + gint i; if (data->prev_data) { t = data->prev_data; - for (i = 0; i < MAX_LEVELS; i ++) { + for (i = 0; i < MAX_LEVELS; i++) { if (t[i] != NULL) { g_hash_table_destroy (t[i]); } @@ -143,16 +156,16 @@ fin_exceptions_list (rspamd_mempool_t * pool, struct map_cb_data *data) static void redirector_insert (gpointer st, gconstpointer key, gpointer value) { - GHashTable *t = st; - const gchar *p = key, *begin = key; - gchar *new; - gsize len; - GRegex *re = NO_REGEXP; - GError *err = NULL; - guint idx; + GHashTable *t = st; + const gchar *p = key, *begin = key; + gchar *new; + gsize len; + GRegex *re = NO_REGEXP; + GError *err = NULL; + guint idx; while (*p && !g_ascii_isspace (*p)) { - p ++; + p++; } len = p - begin; @@ -165,13 +178,17 @@ redirector_insert (gpointer st, gconstpointer key, gpointer value) if (g_ascii_isspace (*p)) { while (g_ascii_isspace (*p) && *p) { - p ++; + p++; } if (*p) { - re = g_regex_new (p, G_REGEX_RAW | G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE | G_REGEX_CASELESS, - 0, &err); + re = g_regex_new (p, + G_REGEX_RAW | G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE | G_REGEX_CASELESS, + 0, + &err); if (re == NULL) { - msg_warn ("could not read regexp: %s while reading regexp %s", err->message, p); + msg_warn ("could not read regexp: %s while reading regexp %s", + err->message, + p); re = NO_REGEXP; } } @@ -182,21 +199,31 @@ redirector_insert (gpointer st, gconstpointer key, gpointer value) static void redirector_item_free (gpointer p) { - GRegex *re; + GRegex *re; if (p != NULL && p != NO_REGEXP) { re = (GRegex *)p; g_regex_unref (re); } } -static gchar * -read_redirectors_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +static gchar * +read_redirectors_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { if (data->cur_data == NULL) { - data->cur_data = g_hash_table_new_full (rspamd_strcase_hash, rspamd_strcase_equal, g_free, redirector_item_free); + data->cur_data = g_hash_table_new_full (rspamd_strcase_hash, + rspamd_strcase_equal, + g_free, + redirector_item_free); } - return abstract_parse_list (pool, chunk, len, data, (insert_func) redirector_insert); + return abstract_parse_list (pool, + chunk, + len, + data, + (insert_func) redirector_insert); } void @@ -214,7 +241,8 @@ surbl_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) surbl_module_ctx->use_redirector = 0; surbl_module_ctx->suffixes = NULL; - surbl_module_ctx->surbl_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + surbl_module_ctx->surbl_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); surbl_module_ctx->tld2_file = NULL; surbl_module_ctx->whitelist_file = NULL; @@ -222,16 +250,28 @@ surbl_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) surbl_module_ctx->redirector_trie = rspamd_trie_create (TRUE); surbl_module_ctx->redirector_ptrs = g_ptr_array_new (); - surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); - surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); + surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); + surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); /* Zero exceptions hashes */ - surbl_module_ctx->exceptions = rspamd_mempool_alloc0 (surbl_module_ctx->surbl_pool, MAX_LEVELS * sizeof (GHashTable *)); + surbl_module_ctx->exceptions = rspamd_mempool_alloc0 ( + surbl_module_ctx->surbl_pool, + MAX_LEVELS * sizeof (GHashTable *)); /* Register destructors */ - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, surbl_module_ctx->whitelist); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, surbl_module_ctx->redirector_hosts); - - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) rspamd_trie_free, surbl_module_ctx->redirector_trie); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_ptr_array_unref, surbl_module_ctx->redirector_ptrs); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, + surbl_module_ctx->whitelist); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, + surbl_module_ctx->redirector_hosts); + + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) rspamd_trie_free, + surbl_module_ctx->redirector_trie); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_ptr_array_unref, + surbl_module_ctx->redirector_ptrs); *ctx = (struct module_ctx *)surbl_module_ctx; @@ -244,8 +284,8 @@ surbl_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) static void register_bit_symbols (struct rspamd_config *cfg, struct suffix_item *suffix) { - GList *cur; - struct surbl_bit_item *bit; + GList *cur; + struct surbl_bit_item *bit; if (suffix->bits != NULL) { /* Prepend bit to symbol */ @@ -264,131 +304,163 @@ register_bit_symbols (struct rspamd_config *cfg, struct suffix_item *suffix) gint surbl_module_config (struct rspamd_config *cfg) { - GList *cur_opt; - struct suffix_item *new_suffix, *cur_suffix = NULL; - struct surbl_bit_item *new_bit; + GList *cur_opt; + struct suffix_item *new_suffix, *cur_suffix = NULL; + struct surbl_bit_item *new_bit; - const ucl_object_t *value, *cur, *cur_rule, *cur_bit; - ucl_object_iter_t it = NULL; - const gchar *redir_val; - guint32 bit; - gint i, idx; + const ucl_object_t *value, *cur, *cur_rule, *cur_bit; + ucl_object_iter_t it = NULL; + const gchar *redir_val; + guint32 bit; + gint i, idx; - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "redirector")) != NULL) { i = 0; - LL_FOREACH (value, cur) { - i ++; + LL_FOREACH (value, cur) + { + i++; } - surbl_module_ctx->redirectors = rspamd_mempool_alloc0 (surbl_module_ctx->surbl_pool, - i * sizeof (struct redirector_upstream)); + surbl_module_ctx->redirectors = rspamd_mempool_alloc0 ( + surbl_module_ctx->surbl_pool, + i * sizeof (struct redirector_upstream)); idx = 0; - LL_FOREACH (value, cur) { + LL_FOREACH (value, cur) + { redir_val = ucl_obj_tostring (cur); surbl_module_ctx->redirectors[idx].up.priority = 100; - if (! rspamd_parse_host_port_priority (surbl_module_ctx->surbl_pool, - redir_val, &surbl_module_ctx->redirectors[idx].addr, - &surbl_module_ctx->redirectors[idx].port, - &surbl_module_ctx->redirectors[idx].up.priority)) { + if (!rspamd_parse_host_port_priority (surbl_module_ctx->surbl_pool, + redir_val, &surbl_module_ctx->redirectors[idx].addr, + &surbl_module_ctx->redirectors[idx].port, + &surbl_module_ctx->redirectors[idx].up.priority)) { msg_warn ("invalid redirector definition: %s", redir_val); } else { if (surbl_module_ctx->redirectors[idx].port != 0) { - surbl_module_ctx->redirectors[idx].name = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, + surbl_module_ctx->redirectors[idx].name = + rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, redir_val); - msg_info ("add redirector %s", surbl_module_ctx->redirectors[idx].name); - idx ++; + msg_info ("add redirector %s", + surbl_module_ctx->redirectors[idx].name); + idx++; } } - i ++; + i++; } surbl_module_ctx->redirectors_number = idx; - surbl_module_ctx->use_redirector = (surbl_module_ctx->redirectors_number != 0); + surbl_module_ctx->use_redirector = + (surbl_module_ctx->redirectors_number != 0); } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector_symbol")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", + "redirector_symbol")) != NULL) { surbl_module_ctx->redirector_symbol = ucl_obj_tostring (value); - register_virtual_symbol (&cfg->cache, surbl_module_ctx->redirector_symbol, 1.0); + register_virtual_symbol (&cfg->cache, + surbl_module_ctx->redirector_symbol, + 1.0); } else { surbl_module_ctx->redirector_symbol = NULL; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "weight")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "weight")) != NULL) { surbl_module_ctx->weight = ucl_obj_toint (value); } else { surbl_module_ctx->weight = DEFAULT_SURBL_WEIGHT; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "url_expire")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "url_expire")) != NULL) { surbl_module_ctx->url_expire = ucl_obj_todouble (value); } else { surbl_module_ctx->url_expire = DEFAULT_SURBL_URL_EXPIRE; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector_connect_timeout")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", + "redirector_connect_timeout")) != NULL) { surbl_module_ctx->connect_timeout = ucl_obj_todouble (value); } else { surbl_module_ctx->connect_timeout = DEFAULT_REDIRECTOR_CONNECT_TIMEOUT; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector_read_timeout")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", + "redirector_read_timeout")) != NULL) { surbl_module_ctx->read_timeout = ucl_obj_todouble (value); } else { surbl_module_ctx->read_timeout = DEFAULT_REDIRECTOR_READ_TIMEOUT; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector_hosts_map")) != NULL) { - add_map (cfg, ucl_obj_tostring (value), - "SURBL redirectors list", read_redirectors_list, fin_redirectors_list, - (void **)&surbl_module_ctx->redirector_hosts); + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", + "redirector_hosts_map")) != NULL) { + add_map (cfg, ucl_obj_tostring ( + value), + "SURBL redirectors list", read_redirectors_list, fin_redirectors_list, + (void **)&surbl_module_ctx->redirector_hosts); } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "max_urls")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "max_urls")) != NULL) { surbl_module_ctx->max_urls = ucl_obj_toint (value); } else { surbl_module_ctx->max_urls = DEFAULT_SURBL_MAX_URLS; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "exceptions")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "exceptions")) != NULL) { if (add_map (cfg, ucl_obj_tostring (value), - "SURBL exceptions list", read_exceptions_list, fin_exceptions_list, - (void **)&surbl_module_ctx->exceptions)) { - surbl_module_ctx->tld2_file = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, - ucl_obj_tostring (value) + sizeof ("file://") - 1); + "SURBL exceptions list", read_exceptions_list, fin_exceptions_list, + (void **)&surbl_module_ctx->exceptions)) { + surbl_module_ctx->tld2_file = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + ucl_obj_tostring (value) + sizeof ("file://") - 1); } } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "whitelist")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "whitelist")) != NULL) { if (add_map (cfg, ucl_obj_tostring (value), - "SURBL whitelist", read_host_list, fin_host_list, - (void **)&surbl_module_ctx->whitelist)) { - surbl_module_ctx->whitelist_file = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, - ucl_obj_tostring (value) + sizeof ("file://") - 1); + "SURBL whitelist", read_host_list, fin_host_list, + (void **)&surbl_module_ctx->whitelist)) { + surbl_module_ctx->whitelist_file = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + ucl_obj_tostring (value) + sizeof ("file://") - 1); } } value = rspamd_config_get_module_opt (cfg, "surbl", "rule"); if (value != NULL && value->type == UCL_OBJECT) { - LL_FOREACH (value, cur_rule) { + LL_FOREACH (value, cur_rule) + { cur = ucl_obj_get_key (cur_rule, "suffix"); if (cur == NULL) { msg_err ("surbl rule must have explicit symbol definition"); continue; } - new_suffix = rspamd_mempool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct suffix_item)); - new_suffix->suffix = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, - ucl_obj_tostring (cur)); + new_suffix = rspamd_mempool_alloc (surbl_module_ctx->surbl_pool, + sizeof (struct suffix_item)); + new_suffix->suffix = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + ucl_obj_tostring (cur)); new_suffix->options = 0; new_suffix->bits = NULL; cur = ucl_obj_get_key (cur_rule, "symbol"); if (cur == NULL) { - msg_warn ("surbl rule for suffix %s lacks symbol, using %s as symbol", new_suffix->suffix, - DEFAULT_SURBL_SYMBOL); - new_suffix->symbol = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, - DEFAULT_SURBL_SYMBOL); + msg_warn ( + "surbl rule for suffix %s lacks symbol, using %s as symbol", + new_suffix->suffix, + DEFAULT_SURBL_SYMBOL); + new_suffix->symbol = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + DEFAULT_SURBL_SYMBOL); } else { - new_suffix->symbol = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, - ucl_obj_tostring (cur)); + new_suffix->symbol = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + ucl_obj_tostring (cur)); } cur = ucl_obj_get_key (cur_rule, "options"); if (cur != NULL && cur->type == UCL_STRING) { @@ -399,19 +471,33 @@ surbl_module_config (struct rspamd_config *cfg) cur = ucl_obj_get_key (cur_rule, "bits"); if (cur != NULL && cur->type == UCL_OBJECT) { it = NULL; - while ((cur_bit = ucl_iterate_object (cur, &it, true)) != NULL) { - if (ucl_object_key (cur_bit) != NULL && cur_bit->type == UCL_INT) { + while ((cur_bit = + ucl_iterate_object (cur, &it, true)) != NULL) { + if (ucl_object_key (cur_bit) != NULL && cur_bit->type == + UCL_INT) { bit = ucl_obj_toint (cur_bit); - new_bit = rspamd_mempool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct surbl_bit_item)); + new_bit = rspamd_mempool_alloc ( + surbl_module_ctx->surbl_pool, + sizeof (struct surbl_bit_item)); new_bit->bit = bit; - new_bit->symbol = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, ucl_object_key (cur_bit)); - msg_debug ("add new bit suffix: %d with symbol: %s", (gint)new_bit->bit, new_bit->symbol); - new_suffix->bits = g_list_prepend (new_suffix->bits, new_bit); + new_bit->symbol = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + ucl_object_key (cur_bit)); + msg_debug ("add new bit suffix: %d with symbol: %s", + (gint)new_bit->bit, new_bit->symbol); + new_suffix->bits = g_list_prepend (new_suffix->bits, + new_bit); } } } - surbl_module_ctx->suffixes = g_list_prepend (surbl_module_ctx->suffixes, new_suffix); - register_callback_symbol (&cfg->cache, new_suffix->symbol, 1, surbl_test_url, new_suffix); + surbl_module_ctx->suffixes = g_list_prepend ( + surbl_module_ctx->suffixes, + new_suffix); + register_callback_symbol (&cfg->cache, + new_suffix->symbol, + 1, + surbl_test_url, + new_suffix); } } /* Add default suffix */ @@ -421,8 +507,9 @@ surbl_module_config (struct rspamd_config *cfg) } if (surbl_module_ctx->suffixes != NULL) { - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_list_free, - surbl_module_ctx->suffixes); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_list_free, + surbl_module_ctx->suffixes); } cur_opt = surbl_module_ctx->suffixes; @@ -430,8 +517,9 @@ surbl_module_config (struct rspamd_config *cfg) cur_suffix = cur_opt->data; if (cur_suffix->bits != NULL) { register_bit_symbols (cfg, cur_suffix); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_list_free, - cur_suffix->bits); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_list_free, + cur_suffix->bits); } cur_opt = g_list_next (cur_opt); } @@ -447,25 +535,40 @@ surbl_module_reconfig (struct rspamd_config *cfg) /* Reinit module */ surbl_module_ctx->use_redirector = 0; surbl_module_ctx->suffixes = NULL; - surbl_module_ctx->surbl_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + surbl_module_ctx->surbl_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); surbl_module_ctx->tld2_file = NULL; surbl_module_ctx->whitelist_file = NULL; surbl_module_ctx->redirectors_number = 0; surbl_module_ctx->redirector_trie = rspamd_trie_create (TRUE); - surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); - surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); + surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); + surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); /* Zero exceptions hashes */ - surbl_module_ctx->exceptions = rspamd_mempool_alloc0 (surbl_module_ctx->surbl_pool, MAX_LEVELS * sizeof (GHashTable *)); + surbl_module_ctx->exceptions = rspamd_mempool_alloc0 ( + surbl_module_ctx->surbl_pool, + MAX_LEVELS * sizeof (GHashTable *)); /* Register destructors */ - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, surbl_module_ctx->whitelist); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, surbl_module_ctx->redirector_hosts); - - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_list_free, surbl_module_ctx->suffixes); - - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) rspamd_trie_free, surbl_module_ctx->redirector_trie); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_ptr_array_unref, surbl_module_ctx->redirector_ptrs); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, + surbl_module_ctx->whitelist); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, + surbl_module_ctx->redirector_hosts); + + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_list_free, + surbl_module_ctx->suffixes); + + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) rspamd_trie_free, + surbl_module_ctx->redirector_trie); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_ptr_array_unref, + surbl_module_ctx->redirector_ptrs); /* Perform configure */ return surbl_module_config (cfg); @@ -473,16 +576,22 @@ surbl_module_reconfig (struct rspamd_config *cfg) -static gchar * -format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix_item *suffix, - gboolean append_suffix, GError ** err, gboolean forced, GTree *tree) +static gchar * +format_surbl_request (rspamd_mempool_t * pool, + f_str_t * hostname, + struct suffix_item *suffix, + gboolean append_suffix, + GError ** err, + gboolean forced, + GTree *tree) { - GHashTable *t; - gchar *result = NULL, *dots[MAX_LEVELS], num_buf[sizeof("18446744073709551616")], *p; - gint len, slen, r, i, dots_num = 0, level = MAX_LEVELS; - gboolean is_numeric = TRUE; - guint64 ip_num; - f_str_t f; + GHashTable *t; + gchar *result = NULL, *dots[MAX_LEVELS], + num_buf[sizeof("18446744073709551616")], *p; + gint len, slen, r, i, dots_num = 0, level = MAX_LEVELS; + gboolean is_numeric = TRUE; + guint64 ip_num; + f_str_t f; if (G_LIKELY (suffix != NULL)) { slen = strlen (suffix->suffix); @@ -494,19 +603,19 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix g_assert_not_reached (); } len = hostname->len + slen + 2; - + p = hostname->begin; while (p - hostname->begin < (gint)hostname->len && dots_num < MAX_LEVELS) { if (*p == '.') { dots[dots_num] = p; - dots_num ++; + dots_num++; } - else if (! g_ascii_isdigit (*p)) { + else if (!g_ascii_isdigit (*p)) { is_numeric = FALSE; } - p ++; + p++; } - + /* Check for numeric expressions */ if (is_numeric && dots_num == 3) { /* This is ip address */ @@ -516,7 +625,7 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix return NULL; } result = rspamd_mempool_alloc (pool, len); - r = rspamd_snprintf (result, len, "%*s.%*s.%*s.%*s", + r = rspamd_snprintf (result, len, "%*s.%*s.%*s.%*s", (gint)(hostname->len - (dots[2] - hostname->begin + 1)), dots[2] + 1, (gint)(dots[2] - dots[1] - 1), @@ -533,13 +642,16 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix msg_info ("ignore request of ip url for list %s", suffix->symbol); return NULL; } - rspamd_strlcpy (num_buf, hostname->begin, MIN (hostname->len + 1, sizeof (num_buf))); + rspamd_strlcpy (num_buf, hostname->begin, + MIN (hostname->len + 1, sizeof (num_buf))); errno = 0; ip_num = strtoull (num_buf, NULL, 10); if (errno != 0) { - msg_info ("cannot convert ip to number '%s': %s", num_buf, strerror (errno)); - g_set_error (err, SURBL_ERROR, /* error domain */ - CONVERSION_ERROR, /* error code */ + msg_info ("cannot convert ip to number '%s': %s", + num_buf, + strerror (errno)); + g_set_error (err, SURBL_ERROR, /* error domain */ + CONVERSION_ERROR, /* error code */ "URL cannot be decoded"); return NULL; } @@ -549,19 +661,25 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix /* Hack for bugged windows resolver */ ip_num &= 0xFFFFFFFF; /* Get octets */ - r = rspamd_snprintf (result, len, "%ud.%ud.%ud.%ud", - (guint32) ip_num & 0x000000FF, (guint32) (ip_num & 0x0000FF00) >> 8, (guint32) (ip_num & 0x00FF0000) >> 16, (guint32) (ip_num & 0xFF000000) >> 24); + r = rspamd_snprintf (result, + len, + "%ud.%ud.%ud.%ud", + (guint32) ip_num & 0x000000FF, + (guint32) (ip_num & 0x0000FF00) >> 8, + (guint32) (ip_num & 0x00FF0000) >> 16, + (guint32) (ip_num & 0xFF000000) >> 24); } else { /* Not a numeric url */ result = rspamd_mempool_alloc (pool, len); /* Now we should try to check for exceptions */ - if (! forced) { - for (i = MAX_LEVELS - 1; i >= 0; i --) { + if (!forced) { + for (i = MAX_LEVELS - 1; i >= 0; i--) { t = surbl_module_ctx->exceptions[i]; if (t != NULL && dots_num >= i + 1) { f.begin = dots[dots_num - i - 1] + 1; - f.len = hostname->len - (dots[dots_num - i - 1] - hostname->begin + 1); + f.len = hostname->len - + (dots[dots_num - i - 1] - hostname->begin + 1); if (g_hash_table_lookup (t, &f) != NULL) { level = dots_num - i - 1; break; @@ -571,31 +689,41 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix } if (level != MAX_LEVELS) { if (level == 0) { - r = rspamd_snprintf (result, len, "%*s", (gint)hostname->len, hostname->begin); + r = rspamd_snprintf (result, + len, + "%*s", + (gint)hostname->len, + hostname->begin); } else { - r = rspamd_snprintf (result, len, "%*s", - (gint)(hostname->len - (dots[level - 1] - hostname->begin + 1)), - dots[level - 1] + 1); + r = rspamd_snprintf (result, len, "%*s", + (gint)(hostname->len - + (dots[level - 1] - hostname->begin + 1)), + dots[level - 1] + 1); } } else if (dots_num >= 2) { r = rspamd_snprintf (result, len, "%*s", - (gint)(hostname->len - (dots[dots_num - 2] - hostname->begin + 1)), + (gint)(hostname->len - + (dots[dots_num - 2] - hostname->begin + 1)), dots[dots_num - 2] + 1); } else { - r = rspamd_snprintf (result, len, "%*s", (gint)hostname->len, hostname->begin); + r = rspamd_snprintf (result, + len, + "%*s", + (gint)hostname->len, + hostname->begin); } } if (tree != NULL) { if (g_tree_lookup (tree, result) != NULL) { msg_debug ("url %s is already registered", result); - g_set_error (err, SURBL_ERROR, /* error domain */ - DUPLICATE_ERROR, /* error code */ - "URL is duplicated: %s", /* error message format string */ - result); + g_set_error (err, SURBL_ERROR, /* error domain */ + DUPLICATE_ERROR, /* error code */ + "URL is duplicated: %s", /* error message format string */ + result); return NULL; } else { @@ -603,12 +731,13 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix } } - if (!forced && g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) { + if (!forced && + g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) { msg_debug ("url %s is whitelisted", result); - g_set_error (err, SURBL_ERROR, /* error domain */ - WHITELIST_ERROR, /* error code */ - "URL is whitelisted: %s", /* error message format string */ - result); + g_set_error (err, SURBL_ERROR, /* error domain */ + WHITELIST_ERROR, /* error code */ + "URL is whitelisted: %s", /* error message format string */ + result); return NULL; } @@ -617,38 +746,48 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix rspamd_snprintf (result + r, len - r, ".%s", suffix->suffix); } - msg_debug ("request: %s, dots: %d, level: %d, orig: %*s", result, dots_num, level, (gint)hostname->len, hostname->begin); + msg_debug ("request: %s, dots: %d, level: %d, orig: %*s", + result, + dots_num, + level, + (gint)hostname->len, + hostname->begin); return result; } static void make_surbl_requests (struct uri *url, struct rspamd_task *task, - struct suffix_item *suffix, gboolean forced, GTree *tree) + struct suffix_item *suffix, gboolean forced, GTree *tree) { - gchar *surbl_req; - f_str_t f; - GError *err = NULL; - struct dns_param *param; + gchar *surbl_req; + f_str_t f; + GError *err = NULL; + struct dns_param *param; f.begin = url->host; f.len = url->hostlen; if ((surbl_req = format_surbl_request (task->task_pool, &f, suffix, TRUE, - &err, forced, tree)) != NULL) { - param = rspamd_mempool_alloc (task->task_pool, sizeof (struct dns_param)); + &err, forced, tree)) != NULL) { + param = + rspamd_mempool_alloc (task->task_pool, sizeof (struct dns_param)); param->url = url; param->task = task; param->suffix = suffix; - param->host_resolve = rspamd_mempool_strdup (task->task_pool, surbl_req); + param->host_resolve = + rspamd_mempool_strdup (task->task_pool, surbl_req); debug_task ("send surbl dns request %s", surbl_req); - if (make_dns_request (task->resolver, task->s, task->task_pool, dns_callback, - (void *)param, RDNS_REQUEST_A, surbl_req)) { - task->dns_requests ++; + if (make_dns_request (task->resolver, task->s, task->task_pool, + dns_callback, + (void *)param, RDNS_REQUEST_A, surbl_req)) { + task->dns_requests++; } } - else if (err != NULL && err->code != WHITELIST_ERROR && err->code != DUPLICATE_ERROR) { - msg_info ("cannot format url string for surbl %s, %s", struri (url), err->message); + else if (err != NULL && err->code != WHITELIST_ERROR && err->code != + DUPLICATE_ERROR) { + msg_info ("cannot format url string for surbl %s, %s", struri ( + url), err->message); g_error_free (err); return; } @@ -658,58 +797,67 @@ make_surbl_requests (struct uri *url, struct rspamd_task *task, } static void -process_dns_results (struct rspamd_task *task, struct suffix_item *suffix, gchar *url, guint32 addr) +process_dns_results (struct rspamd_task *task, + struct suffix_item *suffix, + gchar *url, + guint32 addr) { - GList *cur; - struct surbl_bit_item *bit; + GList *cur; + struct surbl_bit_item *bit; if (suffix->bits != NULL) { cur = g_list_first (suffix->bits); while (cur) { bit = (struct surbl_bit_item *)cur->data; - debug_task ("got result(%d) AND bit(%d): %d", (gint)addr, (gint)ntohl (bit->bit), - (gint)bit->bit & (gint)ntohl (addr)); + debug_task ("got result(%d) AND bit(%d): %d", + (gint)addr, + (gint)ntohl (bit->bit), + (gint)bit->bit & (gint)ntohl (addr)); if (((gint)bit->bit & (gint)ntohl (addr)) != 0) { insert_result (task, bit->symbol, 1, - g_list_prepend (NULL, rspamd_mempool_strdup (task->task_pool, url))); + g_list_prepend (NULL, + rspamd_mempool_strdup (task->task_pool, url))); } cur = g_list_next (cur); } } else { - insert_result (task, suffix->symbol, 1, g_list_prepend (NULL, rspamd_mempool_strdup (task->task_pool, url))); + insert_result (task, suffix->symbol, 1, + g_list_prepend (NULL, + rspamd_mempool_strdup (task->task_pool, url))); } } static void dns_callback (struct rdns_reply *reply, gpointer arg) { - struct dns_param *param = (struct dns_param *)arg; - struct rspamd_task *task = param->task; - struct rdns_reply_entry *elt; + struct dns_param *param = (struct dns_param *)arg; + struct rspamd_task *task = param->task; + struct rdns_reply_entry *elt; debug_task ("in surbl request callback"); /* If we have result from DNS server, this url exists in SURBL, so increase score */ if (reply->code == RDNS_RC_NOERROR && reply->entries) { msg_info ("<%s> domain [%s] is in surbl %s", param->task->message_id, - param->host_resolve, param->suffix->suffix); + param->host_resolve, param->suffix->suffix); elt = reply->entries; if (elt->type == RDNS_REQUEST_A) { process_dns_results (param->task, param->suffix, - param->host_resolve, (guint32)elt->content.a.addr.s_addr); + param->host_resolve, (guint32)elt->content.a.addr.s_addr); } } else { debug_task ("<%s> domain [%s] is not in surbl %s", - param->task->message_id, param->host_resolve, param->suffix->suffix); + param->task->message_id, param->host_resolve, + param->suffix->suffix); } } static void free_redirector_session (void *ud) { - struct redirector_param *param = (struct redirector_param *)ud; + struct redirector_param *param = (struct redirector_param *)ud; event_del (¶m->ev); g_string_free (param->buf, TRUE); @@ -719,38 +867,55 @@ free_redirector_session (void *ud) static void redirector_callback (gint fd, short what, void *arg) { - struct redirector_param *param = (struct redirector_param *)arg; - struct rspamd_task *task = param->task; - gchar url_buf[512]; - gint r; - struct timeval *timeout; - gchar *p, *c; - gboolean found = FALSE; + struct redirector_param *param = (struct redirector_param *)arg; + struct rspamd_task *task = param->task; + gchar url_buf[512]; + gint r; + struct timeval *timeout; + gchar *p, *c; + gboolean found = FALSE; switch (param->state) { case STATE_CONNECT: /* We have write readiness after connect call, so reinit event */ if (what == EV_WRITE) { - timeout = rspamd_mempool_alloc (param->task->task_pool, sizeof (struct timeval)); + timeout = + rspamd_mempool_alloc (param->task->task_pool, + sizeof (struct timeval)); timeout->tv_sec = surbl_module_ctx->read_timeout / 1000; - timeout->tv_usec = (surbl_module_ctx->read_timeout - timeout->tv_sec * 1000) * 1000; + timeout->tv_usec = + (surbl_module_ctx->read_timeout - timeout->tv_sec * + 1000) * 1000; event_del (¶m->ev); - event_set (¶m->ev, param->sock, EV_READ | EV_PERSIST, redirector_callback, (void *)param); + event_set (¶m->ev, + param->sock, + EV_READ | EV_PERSIST, + redirector_callback, + (void *)param); event_add (¶m->ev, timeout); - r = rspamd_snprintf (url_buf, sizeof (url_buf), "GET %s HTTP/1.0\r\n\r\n", struri (param->url)); + r = rspamd_snprintf (url_buf, + sizeof (url_buf), + "GET %s HTTP/1.0\r\n\r\n", + struri (param->url)); if (write (param->sock, url_buf, r) == -1) { - msg_err ("write failed %s to %s", strerror (errno), param->redirector->name); + msg_err ("write failed %s to %s", strerror ( + errno), param->redirector->name); upstream_fail (¶m->redirector->up, param->task->tv.tv_sec); - remove_normal_event (param->task->s, free_redirector_session, param); + remove_normal_event (param->task->s, + free_redirector_session, + param); return; } param->state = STATE_READ; } else { - msg_info ("<%s> connection to redirector %s timed out while waiting for write", - param->task->message_id, param->redirector->name); + msg_info ( + "<%s> connection to redirector %s timed out while waiting for write", + param->task->message_id, + param->redirector->name); upstream_fail (¶m->redirector->up, param->task->tv.tv_sec); - remove_normal_event (param->task->s, free_redirector_session, param); + remove_normal_event (param->task->s, free_redirector_session, + param); return; } @@ -759,10 +924,17 @@ redirector_callback (gint fd, short what, void *arg) if (what == EV_READ) { r = read (param->sock, url_buf, sizeof (url_buf) - 1); if (r <= 0) { - msg_err ("read failed: %s from %s", strerror (errno), param->redirector->name); + msg_err ("read failed: %s from %s", strerror ( + errno), param->redirector->name); upstream_fail (¶m->redirector->up, param->task->tv.tv_sec); - make_surbl_requests (param->url, param->task, param->suffix, FALSE, param->tree); - remove_normal_event (param->task->s, free_redirector_session, param); + make_surbl_requests (param->url, + param->task, + param->suffix, + FALSE, + param->tree); + remove_normal_event (param->task->s, + free_redirector_session, + param); return; } @@ -779,21 +951,36 @@ redirector_callback (gint fd, short what, void *arg) } } if (found) { - debug_task ("<%s> got reply from redirector: '%s' -> '%s'", param->task->message_id, struri (param->url), c); - r = parse_uri (param->url, rspamd_mempool_strdup (param->task->task_pool, c), param->task->task_pool); - if (r == URI_ERRNO_OK || r == URI_ERRNO_NO_SLASHES || r == URI_ERRNO_NO_HOST_SLASH) { - make_surbl_requests (param->url, param->task, param->suffix, FALSE, param->tree); + debug_task ("<%s> got reply from redirector: '%s' -> '%s'", + param->task->message_id, + struri (param->url), + c); + r = + parse_uri (param->url, + rspamd_mempool_strdup (param->task->task_pool, + c), param->task->task_pool); + if (r == URI_ERRNO_OK || r == URI_ERRNO_NO_SLASHES || r == + URI_ERRNO_NO_HOST_SLASH) { + make_surbl_requests (param->url, + param->task, + param->suffix, + FALSE, + param->tree); } } } upstream_ok (¶m->redirector->up, param->task->tv.tv_sec); - remove_normal_event (param->task->s, free_redirector_session, param); + remove_normal_event (param->task->s, free_redirector_session, + param); } else { - msg_info ("<%s> reading redirector %s timed out, while waiting for read", - param->redirector->name, param->task->message_id); + msg_info ( + "<%s> reading redirector %s timed out, while waiting for read", + param->redirector->name, + param->task->message_id); upstream_fail (¶m->redirector->up, param->task->tv.tv_sec); - remove_normal_event (param->task->s, free_redirector_session, param); + remove_normal_event (param->task->s, free_redirector_session, + param); } break; } @@ -802,30 +989,42 @@ redirector_callback (gint fd, short what, void *arg) static void register_redirector_call (struct uri *url, struct rspamd_task *task, - struct suffix_item *suffix, const gchar *rule, GTree *tree) + struct suffix_item *suffix, const gchar *rule, GTree *tree) { - gint s = -1; - struct redirector_param *param; - struct timeval *timeout; - struct redirector_upstream *selected; - - selected = (struct redirector_upstream *)get_upstream_round_robin (surbl_module_ctx->redirectors, - surbl_module_ctx->redirectors_number, - sizeof (struct redirector_upstream), - task->tv.tv_sec, DEFAULT_UPSTREAM_ERROR_TIME, - DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS); + gint s = -1; + struct redirector_param *param; + struct timeval *timeout; + struct redirector_upstream *selected; + + selected = (struct redirector_upstream *)get_upstream_round_robin ( + surbl_module_ctx->redirectors, + surbl_module_ctx->redirectors_number, + sizeof (struct redirector_upstream), + task->tv.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS); if (selected) { - s = make_universal_socket (selected->addr, selected->port, SOCK_STREAM, TRUE, FALSE, FALSE); + s = make_universal_socket (selected->addr, + selected->port, + SOCK_STREAM, + TRUE, + FALSE, + FALSE); } if (s == -1) { - msg_info ("<%s> cannot create tcp socket failed: %s", task->message_id, strerror (errno)); + msg_info ("<%s> cannot create tcp socket failed: %s", + task->message_id, + strerror (errno)); make_surbl_requests (url, task, suffix, FALSE, tree); return; } - param = rspamd_mempool_alloc (task->task_pool, sizeof (struct redirector_param)); + param = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct redirector_param)); param->url = url; param->task = task; param->state = STATE_CONNECT; @@ -836,25 +1035,33 @@ register_redirector_call (struct uri *url, struct rspamd_task *task, param->tree = tree; timeout = rspamd_mempool_alloc (task->task_pool, sizeof (struct timeval)); timeout->tv_sec = surbl_module_ctx->connect_timeout / 1000; - timeout->tv_usec = (surbl_module_ctx->connect_timeout - timeout->tv_sec * 1000) * 1000; + timeout->tv_usec = + (surbl_module_ctx->connect_timeout - timeout->tv_sec * 1000) * 1000; event_set (¶m->ev, s, EV_WRITE, redirector_callback, (void *)param); event_add (¶m->ev, timeout); - register_async_event (task->s, free_redirector_session, param, g_quark_from_static_string ("surbl")); - - msg_info ("<%s> registered redirector call for %s to %s, according to rule: %s", - task->message_id, struri (url), selected->name, rule); + register_async_event (task->s, + free_redirector_session, + param, + g_quark_from_static_string ("surbl")); + + msg_info ( + "<%s> registered redirector call for %s to %s, according to rule: %s", + task->message_id, + struri (url), + selected->name, + rule); } -static gboolean +static gboolean surbl_tree_url_callback (gpointer key, gpointer value, void *data) { - struct redirector_param *param = data; - struct rspamd_task *task; - struct uri *url = value; - gchar *red_domain; - const gchar *pos; - GRegex *re; - guint idx, len; + struct redirector_param *param = data; + struct rspamd_task *task; + struct uri *url = value; + gchar *red_domain; + const gchar *pos; + GRegex *re; + guint idx, len; task = param->task; debug_task ("check url %s", struri (url)); @@ -866,32 +1073,48 @@ surbl_tree_url_callback (gpointer key, gpointer value, void *data) if (surbl_module_ctx->use_redirector) { /* Search in trie */ if (surbl_module_ctx->redirector_trie && - (pos = rspamd_trie_lookup (surbl_module_ctx->redirector_trie, url->host, url->hostlen, &idx)) != NULL && - idx < surbl_module_ctx->redirector_ptrs->len) { + (pos = + rspamd_trie_lookup (surbl_module_ctx->redirector_trie, url->host, + url->hostlen, &idx)) != NULL && + idx < surbl_module_ctx->redirector_ptrs->len) { /* Get corresponding prefix */ - red_domain = g_ptr_array_index (surbl_module_ctx->redirector_ptrs, idx); + red_domain = g_ptr_array_index (surbl_module_ctx->redirector_ptrs, + idx); if (red_domain != NULL) { len = strlen (red_domain); /* First check that we have found domain at the end of host */ if (pos + len == url->host + url->hostlen && (pos == url->host || *(pos - 1) == '.')) { /* Try to find corresponding regexp */ - re = g_hash_table_lookup (surbl_module_ctx->redirector_hosts, red_domain); - if (re != NULL && (re == NO_REGEXP || g_regex_match (re, url->string, 0, NULL))) { + re = g_hash_table_lookup ( + surbl_module_ctx->redirector_hosts, + red_domain); + if (re != NULL && + (re == NO_REGEXP || + g_regex_match (re, url->string, 0, NULL))) { /* If no regexp found or founded regexp matches url string register redirector's call */ if (surbl_module_ctx->redirector_symbol != NULL) { - insert_result (param->task, surbl_module_ctx->redirector_symbol, 1, g_list_prepend (NULL, red_domain)); + insert_result (param->task, + surbl_module_ctx->redirector_symbol, + 1, + g_list_prepend (NULL, red_domain)); } - register_redirector_call (url, param->task, param->suffix, red_domain, param->tree); + register_redirector_call (url, + param->task, + param->suffix, + red_domain, + param->tree); return FALSE; } } } } - make_surbl_requests (url, param->task, param->suffix, FALSE, param->tree); + make_surbl_requests (url, param->task, param->suffix, FALSE, + param->tree); } else { - make_surbl_requests (url, param->task, param->suffix, FALSE, param->tree); + make_surbl_requests (url, param->task, param->suffix, FALSE, + param->tree); } return FALSE; @@ -900,13 +1123,15 @@ surbl_tree_url_callback (gpointer key, gpointer value, void *data) static void surbl_test_url (struct rspamd_task *task, void *user_data) { - struct redirector_param param; - struct suffix_item *suffix = user_data; + struct redirector_param param; + struct suffix_item *suffix = user_data; param.task = task; param.suffix = suffix; param.tree = g_tree_new ((GCompareFunc)strcmp); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_tree_destroy, param.tree); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_tree_destroy, + param.tree); g_tree_foreach (task->urls, surbl_tree_url_callback, ¶m); } /* @@ -914,17 +1139,17 @@ surbl_test_url (struct rspamd_task *task, void *user_data) */ #if 0 struct urls_tree_cb_data { - gchar *buf; - gsize len; - gsize off; - struct rspamd_task *task; + gchar *buf; + gsize len; + gsize off; + struct rspamd_task *task; }; static gboolean calculate_buflen_cb (gpointer key, gpointer value, gpointer cbdata) { - struct urls_tree_cb_data *cb = cbdata; - struct uri *url = value; + struct urls_tree_cb_data *cb = cbdata; + struct uri *url = value; cb->len += strlen (struri (url)) + url->hostlen + sizeof (" <\"\">, ") - 1; @@ -934,23 +1159,30 @@ calculate_buflen_cb (gpointer key, gpointer value, gpointer cbdata) static gboolean write_urls_buffer (gpointer key, gpointer value, gpointer cbdata) { - struct urls_tree_cb_data *cb = cbdata; - struct uri *url = value; - f_str_t f; - gchar *urlstr; - gsize len; + struct urls_tree_cb_data *cb = cbdata; + struct uri *url = value; + f_str_t f; + gchar *urlstr; + gsize len; f.begin = url->host; f.len = url->hostlen; - if ((urlstr = format_surbl_request (cb->task->task_pool, &f, NULL, FALSE, NULL, FALSE)) != NULL) { + if ((urlstr = + format_surbl_request (cb->task->task_pool, &f, NULL, FALSE, NULL, + FALSE)) != NULL) { len = strlen (urlstr); if (cb->off + len >= cb->len) { - msg_info ("cannot write urls header completely, stripped reply at: %z", cb->off); + msg_info ( + "cannot write urls header completely, stripped reply at: %z", + cb->off); return TRUE; } else { - cb->off += rspamd_snprintf (cb->buf + cb->off, cb->len - cb->off, " %s <\"%s\">,", - urlstr, struri (url)); + cb->off += rspamd_snprintf (cb->buf + cb->off, + cb->len - cb->off, + " %s <\"%s\">,", + urlstr, + struri (url)); } } @@ -961,7 +1193,7 @@ write_urls_buffer (gpointer key, gpointer value, gpointer cbdata) static gboolean urls_command_handler (struct rspamd_task *task) { - struct urls_tree_cb_data cb; + struct urls_tree_cb_data cb; /* First calculate buffer length */ cb.len = sizeof (RSPAMD_REPLY_BANNER "/1.0 0 " SPAMD_OK CRLF "Urls: " CRLF); @@ -969,9 +1201,12 @@ urls_command_handler (struct rspamd_task *task) g_tree_foreach (task->urls, calculate_buflen_cb, &cb); cb.buf = rspamd_mempool_alloc (task->task_pool, cb.len * sizeof (gchar)); - cb.off += rspamd_snprintf (cb.buf + cb.off, cb.len - cb.off, "%s/%s 0 %s" CRLF "Urls:", - (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, - "1.3", SPAMD_OK); + cb.off += rspamd_snprintf (cb.buf + cb.off, + cb.len - cb.off, + "%s/%s 0 %s" CRLF "Urls:", + (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, + "1.3", + SPAMD_OK); cb.task = task; /* Write urls to buffer */ @@ -982,10 +1217,12 @@ urls_command_handler (struct rspamd_task *task) cb.buf[--cb.off] = '\0'; } /* Write result */ - if (! rspamd_dispatcher_write (task->dispatcher, cb.buf, cb.off, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (task->dispatcher, cb.buf, cb.off, FALSE, + TRUE)) { return FALSE; } - if (!rspamd_dispatcher_write (task->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (task->dispatcher, CRLF, sizeof (CRLF) - 1, + FALSE, TRUE)) { return FALSE; } task->state = STATE_REPLY; @@ -994,5 +1231,5 @@ urls_command_handler (struct rspamd_task *task) } #endif /* - * vi:ts=4 + * vi:ts=4 */ diff --git a/src/smtp.c b/src/smtp.c index dc3ff6089..98b012e3e 100644 --- a/src/smtp.c +++ b/src/smtp.c @@ -53,26 +53,26 @@ gpointer init_smtp (struct rspamd_config *cfg); void start_smtp (struct rspamd_worker *worker); worker_t smtp_worker = { - "smtp", /* Name */ - init_smtp, /* Init function */ - start_smtp, /* Start function */ - TRUE, /* Has socket */ - FALSE, /* Non unique */ - FALSE, /* Non threaded */ - TRUE, /* Killable */ - SOCK_STREAM /* TCP socket */ + "smtp", /* Name */ + init_smtp, /* Init function */ + start_smtp, /* Start function */ + TRUE, /* Has socket */ + FALSE, /* Non unique */ + FALSE, /* Non threaded */ + TRUE, /* Killable */ + SOCK_STREAM /* TCP socket */ }; static gboolean call_stage_filters (struct smtp_session *session, enum rspamd_smtp_stage stage) { - gboolean res = TRUE; - GList *list = session->ctx->smtp_filters[stage]; - struct smtp_filter *filter; - + gboolean res = TRUE; + GList *list = session->ctx->smtp_filters[stage]; + struct smtp_filter *filter; + while (list) { filter = list->data; - if (! filter->filter (session, filter->filter_data)) { + if (!filter->filter (session, filter->filter_data)) { res = FALSE; break; } @@ -85,144 +85,159 @@ call_stage_filters (struct smtp_session *session, enum rspamd_smtp_stage stage) static gboolean read_smtp_command (struct smtp_session *session, f_str_t *line) { - struct smtp_command *cmd; - gchar outbuf[BUFSIZ]; - gint r; - - if (! parse_smtp_command (session, line, &cmd)) { + struct smtp_command *cmd; + gchar outbuf[BUFSIZ]; + gint r; + + if (!parse_smtp_command (session, line, &cmd)) { session->error = SMTP_ERROR_BAD_COMMAND; - session->errors ++; + session->errors++; return FALSE; } - + switch (cmd->command) { - case SMTP_COMMAND_HELO: - case SMTP_COMMAND_EHLO: - if (session->state == SMTP_STATE_GREETING || session->state == SMTP_STATE_HELO) { - if (parse_smtp_helo (session, cmd)) { - session->state = SMTP_STATE_FROM; - } - else { - session->errors ++; - } - if (! call_stage_filters (session, SMTP_STAGE_HELO)) { - return FALSE; - } - return TRUE; + case SMTP_COMMAND_HELO: + case SMTP_COMMAND_EHLO: + if (session->state == SMTP_STATE_GREETING || session->state == + SMTP_STATE_HELO) { + if (parse_smtp_helo (session, cmd)) { + session->state = SMTP_STATE_FROM; } else { - goto improper_sequence; + session->errors++; } - break; - case SMTP_COMMAND_QUIT: - session->state = SMTP_STATE_QUIT; - break; - case SMTP_COMMAND_NOOP: - break; - case SMTP_COMMAND_MAIL: - if (((session->state == SMTP_STATE_GREETING || session->state == SMTP_STATE_HELO) && !session->ctx->helo_required) - || session->state == SMTP_STATE_FROM) { - if (parse_smtp_from (session, cmd)) { - session->state = SMTP_STATE_RCPT; - } - else { - session->errors ++; - return FALSE; - } - if (! call_stage_filters (session, SMTP_STAGE_MAIL)) { - return FALSE; - } + if (!call_stage_filters (session, SMTP_STAGE_HELO)) { + return FALSE; + } + return TRUE; + } + else { + goto improper_sequence; + } + break; + case SMTP_COMMAND_QUIT: + session->state = SMTP_STATE_QUIT; + break; + case SMTP_COMMAND_NOOP: + break; + case SMTP_COMMAND_MAIL: + if (((session->state == SMTP_STATE_GREETING || session->state == + SMTP_STATE_HELO) && !session->ctx->helo_required) + || session->state == SMTP_STATE_FROM) { + if (parse_smtp_from (session, cmd)) { + session->state = SMTP_STATE_RCPT; } else { - goto improper_sequence; + session->errors++; + return FALSE; } - break; - case SMTP_COMMAND_RCPT: - if (session->state == SMTP_STATE_RCPT) { - if (parse_smtp_rcpt (session, cmd)) { - if (! call_stage_filters (session, SMTP_STAGE_RCPT)) { + if (!call_stage_filters (session, SMTP_STAGE_MAIL)) { + return FALSE; + } + } + else { + goto improper_sequence; + } + break; + case SMTP_COMMAND_RCPT: + if (session->state == SMTP_STATE_RCPT) { + if (parse_smtp_rcpt (session, cmd)) { + if (!call_stage_filters (session, SMTP_STAGE_RCPT)) { + return FALSE; + } + /* Make upstream connection */ + if (session->upstream == NULL) { + if (!create_smtp_upstream_connection (session)) { + session->error = SMTP_ERROR_UPSTREAM; + session->state = SMTP_STATE_CRITICAL_ERROR; return FALSE; } - /* Make upstream connection */ - if (session->upstream == NULL) { - if (!create_smtp_upstream_connection (session)) { - session->error = SMTP_ERROR_UPSTREAM; - session->state = SMTP_STATE_CRITICAL_ERROR; - return FALSE; - } - } - else { - /* Send next rcpt to upstream */ - session->state = SMTP_STATE_WAIT_UPSTREAM; - session->upstream_state = SMTP_STATE_BEFORE_DATA; - rspamd_dispatcher_restore (session->upstream_dispatcher); - r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: "); - r += smtp_upstream_write_list (session->rcpt->data, outbuf + r, sizeof (outbuf) - r); - session->cur_rcpt = NULL; - return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); - } - session->state = SMTP_STATE_WAIT_UPSTREAM; - return TRUE; } else { - session->errors ++; - return FALSE; + /* Send next rcpt to upstream */ + session->state = SMTP_STATE_WAIT_UPSTREAM; + session->upstream_state = SMTP_STATE_BEFORE_DATA; + rspamd_dispatcher_restore (session->upstream_dispatcher); + r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: "); + r += smtp_upstream_write_list (session->rcpt->data, + outbuf + r, + sizeof (outbuf) - r); + session->cur_rcpt = NULL; + return rspamd_dispatcher_write ( + session->upstream_dispatcher, + outbuf, + r, + FALSE, + FALSE); } + session->state = SMTP_STATE_WAIT_UPSTREAM; + return TRUE; } else { - goto improper_sequence; + session->errors++; + return FALSE; } - break; - case SMTP_COMMAND_RSET: - session->from = NULL; - if (session->rcpt) { - g_list_free (session->rcpt); + } + else { + goto improper_sequence; + } + break; + case SMTP_COMMAND_RSET: + session->from = NULL; + if (session->rcpt) { + g_list_free (session->rcpt); + } + if (session->upstream) { + remove_normal_event (session->s, + smtp_upstream_finalize_connection, + session); + session->upstream = NULL; + } + session->state = SMTP_STATE_GREETING; + break; + case SMTP_COMMAND_DATA: + if (session->state == SMTP_STATE_RCPT) { + if (session->rcpt == NULL) { + session->error = SMTP_ERROR_RECIPIENTS; + session->errors++; + return FALSE; } - if (session->upstream) { - remove_normal_event (session->s, smtp_upstream_finalize_connection, session); - session->upstream = NULL; + if (!call_stage_filters (session, SMTP_STAGE_DATA)) { + return FALSE; } - session->state = SMTP_STATE_GREETING; - break; - case SMTP_COMMAND_DATA: - if (session->state == SMTP_STATE_RCPT) { - if (session->rcpt == NULL) { - session->error = SMTP_ERROR_RECIPIENTS; - session->errors ++; - return FALSE; - } - if (! call_stage_filters (session, SMTP_STAGE_DATA)) { - return FALSE; - } - if (session->upstream == NULL) { - session->error = SMTP_ERROR_UPSTREAM; - session->state = SMTP_STATE_CRITICAL_ERROR; - return FALSE; - } - else { - session->upstream_state = SMTP_STATE_DATA; - rspamd_dispatcher_restore (session->upstream_dispatcher); - r = rspamd_snprintf (outbuf, sizeof (outbuf), "DATA" CRLF); - session->state = SMTP_STATE_WAIT_UPSTREAM; - session->error = SMTP_ERROR_DATA_OK; - return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); - } + if (session->upstream == NULL) { + session->error = SMTP_ERROR_UPSTREAM; + session->state = SMTP_STATE_CRITICAL_ERROR; + return FALSE; } else { - goto improper_sequence; + session->upstream_state = SMTP_STATE_DATA; + rspamd_dispatcher_restore (session->upstream_dispatcher); + r = rspamd_snprintf (outbuf, sizeof (outbuf), "DATA" CRLF); + session->state = SMTP_STATE_WAIT_UPSTREAM; + session->error = SMTP_ERROR_DATA_OK; + return rspamd_dispatcher_write (session->upstream_dispatcher, + outbuf, + r, + FALSE, + FALSE); } - case SMTP_COMMAND_VRFY: - case SMTP_COMMAND_EXPN: - case SMTP_COMMAND_HELP: - session->error = SMTP_ERROR_UNIMPLIMENTED; - return FALSE; + } + else { + goto improper_sequence; + } + case SMTP_COMMAND_VRFY: + case SMTP_COMMAND_EXPN: + case SMTP_COMMAND_HELP: + session->error = SMTP_ERROR_UNIMPLIMENTED; + return FALSE; } - + session->error = SMTP_ERROR_OK; return TRUE; improper_sequence: - session->errors ++; + session->errors++; session->error = SMTP_ERROR_SEQUENCE; return FALSE; } @@ -230,11 +245,11 @@ improper_sequence: static gboolean process_smtp_data (struct smtp_session *session) { - struct stat st; - gint r; - GList *cur, *t; - f_str_t *f; - gchar *s; + struct stat st; + gint r; + GList *cur, *t; + f_str_t *f; + gchar *s; if (fstat (session->temp_fd, &st) == -1) { msg_err ("fstat failed: %s", strerror (errno)); @@ -242,17 +257,23 @@ process_smtp_data (struct smtp_session *session) } /* Now mmap temp file if it is small enough */ session->temp_size = st.st_size; - if (session->ctx->max_size == 0 || st.st_size < (off_t)session->ctx->max_size) { + if (session->ctx->max_size == 0 || st.st_size < + (off_t)session->ctx->max_size) { session->task = rspamd_task_new (session->worker); session->task->resolver = session->resolver; session->task->fin_callback = smtp_write_socket; session->task->fin_arg = session; - session->task->msg = rspamd_mempool_alloc (session->pool, sizeof (GString)); + session->task->msg = + rspamd_mempool_alloc (session->pool, sizeof (GString)); session->task->s = session->s; #ifdef HAVE_MMAP_NOCORE - if ((session->task->msg->str = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED | MAP_NOCORE, session->temp_fd, 0)) == MAP_FAILED) { + if ((session->task->msg->str = + mmap (NULL, st.st_size, PROT_READ, MAP_SHARED | MAP_NOCORE, + session->temp_fd, 0)) == MAP_FAILED) { #else - if ((session->task->msg->str = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, session->temp_fd, 0)) == MAP_FAILED) { + if ((session->task->msg->str = + mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, session->temp_fd, + 0)) == MAP_FAILED) { #endif msg_err ("mmap failed: %s", strerror (errno)); goto err; @@ -280,7 +301,8 @@ process_smtp_data (struct smtp_session *session) t = g_list_next (t); } - memcpy (&session->task->from_addr, &session->client_addr, sizeof (struct in_addr)); + memcpy (&session->task->from_addr, &session->client_addr, + sizeof (struct in_addr)); session->task->cmd = CMD_CHECK; if (process_message (session->task) == -1) { @@ -305,7 +327,9 @@ process_smtp_data (struct smtp_session *session) } } else { - msg_info ("not scan message as it is %z bytes and maximum is %z", st.st_size, session->ctx->max_size); + msg_info ("not scan message as it is %z bytes and maximum is %z", + st.st_size, + session->ctx->max_size); session->task = NULL; return smtp_send_upstream_message (session); } @@ -314,7 +338,8 @@ process_smtp_data (struct smtp_session *session) err: session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, + TRUE)) { return FALSE; } destroy_session (session->s); @@ -324,65 +349,74 @@ err: /* * Callback that is called when there is data to read in buffer */ -static gboolean +static gboolean smtp_read_socket (f_str_t * in, void *arg) { - struct smtp_session *session = arg; + struct smtp_session *session = arg; switch (session->state) { - case SMTP_STATE_RESOLVE_REVERSE: - case SMTP_STATE_RESOLVE_NORMAL: - case SMTP_STATE_DELAY: - session->error = make_smtp_error (session->pool, 550, "%s Improper use of SMTP command pipelining", "5.5.0"); - session->state = SMTP_STATE_ERROR; - break; - case SMTP_STATE_GREETING: - case SMTP_STATE_HELO: - case SMTP_STATE_FROM: - case SMTP_STATE_RCPT: - case SMTP_STATE_DATA: - read_smtp_command (session, in); - if (session->state != SMTP_STATE_WAIT_UPSTREAM) { - if (session->errors > session->ctx->max_errors) { - session->error = SMTP_ERROR_LIMIT; - session->state = SMTP_STATE_CRITICAL_ERROR; - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { - return FALSE; - } - destroy_session (session->s); - return FALSE; - } - if (! smtp_write_socket (session)) { + case SMTP_STATE_RESOLVE_REVERSE: + case SMTP_STATE_RESOLVE_NORMAL: + case SMTP_STATE_DELAY: + session->error = make_smtp_error (session->pool, + 550, + "%s Improper use of SMTP command pipelining", + "5.5.0"); + session->state = SMTP_STATE_ERROR; + break; + case SMTP_STATE_GREETING: + case SMTP_STATE_HELO: + case SMTP_STATE_FROM: + case SMTP_STATE_RCPT: + case SMTP_STATE_DATA: + read_smtp_command (session, in); + if (session->state != SMTP_STATE_WAIT_UPSTREAM) { + if (session->errors > session->ctx->max_errors) { + session->error = SMTP_ERROR_LIMIT; + session->state = SMTP_STATE_CRITICAL_ERROR; + if (!rspamd_dispatcher_write (session->dispatcher, + session->error, 0, FALSE, TRUE)) { return FALSE; } + destroy_session (session->s); + return FALSE; } - break; - case SMTP_STATE_AFTER_DATA: - if (in->len == 0) { - return TRUE; - } - if (in->len == 3 && memcmp (in->begin, DATA_END_TRAILER, in->len) == 0) { - return process_smtp_data (session); + if (!smtp_write_socket (session)) { + return FALSE; } + } + break; + case SMTP_STATE_AFTER_DATA: + if (in->len == 0) { + return TRUE; + } + if (in->len == 3 && + memcmp (in->begin, DATA_END_TRAILER, in->len) == 0) { + return process_smtp_data (session); + } - if (write (session->temp_fd, in->begin, in->len) != (ssize_t)in->len) { - msg_err ("cannot write to temp file: %s", strerror (errno)); - session->error = SMTP_ERROR_FILE; - session->state = SMTP_STATE_CRITICAL_ERROR; - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { - return FALSE; - } - destroy_session (session->s); + if (write (session->temp_fd, in->begin, in->len) != (ssize_t)in->len) { + msg_err ("cannot write to temp file: %s", strerror (errno)); + session->error = SMTP_ERROR_FILE; + session->state = SMTP_STATE_CRITICAL_ERROR; + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { return FALSE; } - break; - case SMTP_STATE_WAIT_UPSTREAM: - rspamd_dispatcher_pause (session->dispatcher); - break; - default: - session->error = make_smtp_error (session->pool, 550, "%s Internal error", "5.5.0"); - session->state = SMTP_STATE_ERROR; - break; + destroy_session (session->s); + return FALSE; + } + break; + case SMTP_STATE_WAIT_UPSTREAM: + rspamd_dispatcher_pause (session->dispatcher); + break; + default: + session->error = make_smtp_error (session->pool, + 550, + "%s Internal error", + "5.5.0"); + session->state = SMTP_STATE_ERROR; + break; } if (session->state == SMTP_STATE_QUIT) { @@ -399,14 +433,15 @@ smtp_read_socket (f_str_t * in, void *arg) /* * Callback for socket writing */ -static gboolean +static gboolean smtp_write_socket (void *arg) { - struct smtp_session *session = arg; + struct smtp_session *session = arg; if (session->state == SMTP_STATE_CRITICAL_ERROR) { if (session->error != NULL) { - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { return FALSE; } } @@ -419,7 +454,8 @@ smtp_write_socket (void *arg) } else { if (session->error != NULL) { - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, + session->error, 0, FALSE, TRUE)) { return FALSE; } } @@ -427,12 +463,13 @@ smtp_write_socket (void *arg) } else { if (session->error != NULL) { - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { return FALSE; } } } - + return TRUE; } @@ -442,7 +479,7 @@ smtp_write_socket (void *arg) static void smtp_err_socket (GError * err, void *arg) { - struct smtp_session *session = arg; + struct smtp_session *session = arg; msg_info ("abnormally closing connection, error: %s", err->message); /* Free buffers */ @@ -456,7 +493,8 @@ static gboolean write_smtp_greeting (struct smtp_session *session) { if (session->ctx->smtp_banner) { - if (! rspamd_dispatcher_write (session->dispatcher, session->ctx->smtp_banner, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, + session->ctx->smtp_banner, 0, FALSE, TRUE)) { return FALSE; } } @@ -470,9 +508,11 @@ write_smtp_greeting (struct smtp_session *session) static void smtp_delay_handler (gint fd, short what, void *arg) { - struct smtp_session *session = arg; - - remove_normal_event (session->s, (event_finalizer_t)event_del, session->delay_timer); + struct smtp_session *session = arg; + + remove_normal_event (session->s, + (event_finalizer_t)event_del, + session->delay_timer); if (session->state == SMTP_STATE_DELAY) { session->state = SMTP_STATE_GREETING; write_smtp_greeting (session); @@ -489,9 +529,9 @@ smtp_delay_handler (gint fd, short what, void *arg) static void smtp_make_delay (struct smtp_session *session) { - struct event *tev; - struct timeval *tv; - gint32 jitter; + struct event *tev; + struct timeval *tv; + gint32 jitter; if (session->ctx->smtp_delay != 0 && session->state == SMTP_STATE_DELAY) { tev = rspamd_mempool_alloc (session->pool, sizeof (struct event)); @@ -506,7 +546,10 @@ smtp_make_delay (struct smtp_session *session) evtimer_set (tev, smtp_delay_handler, session); evtimer_add (tev, tv); - register_async_event (session->s, (event_finalizer_t)event_del, tev, g_quark_from_static_string ("smtp proxy")); + register_async_event (session->s, + (event_finalizer_t)event_del, + tev, + g_quark_from_static_string ("smtp proxy")); session->delay_timer = tev; } else if (session->state == SMTP_STATE_DELAY) { @@ -521,83 +564,98 @@ smtp_make_delay (struct smtp_session *session) static void smtp_dns_cb (struct rspamd_dns_reply *reply, void *arg) { - struct smtp_session *session = arg; - gint res = 0; - union rspamd_reply_element *elt; - GList *cur; + struct smtp_session *session = arg; + gint res = 0; + union rspamd_reply_element *elt; + GList *cur; switch (session->state) { - case SMTP_STATE_RESOLVE_REVERSE: - /* Parse reverse reply and start resolve of this ip */ - if (reply->code != RDNS_RC_NOERROR) { - rspamd_conditional_debug(rspamd_main->logger, session->client_addr.s_addr, __FUNCTION__, - "DNS error: %s", dns_strerror (reply->code)); - - if (reply->code == RDNS_RC_NXDOMAIN) { - session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_UNAVAILABLE); - } - else { - session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_TEMPFAIL); - } - session->state = SMTP_STATE_DELAY; - smtp_make_delay (session); + case SMTP_STATE_RESOLVE_REVERSE: + /* Parse reverse reply and start resolve of this ip */ + if (reply->code != RDNS_RC_NOERROR) { + rspamd_conditional_debug (rspamd_main->logger, + session->client_addr.s_addr, + __FUNCTION__, + "DNS error: %s", + dns_strerror (reply->code)); + + if (reply->code == RDNS_RC_NXDOMAIN) { + session->hostname = rspamd_mempool_strdup (session->pool, + XCLIENT_HOST_UNAVAILABLE); } else { - if (reply->elements) { - elt = reply->elements->data; - session->hostname = rspamd_mempool_strdup (session->pool, elt->ptr.name); - session->state = SMTP_STATE_RESOLVE_NORMAL; - make_dns_request (session->resolver, session->s, session->pool, - smtp_dns_cb, session, RDNS_REQUEST_A, session->hostname); - - } + session->hostname = rspamd_mempool_strdup (session->pool, + XCLIENT_HOST_TEMPFAIL); } - break; - case SMTP_STATE_RESOLVE_NORMAL: - if (reply->code != RDNS_RC_NOERROR) { - rspamd_conditional_debug(rspamd_main->logger, session->client_addr.s_addr, __FUNCTION__, - "DNS error: %s", dns_strerror (reply->code)); + session->state = SMTP_STATE_DELAY; + smtp_make_delay (session); + } + else { + if (reply->elements) { + elt = reply->elements->data; + session->hostname = rspamd_mempool_strdup (session->pool, + elt->ptr.name); + session->state = SMTP_STATE_RESOLVE_NORMAL; + make_dns_request (session->resolver, session->s, session->pool, + smtp_dns_cb, session, RDNS_REQUEST_A, session->hostname); - if (reply->code == RDNS_RC_NXDOMAIN) { - session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_UNAVAILABLE); - } - else { - session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_TEMPFAIL); - } - session->state = SMTP_STATE_DELAY; - smtp_make_delay (session); + } + } + break; + case SMTP_STATE_RESOLVE_NORMAL: + if (reply->code != RDNS_RC_NOERROR) { + rspamd_conditional_debug (rspamd_main->logger, + session->client_addr.s_addr, + __FUNCTION__, + "DNS error: %s", + dns_strerror (reply->code)); + + if (reply->code == RDNS_RC_NXDOMAIN) { + session->hostname = rspamd_mempool_strdup (session->pool, + XCLIENT_HOST_UNAVAILABLE); } else { - res = 0; - cur = reply->elements; - while (cur) { - elt = cur->data; - if (memcmp (&session->client_addr, &elt->a.addr[0], sizeof (struct in_addr)) == 0) { - res = 1; - session->resolved = TRUE; - break; - } - cur = g_list_next (cur); + session->hostname = rspamd_mempool_strdup (session->pool, + XCLIENT_HOST_TEMPFAIL); + } + session->state = SMTP_STATE_DELAY; + smtp_make_delay (session); + } + else { + res = 0; + cur = reply->elements; + while (cur) { + elt = cur->data; + if (memcmp (&session->client_addr, &elt->a.addr[0], + sizeof (struct in_addr)) == 0) { + res = 1; + session->resolved = TRUE; + break; } + cur = g_list_next (cur); + } - if (res == 0) { - msg_info ("cannot find address for hostname: %s, ip: %s", session->hostname, inet_ntoa (session->client_addr)); - session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_UNAVAILABLE); - } - session->state = SMTP_STATE_DELAY; - smtp_make_delay (session); + if (res == 0) { + msg_info ("cannot find address for hostname: %s, ip: %s", + session->hostname, + inet_ntoa (session->client_addr)); + session->hostname = rspamd_mempool_strdup (session->pool, + XCLIENT_HOST_UNAVAILABLE); } - break; - case SMTP_STATE_ERROR: - session->state = SMTP_STATE_WRITE_ERROR; - smtp_write_socket (session); - break; - default: - /* - * This callback is called on unknown state, usually this indicates - * an error (invalid pipelining) - */ - break; + session->state = SMTP_STATE_DELAY; + smtp_make_delay (session); + } + break; + case SMTP_STATE_ERROR: + session->state = SMTP_STATE_WRITE_ERROR; + smtp_write_socket (session); + break; + default: + /* + * This callback is called on unknown state, usually this indicates + * an error (invalid pipelining) + */ + break; } } @@ -607,15 +665,16 @@ smtp_dns_cb (struct rspamd_dns_reply *reply, void *arg) static void accept_socket (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *)arg; - union sa_union su; - struct smtp_session *session; - struct smtp_worker_ctx *ctx; + struct rspamd_worker *worker = (struct rspamd_worker *)arg; + union sa_union su; + struct smtp_session *session; + struct smtp_worker_ctx *ctx; - socklen_t addrlen = sizeof (su.ss); - gint nfd; + socklen_t addrlen = sizeof (su.ss); + gint nfd; - if ((nfd = accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) { + if ((nfd = + accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) { msg_warn ("accept failed: %s", strerror (errno)); return; } @@ -633,8 +692,10 @@ accept_socket (gint fd, short what, void *arg) session->client_addr.s_addr = INADDR_NONE; } else if (su.ss.ss_family == AF_INET) { - msg_info ("accepted connection from %s port %d", inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port)); - memcpy (&session->client_addr, &su.s4.sin_addr, sizeof (struct in_addr)); + msg_info ("accepted connection from %s port %d", + inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port)); + memcpy (&session->client_addr, &su.s4.sin_addr, + sizeof (struct in_addr)); } session->sock = nfd; @@ -649,18 +710,28 @@ accept_socket (gint fd, short what, void *arg) /* Resolve client's addr */ /* Set up async session */ - session->s = new_async_session (session->pool, NULL, NULL, free_smtp_session, session); + session->s = new_async_session (session->pool, + NULL, + NULL, + free_smtp_session, + session); session->state = SMTP_STATE_RESOLVE_REVERSE; - if (! make_dns_request (session->resolver, session->s, session->pool, - smtp_dns_cb, session, RDNS_REQUEST_PTR, &session->client_addr)) { + if (!make_dns_request (session->resolver, session->s, session->pool, + smtp_dns_cb, session, RDNS_REQUEST_PTR, &session->client_addr)) { msg_err ("cannot resolve %s", inet_ntoa (session->client_addr)); g_free (session); close (nfd); return; } else { - session->dispatcher = rspamd_create_dispatcher (session->ev_base, nfd, BUFFER_LINE, - smtp_read_socket, smtp_write_socket, smtp_err_socket, &session->ctx->smtp_timeout, session); + session->dispatcher = rspamd_create_dispatcher (session->ev_base, + nfd, + BUFFER_LINE, + smtp_read_socket, + smtp_write_socket, + smtp_err_socket, + &session->ctx->smtp_timeout, + session); session->dispatcher->peer_addr = session->client_addr.s_addr; } } @@ -668,41 +739,41 @@ accept_socket (gint fd, short what, void *arg) static void parse_smtp_banner (struct smtp_worker_ctx *ctx, const gchar *line) { - gint hostmax, banner_len = sizeof ("220 ") - 1; - gchar *p, *t, *hostbuf = NULL; - gboolean has_crlf = FALSE; + gint hostmax, banner_len = sizeof ("220 ") - 1; + gchar *p, *t, *hostbuf = NULL; + gboolean has_crlf = FALSE; p = (gchar *)line; while (*p) { if (*p == '%') { - p ++; + p++; switch (*p) { - case 'n': - /* Assume %n as CRLF */ - banner_len += sizeof (CRLF) - 1 + sizeof ("220 -") - 1; - has_crlf = TRUE; - break; - case 'h': - hostmax = sysconf (_SC_HOST_NAME_MAX) + 1; - hostbuf = alloca (hostmax); - gethostname (hostbuf, hostmax); - hostbuf[hostmax - 1] = '\0'; - banner_len += strlen (hostbuf); - break; - case '%': - banner_len += 1; - break; - default: - banner_len += 2; - break; + case 'n': + /* Assume %n as CRLF */ + banner_len += sizeof (CRLF) - 1 + sizeof ("220 -") - 1; + has_crlf = TRUE; + break; + case 'h': + hostmax = sysconf (_SC_HOST_NAME_MAX) + 1; + hostbuf = alloca (hostmax); + gethostname (hostbuf, hostmax); + hostbuf[hostmax - 1] = '\0'; + banner_len += strlen (hostbuf); + break; + case '%': + banner_len += 1; + break; + default: + banner_len += 2; + break; } } else { - banner_len ++; + banner_len++; } - p ++; + p++; } - + if (has_crlf) { banner_len += sizeof (CRLF "220 " CRLF); } @@ -723,30 +794,30 @@ parse_smtp_banner (struct smtp_worker_ctx *ctx, const gchar *line) while (*p) { if (*p == '%') { - p ++; + p++; switch (*p) { - case 'n': - /* Assume %n as CRLF */ - *t++ = CR; *t++ = LF; - t = g_stpcpy (t, "220-"); - p ++; - break; - case 'h': - t = g_stpcpy (t, hostbuf); - p ++; - break; - case '%': - *t++ = '%'; - p ++; - break; - default: - /* Copy all %<gchar> to dest */ - *t++ = *(p - 1); *t++ = *p; - break; + case 'n': + /* Assume %n as CRLF */ + *t++ = CR; *t++ = LF; + t = g_stpcpy (t, "220-"); + p++; + break; + case 'h': + t = g_stpcpy (t, hostbuf); + p++; + break; + case '%': + *t++ = '%'; + p++; + break; + default: + /* Copy all %<gchar> to dest */ + *t++ = *(p - 1); *t++ = *p; + break; } } else { - *t ++ = *p ++; + *t++ = *p++; } } if (has_crlf) { @@ -760,12 +831,12 @@ parse_smtp_banner (struct smtp_worker_ctx *ctx, const gchar *line) static void make_capabilities (struct smtp_worker_ctx *ctx, const gchar *line) { - gchar **strv, *p, *result, *hostbuf; - guint32 num, i, len, hostmax; + gchar **strv, *p, *result, *hostbuf; + guint32 num, i, len, hostmax; strv = g_strsplit_set (line, ",;", -1); num = g_strv_length (strv); - + hostmax = sysconf (_SC_HOST_NAME_MAX) + 1; hostbuf = alloca (hostmax); gethostname (hostbuf, hostmax); @@ -773,26 +844,32 @@ make_capabilities (struct smtp_worker_ctx *ctx, const gchar *line) len = sizeof ("250-") + strlen (hostbuf) + sizeof (CRLF) - 1; - for (i = 0; i < num; i ++) { + for (i = 0; i < num; i++) { p = strv[i]; len += sizeof ("250-") + sizeof (CRLF) + strlen (p) - 2; } result = rspamd_mempool_alloc (ctx->pool, len); ctx->smtp_capabilities = result; - + p = result; if (num == 0) { p += rspamd_snprintf (p, len - (p - result), "250 %s" CRLF, hostbuf); } else { p += rspamd_snprintf (p, len - (p - result), "250-%s" CRLF, hostbuf); - for (i = 0; i < num; i ++) { + for (i = 0; i < num; i++) { if (i != num - 1) { - p += rspamd_snprintf (p, len - (p - result), "250-%s" CRLF, strv[i]); + p += rspamd_snprintf (p, + len - (p - result), + "250-%s" CRLF, + strv[i]); } else { - p += rspamd_snprintf (p, len - (p - result), "250 %s" CRLF, strv[i]); + p += rspamd_snprintf (p, + len - (p - result), + "250 %s" CRLF, + strv[i]); } } } @@ -803,14 +880,14 @@ make_capabilities (struct smtp_worker_ctx *ctx, const gchar *line) gpointer init_smtp (struct rspamd_config *cfg) { - struct smtp_worker_ctx *ctx; - GQuark type; + struct smtp_worker_ctx *ctx; + GQuark type; type = g_quark_try_string ("smtp"); ctx = g_malloc0 (sizeof (struct smtp_worker_ctx)); ctx->pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); - + /* Set default values */ ctx->smtp_timeout_raw = 300000; ctx->smtp_delay = 0; @@ -820,44 +897,49 @@ init_smtp (struct rspamd_config *cfg) ctx->reject_message = DEFAULT_REJECT_MESSAGE; rspamd_rcl_register_worker_option (cfg, type, "upstreams", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, upstreams_str), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, upstreams_str), 0); rspamd_rcl_register_worker_option (cfg, type, "banner", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_banner_str), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_banner_str), 0); rspamd_rcl_register_worker_option (cfg, type, "timeout", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_timeout_raw), RSPAMD_CL_FLAG_TIME_UINT_32); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, + smtp_timeout_raw), RSPAMD_CL_FLAG_TIME_UINT_32); rspamd_rcl_register_worker_option (cfg, type, "delay", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_delay), RSPAMD_CL_FLAG_TIME_UINT_32); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, + smtp_delay), RSPAMD_CL_FLAG_TIME_UINT_32); rspamd_rcl_register_worker_option (cfg, type, "jitter", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, delay_jitter), RSPAMD_CL_FLAG_TIME_UINT_32); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, + delay_jitter), RSPAMD_CL_FLAG_TIME_UINT_32); rspamd_rcl_register_worker_option (cfg, type, "capabilities", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_capabilities_str), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_capabilities_str), 0); rspamd_rcl_register_worker_option (cfg, type, "xclient", - rspamd_rcl_parse_struct_boolean, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, use_xclient), 0); + rspamd_rcl_parse_struct_boolean, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, use_xclient), 0); rspamd_rcl_register_worker_option (cfg, type, "reject_message", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, reject_message), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, reject_message), 0); rspamd_rcl_register_worker_option (cfg, type, "max_errors", - rspamd_rcl_parse_struct_integer, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, max_errors), RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_parse_struct_integer, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, + max_errors), RSPAMD_CL_FLAG_INT_32); rspamd_rcl_register_worker_option (cfg, type, "max_size", - rspamd_rcl_parse_struct_integer, ctx, - G_STRUCT_OFFSET (struct smtp_worker_ctx, max_size), RSPAMD_CL_FLAG_INT_SIZE); + rspamd_rcl_parse_struct_integer, ctx, + G_STRUCT_OFFSET (struct smtp_worker_ctx, + max_size), RSPAMD_CL_FLAG_INT_SIZE); return ctx; } @@ -866,15 +948,16 @@ init_smtp (struct rspamd_config *cfg) static gboolean config_smtp_worker (struct rspamd_worker *worker) { - struct smtp_worker_ctx *ctx = worker->ctx; - gchar *value; + struct smtp_worker_ctx *ctx = worker->ctx; + gchar *value; /* Init timeval */ msec_to_tv (ctx->smtp_timeout_raw, &ctx->smtp_timeout); /* Init upstreams */ if ((value = ctx->upstreams_str) != NULL) { - if (!parse_upstreams_line (ctx->pool, ctx->upstreams, value, &ctx->upstream_num)) { + if (!parse_upstreams_line (ctx->pool, ctx->upstreams, value, + &ctx->upstream_num)) { return FALSE; } } @@ -891,7 +974,7 @@ config_smtp_worker (struct rspamd_worker *worker) if ((value = ctx->smtp_capabilities_str) != NULL) { make_capabilities (ctx, value); } - + return TRUE; } @@ -902,7 +985,7 @@ config_smtp_worker (struct rspamd_worker *worker) void start_smtp (struct rspamd_worker *worker) { - struct smtp_worker_ctx *ctx = worker->ctx; + struct smtp_worker_ctx *ctx = worker->ctx; ctx->ev_base = rspamd_prepare_worker (worker, "smtp_worker", accept_socket); @@ -922,15 +1005,18 @@ start_smtp (struct rspamd_worker *worker) umask (S_IWGRP | S_IWOTH | S_IROTH | S_IRGRP); event_base_loop (ctx->ev_base, 0); - + close_log (rspamd_main->logger); exit (EXIT_SUCCESS); } -void -register_smtp_filter (struct smtp_worker_ctx *ctx, enum rspamd_smtp_stage stage, smtp_filter_t filter, gpointer filter_data) +void +register_smtp_filter (struct smtp_worker_ctx *ctx, + enum rspamd_smtp_stage stage, + smtp_filter_t filter, + gpointer filter_data) { - struct smtp_filter *new; + struct smtp_filter *new; new = rspamd_mempool_alloc (ctx->pool, sizeof (struct smtp_filter)); @@ -941,10 +1027,11 @@ register_smtp_filter (struct smtp_worker_ctx *ctx, enum rspamd_smtp_stage stage, msg_err ("invalid smtp stage: %d", stage); } else { - ctx->smtp_filters[stage] = g_list_prepend (ctx->smtp_filters[stage], new); + ctx->smtp_filters[stage] = + g_list_prepend (ctx->smtp_filters[stage], new); } } -/* - * vi:ts=4 +/* + * vi:ts=4 */ diff --git a/src/smtp.h b/src/smtp.h index 482f5243d..4f549dda1 100644 --- a/src/smtp.h +++ b/src/smtp.h @@ -23,7 +23,7 @@ struct smtp_worker_ctx { struct smtp_upstream upstreams[MAX_SMTP_UPSTREAMS]; gsize upstream_num; gchar *upstreams_str; - + rspamd_mempool_t *pool; gchar *smtp_banner; gchar *smtp_banner_str; @@ -90,7 +90,7 @@ struct smtp_session { GList *cur_rcpt; guint errors; - + struct rspamd_async_session *s; rspamd_io_dispatcher_t *dispatcher; rspamd_io_dispatcher_t *upstream_dispatcher; @@ -105,7 +105,8 @@ struct smtp_session { struct event_base *ev_base; }; -typedef gboolean (*smtp_filter_t)(struct smtp_session *session, gpointer filter_data); +typedef gboolean (*smtp_filter_t)(struct smtp_session *session, + gpointer filter_data); struct smtp_filter { smtp_filter_t filter; @@ -116,6 +117,9 @@ struct smtp_filter { * Register new SMTP filter * XXX: work is still in progress */ -void register_smtp_filter (struct smtp_worker_ctx *ctx, enum rspamd_smtp_stage stage, smtp_filter_t filter, gpointer filter_data); +void register_smtp_filter (struct smtp_worker_ctx *ctx, + enum rspamd_smtp_stage stage, + smtp_filter_t filter, + gpointer filter_data); #endif diff --git a/src/smtp_proxy.c b/src/smtp_proxy.c index c2df491b6..0b7660a81 100644 --- a/src/smtp_proxy.c +++ b/src/smtp_proxy.c @@ -53,14 +53,14 @@ gpointer init_smtp_proxy (struct rspamd_config *cfg); void start_smtp_proxy (struct rspamd_worker *worker); worker_t smtp_proxy_worker = { - "smtp_proxy", /* Name */ - init_smtp_proxy, /* Init function */ - start_smtp_proxy, /* Start function */ - TRUE, /* Has socket */ - FALSE, /* Non unique */ - FALSE, /* Non threaded */ - TRUE, /* Killable */ - SOCK_STREAM /* TCP socket */ + "smtp_proxy", /* Name */ + init_smtp_proxy, /* Init function */ + start_smtp_proxy, /* Start function */ + TRUE, /* Has socket */ + FALSE, /* Non unique */ + FALSE, /* Non threaded */ + TRUE, /* Killable */ + SOCK_STREAM /* TCP socket */ }; struct smtp_proxy_ctx { @@ -140,7 +140,7 @@ struct smtp_proxy_session { static void free_smtp_proxy_session (gpointer arg) { - struct smtp_proxy_session *session = arg; + struct smtp_proxy_session *session = arg; static const char fatal_smtp_error[] = "521 5.2.1 Internal error" CRLF; if (session) { @@ -152,17 +152,23 @@ free_smtp_proxy_session (gpointer arg) g_string_free (session->upstream_greeting, TRUE); } - if (session->state != SMTP_PROXY_STATE_PROXY && session->state != SMTP_PROXY_STATE_REJECT && - session->state != SMTP_PROXY_STATE_REJECT_EMULATE) { + if (session->state != SMTP_PROXY_STATE_PROXY && session->state != + SMTP_PROXY_STATE_REJECT && + session->state != SMTP_PROXY_STATE_REJECT_EMULATE) { /* Send 521 fatal error */ - if (write (session->sock, fatal_smtp_error, sizeof (fatal_smtp_error)) == -1) { + if (write (session->sock, fatal_smtp_error, + sizeof (fatal_smtp_error)) == -1) { msg_err ("write error to client failed: %s", strerror (errno)); } } - else if ((session->state == SMTP_PROXY_STATE_REJECT || session->state == SMTP_PROXY_STATE_REJECT_EMULATE) && - session->from && session->rcpt && session->dnsbl_applied) { - msg_info ("reject by %s mail from <%s> to <%s>, ip: %s", session->dnsbl_applied, - session->from, session->rcpt, inet_ntoa (session->client_addr)); + else if ((session->state == SMTP_PROXY_STATE_REJECT || session->state == + SMTP_PROXY_STATE_REJECT_EMULATE) && + session->from && session->rcpt && session->dnsbl_applied) { + msg_info ("reject by %s mail from <%s> to <%s>, ip: %s", + session->dnsbl_applied, + session->from, + session->rcpt, + inet_ntoa (session->client_addr)); } close (session->sock); @@ -185,7 +191,7 @@ free_smtp_proxy_session (gpointer arg) static void smtp_proxy_err_proxy (GError * err, void *arg) { - struct smtp_proxy_session *session = arg; + struct smtp_proxy_session *session = arg; if (err) { g_error_free (err); @@ -204,7 +210,7 @@ smtp_proxy_err_proxy (GError * err, void *arg) static gint check_valid_smtp_greeting (GString *s) { - gchar *p; + gchar *p; p = s->str + s->len - 1; if (s->len < 6 || (*p != '\n' || *(p - 1) != '\r')) { @@ -222,10 +228,10 @@ check_valid_smtp_greeting (GString *s) return 0; } else if ((*p == '5' || *p == '4' || *p == '3') && - g_ascii_isdigit (p[1]) && g_ascii_isdigit (p[2]) && p[3] == ' ') { + g_ascii_isdigit (p[1]) && g_ascii_isdigit (p[2]) && p[3] == ' ') { return -1; } - p --; + p--; } return 1; @@ -238,9 +244,9 @@ check_valid_smtp_greeting (GString *s) static void smtp_proxy_greeting_handler (gint fd, short what, void *arg) { - struct smtp_proxy_session *session = arg; - gint r; - gchar read_buf[BUFSIZ]; + struct smtp_proxy_session *session = arg; + gint r; + gchar read_buf[BUFSIZ]; if (what == EV_READ) { if (session->state == SMTP_PROXY_STATE_GREETING) { @@ -253,16 +259,23 @@ smtp_proxy_greeting_handler (gint fd, short what, void *arg) if (r == 1) { /* Send xclient */ if (session->ctx->use_xclient) { - r = rspamd_snprintf (read_buf, sizeof (read_buf), "XCLIENT NAME=%s ADDR=%s" CRLF, - session->hostname, inet_ntoa (session->client_addr)); + r = rspamd_snprintf (read_buf, + sizeof (read_buf), + "XCLIENT NAME=%s ADDR=%s" CRLF, + session->hostname, + inet_ntoa (session->client_addr)); r = write (session->upstream_sock, read_buf, r); if (r < 0 && errno == EAGAIN) { /* Add write event */ event_del (&session->upstream_ev); - event_set (&session->upstream_ev, session->upstream_sock, - EV_WRITE, smtp_proxy_greeting_handler, session); - event_base_set (session->ev_base, &session->upstream_ev); + event_set (&session->upstream_ev, + session->upstream_sock, + EV_WRITE, + smtp_proxy_greeting_handler, + session); + event_base_set (session->ev_base, + &session->upstream_ev); event_add (&session->upstream_ev, NULL); } else if (r > 0) { @@ -270,35 +283,49 @@ smtp_proxy_greeting_handler (gint fd, short what, void *arg) session->state = SMTP_PROXY_STATE_XCLIENT; } else { - msg_info ("connection with %s got write error: %s", inet_ntoa (session->client_addr), strerror (errno)); + msg_info ("connection with %s got write error: %s", + inet_ntoa (session->client_addr), + strerror (errno)); destroy_session (session->s); } } else { event_del (&session->upstream_ev); /* Start direct proxy */ - r = write (session->sock, session->upstream_greeting->str, session->upstream_greeting->len); + r = write (session->sock, + session->upstream_greeting->str, + session->upstream_greeting->len); /* TODO: handle client's error here */ if (r > 0) { - session->proxy = rspamd_create_proxy (session->sock, session->upstream_sock, session->pool, - session->ev_base, session->ctx->proxy_buf_len, - &session->ctx->smtp_timeout, smtp_proxy_err_proxy, session); + session->proxy = rspamd_create_proxy (session->sock, + session->upstream_sock, + session->pool, + session->ev_base, + session->ctx->proxy_buf_len, + &session->ctx->smtp_timeout, + smtp_proxy_err_proxy, + session); session->state = SMTP_PROXY_STATE_PROXY; } else { - msg_info ("connection with %s got write error: %s", inet_ntoa (session->client_addr), strerror (errno)); + msg_info ("connection with %s got write error: %s", + inet_ntoa (session->client_addr), + strerror (errno)); destroy_session (session->s); } } } else if (r == -1) { /* Proxy sent 500 error */ - msg_info ("connection with %s got smtp error for greeting", session->upstream->name); + msg_info ("connection with %s got smtp error for greeting", + session->upstream->name); destroy_session (session->s); } } else { - msg_info ("connection with %s got read error: %s", session->upstream->name, strerror (errno)); + msg_info ("connection with %s got read error: %s", + session->upstream->name, + strerror (errno)); destroy_session (session->s); } } @@ -312,43 +339,58 @@ smtp_proxy_greeting_handler (gint fd, short what, void *arg) if (r == 1) { event_del (&session->upstream_ev); /* Start direct proxy */ - r = write (session->sock, session->upstream_greeting->str, session->upstream_greeting->len); + r = write (session->sock, + session->upstream_greeting->str, + session->upstream_greeting->len); /* TODO: handle client's error here */ if (r > 0) { - session->proxy = rspamd_create_proxy (session->sock, session->upstream_sock, session->pool, - session->ev_base, session->ctx->proxy_buf_len, - &session->ctx->smtp_timeout, smtp_proxy_err_proxy, session); + session->proxy = rspamd_create_proxy (session->sock, + session->upstream_sock, + session->pool, + session->ev_base, + session->ctx->proxy_buf_len, + &session->ctx->smtp_timeout, + smtp_proxy_err_proxy, + session); session->state = SMTP_PROXY_STATE_PROXY; } else { - msg_info ("connection with %s got write error: %s", inet_ntoa (session->client_addr), strerror (errno)); + msg_info ("connection with %s got write error: %s", + inet_ntoa (session->client_addr), + strerror (errno)); destroy_session (session->s); } } else if (r == -1) { /* Proxy sent 500 error */ - msg_info ("connection with %s got smtp error for xclient", session->upstream->name); + msg_info ("connection with %s got smtp error for xclient", + session->upstream->name); destroy_session (session->s); } } } else { - msg_info ("connection with %s got read event at improper state: %d", session->upstream->name, session->state); + msg_info ("connection with %s got read event at improper state: %d", + session->upstream->name, + session->state); destroy_session (session->s); } } else if (what == EV_WRITE) { if (session->state == SMTP_PROXY_STATE_GREETING) { /* Send xclient again */ - r = rspamd_snprintf (read_buf, sizeof (read_buf), "XCLIENT NAME=%s ADDR=%s" CRLF, - session->hostname, inet_ntoa (session->client_addr)); + r = rspamd_snprintf (read_buf, + sizeof (read_buf), + "XCLIENT NAME=%s ADDR=%s" CRLF, + session->hostname, + inet_ntoa (session->client_addr)); r = write (session->upstream_sock, read_buf, r); if (r < 0 && errno == EAGAIN) { /* Add write event */ event_del (&session->upstream_ev); event_set (&session->upstream_ev, session->upstream_sock, - EV_WRITE, smtp_proxy_greeting_handler, session); + EV_WRITE, smtp_proxy_greeting_handler, session); event_base_set (session->ev_base, &session->upstream_ev); event_add (&session->upstream_ev, NULL); } @@ -357,17 +399,22 @@ smtp_proxy_greeting_handler (gint fd, short what, void *arg) session->state = SMTP_PROXY_STATE_XCLIENT; event_del (&session->upstream_ev); event_set (&session->upstream_ev, session->upstream_sock, - EV_READ | EV_PERSIST, smtp_proxy_greeting_handler, session); + EV_READ | EV_PERSIST, smtp_proxy_greeting_handler, session); event_base_set (session->ev_base, &session->upstream_ev); event_add (&session->upstream_ev, NULL); } else { - msg_info ("connection with %s got write error: %s", session->upstream->name, strerror (errno)); + msg_info ("connection with %s got write error: %s", + session->upstream->name, + strerror (errno)); destroy_session (session->s); } } else { - msg_info ("connection with %s got write event at improper state: %d", session->upstream->name, session->state); + msg_info ( + "connection with %s got write event at improper state: %d", + session->upstream->name, + session->state); destroy_session (session->s); } } @@ -381,12 +428,17 @@ smtp_proxy_greeting_handler (gint fd, short what, void *arg) static gboolean create_smtp_proxy_upstream_connection (struct smtp_proxy_session *session) { - struct smtp_upstream *selected; + struct smtp_upstream *selected; /* Try to select upstream */ - selected = (struct smtp_upstream *)get_upstream_round_robin (session->ctx->upstreams, - session->ctx->upstream_num, sizeof (struct smtp_upstream), - time (NULL), DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS); + selected = (struct smtp_upstream *)get_upstream_round_robin ( + session->ctx->upstreams, + session->ctx->upstream_num, + sizeof (struct smtp_upstream), + time (NULL), + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS); if (selected == NULL) { msg_err ("no upstreams suitable found"); return FALSE; @@ -395,7 +447,12 @@ create_smtp_proxy_upstream_connection (struct smtp_proxy_session *session) session->upstream = selected; /* Now try to create socket */ - session->upstream_sock = make_universal_socket (selected->name, selected->port, SOCK_STREAM, TRUE, FALSE, FALSE); + session->upstream_sock = make_universal_socket (selected->name, + selected->port, + SOCK_STREAM, + TRUE, + FALSE, + FALSE); if (session->upstream_sock == -1) { msg_err ("cannot make a connection to %s", selected->name); upstream_fail (&selected->up, time (NULL)); @@ -406,7 +463,11 @@ create_smtp_proxy_upstream_connection (struct smtp_proxy_session *session) /* First of all get upstream's greeting */ session->state = SMTP_PROXY_STATE_GREETING; - event_set (&session->upstream_ev, session->upstream_sock, EV_READ | EV_PERSIST, smtp_proxy_greeting_handler, session); + event_set (&session->upstream_ev, + session->upstream_sock, + EV_READ | EV_PERSIST, + smtp_proxy_greeting_handler, + session); event_base_set (session->ev_base, &session->upstream_ev); event_add (&session->upstream_ev, &session->ctx->smtp_timeout); @@ -418,16 +479,17 @@ create_smtp_proxy_upstream_connection (struct smtp_proxy_session *session) static void smtp_dnsbl_cb (struct rdns_reply *reply, void *arg) { - struct smtp_proxy_session *session = arg; - const gchar *p; - gint dots = 0; - const struct rdns_request_name *req_name; + struct smtp_proxy_session *session = arg; + const gchar *p; + gint dots = 0; + const struct rdns_request_name *req_name; - session->rbl_requests --; + session->rbl_requests--; req_name = rdns_request_get_name (reply->request, NULL); - msg_debug ("got reply for %s: %s", req_name[0].name, rdns_strerror (reply->code)); + msg_debug ("got reply for %s: %s", req_name[0].name, + rdns_strerror (reply->code)); if (session->state != SMTP_PROXY_STATE_REJECT) { @@ -436,13 +498,13 @@ smtp_dnsbl_cb (struct rdns_reply *reply, void *arg) p = req_name[0].name; while (*p) { if (*p == '.') { - dots ++; + dots++; } if (dots == 4) { session->dnsbl_applied = (gchar *)p + 1; break; } - p ++; + p++; } session->state = SMTP_PROXY_STATE_REJECT; } @@ -458,19 +520,22 @@ smtp_dnsbl_cb (struct rdns_reply *reply, void *arg) else { if (session->ctx->instant_reject) { msg_info ("reject %s is denied by dnsbl: %s", - inet_ntoa (session->client_addr), session->dnsbl_applied); + inet_ntoa (session->client_addr), session->dnsbl_applied); if (!rspamd_dispatcher_write (session->dispatcher, - make_smtp_error (session->pool, 521, "%s Client denied by %s", "5.2.1", session->dnsbl_applied), - 0, FALSE, TRUE)) { + make_smtp_error (session->pool, 521, + "%s Client denied by %s", "5.2.1", session->dnsbl_applied), + 0, FALSE, TRUE)) { msg_err ("cannot write smtp error"); } } else { /* Emulate fake smtp session */ - rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_LINE, 0); + rspamd_set_dispatcher_policy (session->dispatcher, + BUFFER_LINE, + 0); if (!rspamd_dispatcher_write (session->dispatcher, - make_smtp_error (session->pool, 220, "smtp ready"), - 0, FALSE, TRUE)) { + make_smtp_error (session->pool, 220, "smtp ready"), + 0, FALSE, TRUE)) { msg_err ("cannot write smtp reply"); } } @@ -485,9 +550,9 @@ smtp_dnsbl_cb (struct rdns_reply *reply, void *arg) static void make_rbl_requests (struct smtp_proxy_session *session) { - GList *cur; - gchar *p, *dst; - guint len; + GList *cur; + gchar *p, *dst; + guint len; cur = session->ctx->rbls; while (cur) { @@ -496,10 +561,10 @@ make_rbl_requests (struct smtp_proxy_session *session) /* Print ipv4 addr */ p = (gchar *)&session->client_addr.s_addr; rspamd_snprintf (dst, len, "%ud.%ud.%ud.%ud.%s", (guint)p[3], - (guint)p[2], (guint)p[1], (guint)p[0], cur->data); + (guint)p[2], (guint)p[1], (guint)p[0], cur->data); if (make_dns_request (session->resolver, session->s, session->pool, - smtp_dnsbl_cb, session, RDNS_REQUEST_A, dst)) { - session->rbl_requests ++; + smtp_dnsbl_cb, session, RDNS_REQUEST_A, dst)) { + session->rbl_requests++; msg_debug ("send request to %s", dst); } cur = g_list_next (cur); @@ -507,7 +572,7 @@ make_rbl_requests (struct smtp_proxy_session *session) if (session->rbl_requests == 0) { /* Create proxy */ - if (! create_smtp_proxy_upstream_connection (session)) { + if (!create_smtp_proxy_upstream_connection (session)) { rspamd_dispatcher_restore (session->dispatcher); } } @@ -520,10 +585,10 @@ make_rbl_requests (struct smtp_proxy_session *session) static void smtp_delay_handler (gint fd, short what, void *arg) { - struct smtp_proxy_session *session = arg; + struct smtp_proxy_session *session = arg; remove_normal_event (session->s, (event_finalizer_t) event_del, - session->delay_timer); + session->delay_timer); if (session->state == SMTP_PROXY_STATE_DELAY) { /* TODO: Create upstream connection here */ if (session->ctx->rbls) { @@ -539,8 +604,9 @@ smtp_delay_handler (gint fd, short what, void *arg) /* TODO: Write error here */ session->state = SMTP_PROXY_STATE_REJECT; if (!rspamd_dispatcher_write (session->dispatcher, - make_smtp_error (session->pool, 521, "%s Improper use of SMTP command pipelining", "5.2.1"), - 0, FALSE, TRUE)) { + make_smtp_error (session->pool, 521, + "%s Improper use of SMTP command pipelining", "5.2.1"), + 0, FALSE, TRUE)) { msg_err ("cannot write smtp error"); } rspamd_dispatcher_restore (session->dispatcher); @@ -553,11 +619,12 @@ smtp_delay_handler (gint fd, short what, void *arg) static void smtp_make_delay (struct smtp_proxy_session *session) { - struct event *tev; - struct timeval *tv; - gint32 jitter; + struct event *tev; + struct timeval *tv; + gint32 jitter; - if (session->ctx->smtp_delay != 0 && session->state == SMTP_PROXY_STATE_DELAY) { + if (session->ctx->smtp_delay != 0 && session->state == + SMTP_PROXY_STATE_DELAY) { tev = rspamd_mempool_alloc (session->pool, sizeof(struct event)); tv = rspamd_mempool_alloc (session->pool, sizeof(struct timeval)); if (session->ctx->delay_jitter != 0) { @@ -571,7 +638,7 @@ smtp_make_delay (struct smtp_proxy_session *session) evtimer_set (tev, smtp_delay_handler, session); evtimer_add (tev, tv); register_async_event (session->s, (event_finalizer_t) event_del, tev, - g_quark_from_static_string ("smtp proxy")); + g_quark_from_static_string ("smtp proxy")); session->delay_timer = tev; } else if (session->state == SMTP_PROXY_STATE_DELAY) { @@ -593,10 +660,10 @@ smtp_make_delay (struct smtp_proxy_session *session) static void smtp_dns_cb (struct rdns_reply *reply, void *arg) { - struct smtp_proxy_session *session = arg; - gint res = 0; - struct rdns_reply_entry *elt; - GList *cur; + struct smtp_proxy_session *session = arg; + gint res = 0; + struct rdns_reply_entry *elt; + GList *cur; switch (session->state) { @@ -604,8 +671,8 @@ smtp_dns_cb (struct rdns_reply *reply, void *arg) /* Parse reverse reply and start resolve of this ip */ if (reply->code != RDNS_RC_NOERROR) { rspamd_conditional_debug (rspamd_main->logger, - NULL, __FUNCTION__, "DNS error: %s", - rdns_strerror (reply->code)); + NULL, __FUNCTION__, "DNS error: %s", + rdns_strerror (reply->code)); if (reply->code == RDNS_RC_NXDOMAIN) { session->hostname = rspamd_mempool_strdup (session->pool, @@ -625,7 +692,7 @@ smtp_dns_cb (struct rdns_reply *reply, void *arg) elt->content.ptr.name); session->state = SMTP_PROXY_STATE_RESOLVE_NORMAL; make_dns_request (session->resolver, session->s, session->pool, - smtp_dns_cb, session, RDNS_REQUEST_A, session->hostname); + smtp_dns_cb, session, RDNS_REQUEST_A, session->hostname); } } @@ -633,8 +700,8 @@ smtp_dns_cb (struct rdns_reply *reply, void *arg) case SMTP_PROXY_STATE_RESOLVE_NORMAL: if (reply->code != RDNS_RC_NOERROR) { rspamd_conditional_debug (rspamd_main->logger, - NULL, __FUNCTION__, "DNS error: %s", - rdns_strerror (reply->code)); + NULL, __FUNCTION__, "DNS error: %s", + rdns_strerror (reply->code)); if (reply->code == RDNS_RC_NXDOMAIN) { session->hostname = rspamd_mempool_strdup (session->pool, @@ -649,9 +716,10 @@ smtp_dns_cb (struct rdns_reply *reply, void *arg) } else { res = 0; - LL_FOREACH (reply->entries, elt) { + LL_FOREACH (reply->entries, elt) + { if (memcmp (&session->client_addr, &elt->content.a.addr, - sizeof(struct in_addr)) == 0) { + sizeof(struct in_addr)) == 0) { res = 1; session->resolved = TRUE; break; @@ -660,9 +728,10 @@ smtp_dns_cb (struct rdns_reply *reply, void *arg) } if (res == 0) { - msg_info( - "cannot find address for hostname: %s, ip: %s", session->hostname, - inet_ntoa (session->client_addr)); + msg_info ( + "cannot find address for hostname: %s, ip: %s", + session->hostname, + inet_ntoa (session->client_addr)); session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_UNAVAILABLE); } @@ -679,37 +748,41 @@ smtp_dns_cb (struct rdns_reply *reply, void *arg) static void proxy_parse_smtp_input (f_str_t *line, struct smtp_proxy_session *session) { - gchar *p, *c, *end; - gsize len; + gchar *p, *c, *end; + gsize len; p = line->begin; end = line->begin + line->len; - if (line->len >= sizeof("rcpt to: ") - 1 && (*p == 'r' || *p == 'R') && session->rcpt == NULL) { - if (g_ascii_strncasecmp (p, "rcpt to: ", sizeof ("rcpt to: ") - 1) == 0) { + if (line->len >= sizeof("rcpt to: ") - 1 && + (*p == 'r' || *p == 'R') && session->rcpt == NULL) { + if (g_ascii_strncasecmp (p, "rcpt to: ", + sizeof ("rcpt to: ") - 1) == 0) { p += sizeof ("rcpt to: ") - 1; /* Skip spaces */ while ((g_ascii_isspace (*p) || *p == '<') && p < end) { - p ++; + p++; } c = p; while (!(g_ascii_isspace (*p) || *p == '>') && p < end) { - p ++; + p++; } len = p - c; session->rcpt = rspamd_mempool_alloc (session->pool, len + 1); rspamd_strlcpy (session->rcpt, c, len + 1); } } - else if (line->len >= sizeof("mail from: ") - 1 && (*p == 'm' || *p == 'M') && session->from == NULL) { - if (g_ascii_strncasecmp (p, "mail from: ", sizeof ("mail from: ") - 1) == 0) { + else if (line->len >= sizeof("mail from: ") - 1 && + (*p == 'm' || *p == 'M') && session->from == NULL) { + if (g_ascii_strncasecmp (p, "mail from: ", sizeof ("mail from: ") - + 1) == 0) { p += sizeof ("mail from: ") - 1; /* Skip spaces */ while ((g_ascii_isspace (*p) || *p == '<') && p < end) { - p ++; + p++; } c = p; while (!(g_ascii_isspace (*p) || *p == '>') && p < end) { - p ++; + p++; } len = p - c; session->from = rspamd_mempool_alloc (session->pool, len + 1); @@ -726,18 +799,19 @@ proxy_parse_smtp_input (f_str_t *line, struct smtp_proxy_session *session) /* * Callback that is called when there is data to read in buffer */ -static gboolean +static gboolean smtp_proxy_read_socket (f_str_t * in, void *arg) { - struct smtp_proxy_session *session = arg; - gchar *p; + struct smtp_proxy_session *session = arg; + gchar *p; if (session->state != SMTP_PROXY_STATE_REJECT_EMULATE) { /* This can be called only if client is using invalid pipelining */ session->state = SMTP_PROXY_STATE_REJECT; if (!rspamd_dispatcher_write (session->dispatcher, - make_smtp_error (session->pool, 521, "%s Improper use of SMTP command pipelining", "5.2.1"), - 0, FALSE, TRUE)) { + make_smtp_error (session->pool, 521, + "%s Improper use of SMTP command pipelining", "5.2.1"), + 0, FALSE, TRUE)) { msg_err ("cannot write smtp error"); } destroy_session (session->s); @@ -745,10 +819,11 @@ smtp_proxy_read_socket (f_str_t * in, void *arg) else { /* Try to extract data */ p = in->begin; - if (in->len >= sizeof ("helo") - 1 && (*p == 'h' || *p == 'H' || *p == 'e' || *p == 'E')) { + if (in->len >= sizeof ("helo") - 1 && + (*p == 'h' || *p == 'H' || *p == 'e' || *p == 'E')) { return rspamd_dispatcher_write (session->dispatcher, - "220 smtp ready" CRLF, - 0, FALSE, TRUE); + "220 smtp ready" CRLF, + 0, FALSE, TRUE); } else if (in->len > 0) { proxy_parse_smtp_input (in, session); @@ -756,32 +831,36 @@ smtp_proxy_read_socket (f_str_t * in, void *arg) if (session->state == SMTP_PROXY_STATE_REJECT) { /* Received QUIT command */ if (!rspamd_dispatcher_write (session->dispatcher, - "221 2.0.0 Bye" CRLF, - 0, FALSE, TRUE)) { + "221 2.0.0 Bye" CRLF, + 0, FALSE, TRUE)) { msg_err ("cannot write smtp error"); } destroy_session (session->s); return FALSE; } if (session->rcpt != NULL) { - session->errors ++; + session->errors++; if (session->errors > SMTP_MAXERRORS) { if (!rspamd_dispatcher_write (session->dispatcher, - "521 5.2.1 Maximum errors reached" CRLF, - 0, FALSE, TRUE)) { + "521 5.2.1 Maximum errors reached" CRLF, + 0, FALSE, TRUE)) { msg_err ("cannot write smtp error"); } destroy_session (session->s); return FALSE; } return rspamd_dispatcher_write (session->dispatcher, - make_smtp_error (session->pool, 521, "%s Client denied by %s", "5.2.1", session->dnsbl_applied), - 0, FALSE, TRUE); + make_smtp_error (session->pool, + 521, + "%s Client denied by %s", + "5.2.1", + session->dnsbl_applied), + 0, FALSE, TRUE); } else { return rspamd_dispatcher_write (session->dispatcher, - "250 smtp ready" CRLF, - 0, FALSE, TRUE); + "250 smtp ready" CRLF, + 0, FALSE, TRUE); } } @@ -791,10 +870,10 @@ smtp_proxy_read_socket (f_str_t * in, void *arg) /* * Actually called only if something goes wrong */ -static gboolean +static gboolean smtp_proxy_write_socket (void *arg) { - struct smtp_proxy_session *session = arg; + struct smtp_proxy_session *session = arg; if (session->ctx->instant_reject) { destroy_session (session->s); @@ -813,14 +892,14 @@ smtp_proxy_write_socket (void *arg) static void smtp_proxy_err_socket (GError * err, void *arg) { - struct smtp_proxy_session *session = arg; + struct smtp_proxy_session *session = arg; if (err) { if (err->code == ETIMEDOUT) { /* Write smtp error */ if (!rspamd_dispatcher_write (session->dispatcher, - "421 4.4.2 Error: timeout exceeded" CRLF, - 0, FALSE, TRUE)) { + "421 4.4.2 Error: timeout exceeded" CRLF, + 0, FALSE, TRUE)) { msg_err ("cannot write smtp error"); } } @@ -837,16 +916,16 @@ smtp_proxy_err_socket (GError * err, void *arg) static void accept_socket (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *)arg; - struct smtp_proxy_session *session; - struct smtp_proxy_ctx *ctx; - rspamd_inet_addr_t addr; - gint nfd; + struct rspamd_worker *worker = (struct rspamd_worker *)arg; + struct smtp_proxy_session *session; + struct smtp_proxy_ctx *ctx; + rspamd_inet_addr_t addr; + gint nfd; ctx = worker->ctx; if ((nfd = - rspamd_accept_from_socket (fd, &addr)) == -1) { + rspamd_accept_from_socket (fd, &addr)) == -1) { msg_warn ("accept failed: %s", strerror (errno)); return; } @@ -856,8 +935,8 @@ accept_socket (gint fd, short what, void *arg) } msg_info ("accepted connection from %s port %d", - rspamd_inet_address_to_string (&addr), - rspamd_inet_address_get_port (&addr)); + rspamd_inet_address_to_string (&addr), + rspamd_inet_address_get_port (&addr)); ctx = worker->ctx; session = g_slice_alloc0 (sizeof (struct smtp_proxy_session)); @@ -870,24 +949,34 @@ accept_socket (gint fd, short what, void *arg) session->resolver = ctx->resolver; session->ev_base = ctx->ev_base; session->upstream_sock = -1; - session->ptr_str = rdns_generate_ptr_from_str (rspamd_inet_address_to_string (&addr)); + session->ptr_str = rdns_generate_ptr_from_str (rspamd_inet_address_to_string ( + &addr)); worker->srv->stat->connections_count++; /* Resolve client's addr */ /* Set up async session */ - session->s = new_async_session (session->pool, NULL, NULL, free_smtp_proxy_session, session); + session->s = new_async_session (session->pool, + NULL, + NULL, + free_smtp_proxy_session, + session); session->state = SMTP_PROXY_STATE_RESOLVE_REVERSE; - if (! make_dns_request (session->resolver, session->s, session->pool, - smtp_dns_cb, session, RDNS_REQUEST_PTR, session->ptr_str)) { + if (!make_dns_request (session->resolver, session->s, session->pool, + smtp_dns_cb, session, RDNS_REQUEST_PTR, session->ptr_str)) { msg_err ("cannot resolve %s", inet_ntoa (session->client_addr)); g_slice_free1 (sizeof (struct smtp_proxy_session), session); close (nfd); return; } else { - session->dispatcher = rspamd_create_dispatcher (session->ev_base, nfd, BUFFER_ANY, - smtp_proxy_read_socket, smtp_proxy_write_socket, smtp_proxy_err_socket, - &session->ctx->smtp_timeout, session); + session->dispatcher = rspamd_create_dispatcher (session->ev_base, + nfd, + BUFFER_ANY, + smtp_proxy_read_socket, + smtp_proxy_write_socket, + smtp_proxy_err_socket, + &session->ctx->smtp_timeout, + session); session->dispatcher->peer_addr = session->client_addr.s_addr; } } @@ -895,8 +984,8 @@ accept_socket (gint fd, short what, void *arg) gpointer init_smtp_proxy (struct rspamd_config *cfg) { - struct smtp_proxy_ctx *ctx; - GQuark type; + struct smtp_proxy_ctx *ctx; + GQuark type; type = g_quark_try_string ("smtp_proxy"); @@ -909,36 +998,40 @@ init_smtp_proxy (struct rspamd_config *cfg) ctx->instant_reject = TRUE; rspamd_rcl_register_worker_option (cfg, type, "upstreams", - rspamd_rcl_parse_struct_string, ctx, - G_STRUCT_OFFSET (struct smtp_proxy_ctx, upstreams_str), 0); + rspamd_rcl_parse_struct_string, ctx, + G_STRUCT_OFFSET (struct smtp_proxy_ctx, upstreams_str), 0); rspamd_rcl_register_worker_option (cfg, type, "timeout", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct smtp_proxy_ctx, smtp_timeout_raw), RSPAMD_CL_FLAG_TIME_UINT_32); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct smtp_proxy_ctx, + smtp_timeout_raw), RSPAMD_CL_FLAG_TIME_UINT_32); rspamd_rcl_register_worker_option (cfg, type, "delay", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct smtp_proxy_ctx, smtp_delay), RSPAMD_CL_FLAG_TIME_UINT_32); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct smtp_proxy_ctx, + smtp_delay), RSPAMD_CL_FLAG_TIME_UINT_32); rspamd_rcl_register_worker_option (cfg, type, "jitter", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct smtp_proxy_ctx, delay_jitter), RSPAMD_CL_FLAG_TIME_UINT_32); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct smtp_proxy_ctx, + delay_jitter), RSPAMD_CL_FLAG_TIME_UINT_32); rspamd_rcl_register_worker_option (cfg, type, "xclient", - rspamd_rcl_parse_struct_boolean, ctx, - G_STRUCT_OFFSET (struct smtp_proxy_ctx, use_xclient), 0); + rspamd_rcl_parse_struct_boolean, ctx, + G_STRUCT_OFFSET (struct smtp_proxy_ctx, use_xclient), 0); rspamd_rcl_register_worker_option (cfg, type, "instant_reject", - rspamd_rcl_parse_struct_boolean, ctx, - G_STRUCT_OFFSET (struct smtp_proxy_ctx, instant_reject), 0); + rspamd_rcl_parse_struct_boolean, ctx, + G_STRUCT_OFFSET (struct smtp_proxy_ctx, instant_reject), 0); rspamd_rcl_register_worker_option (cfg, type, "proxy_buffer", - rspamd_rcl_parse_struct_integer, ctx, - G_STRUCT_OFFSET (struct smtp_proxy_ctx, proxy_buf_len), RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_parse_struct_integer, ctx, + G_STRUCT_OFFSET (struct smtp_proxy_ctx, + proxy_buf_len), RSPAMD_CL_FLAG_INT_32); rspamd_rcl_register_worker_option (cfg, type, "dnsbl", - rspamd_rcl_parse_struct_string_list, ctx, - G_STRUCT_OFFSET (struct smtp_proxy_ctx, rbls), 0); + rspamd_rcl_parse_struct_string_list, ctx, + G_STRUCT_OFFSET (struct smtp_proxy_ctx, rbls), 0); return ctx; } @@ -947,15 +1040,16 @@ init_smtp_proxy (struct rspamd_config *cfg) static gboolean config_smtp_proxy_worker (struct rspamd_worker *worker) { - struct smtp_proxy_ctx *ctx = worker->ctx; - gchar *value; + struct smtp_proxy_ctx *ctx = worker->ctx; + gchar *value; /* Init timeval */ msec_to_tv (ctx->smtp_timeout_raw, &ctx->smtp_timeout); /* Init upstreams */ if ((value = ctx->upstreams_str) != NULL) { - if (!parse_upstreams_line (ctx->pool, ctx->upstreams, value, &ctx->upstream_num)) { + if (!parse_upstreams_line (ctx->pool, ctx->upstreams, value, + &ctx->upstream_num)) { return FALSE; } } @@ -977,7 +1071,7 @@ config_smtp_proxy_worker (struct rspamd_worker *worker) void start_smtp_proxy (struct rspamd_worker *worker) { - struct smtp_proxy_ctx *ctx = worker->ctx; + struct smtp_proxy_ctx *ctx = worker->ctx; ctx->ev_base = rspamd_prepare_worker (worker, "smtp_proxy", accept_socket); @@ -988,7 +1082,9 @@ start_smtp_proxy (struct rspamd_worker *worker) } /* DNS resolver */ - ctx->resolver = dns_resolver_init (worker->srv->logger, ctx->ev_base, worker->srv->cfg); + ctx->resolver = dns_resolver_init (worker->srv->logger, + ctx->ev_base, + worker->srv->cfg); /* Set umask */ umask (S_IWGRP | S_IWOTH | S_IROTH | S_IRGRP); diff --git a/src/tokenizers/osb.c b/src/tokenizers/osb.c index 823e1e5b5..b74441eca 100644 --- a/src/tokenizers/osb.c +++ b/src/tokenizers/osb.c @@ -32,26 +32,34 @@ /* Minimum length of token */ #define MIN_LEN 4 -extern const int primes[]; +extern const int primes[]; int -osb_tokenize_text (struct tokenizer *tokenizer, rspamd_mempool_t * pool, f_str_t * input, GTree ** tree, - gboolean save_token, gboolean is_utf, GList *exceptions) +osb_tokenize_text (struct tokenizer *tokenizer, + rspamd_mempool_t * pool, + f_str_t * input, + GTree ** tree, + gboolean save_token, + gboolean is_utf, + GList *exceptions) { - token_node_t *new = NULL; - f_str_t token = { NULL, 0, 0 }; - guint32 hashpipe[FEATURE_WINDOW_SIZE], h1, h2; - gint i, l, processed = 0; - gchar *res; + token_node_t *new = NULL; + f_str_t token = { NULL, 0, 0 }; + guint32 hashpipe[FEATURE_WINDOW_SIZE], h1, h2; + gint i, l, processed = 0; + gchar *res; if (*tree == NULL) { *tree = g_tree_new (token_node_compare_func); - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_tree_destroy, *tree); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_tree_destroy, + *tree); } memset (hashpipe, 0xfe, FEATURE_WINDOW_SIZE * sizeof (hashpipe[0])); - while ((res = tokenizer->get_next_word (input, &token, &exceptions)) != NULL) { + while ((res = + tokenizer->get_next_word (input, &token, &exceptions)) != NULL) { /* Skip small words */ if (is_utf) { l = g_utf8_strlen (token.begin, token.len); @@ -67,7 +75,7 @@ osb_tokenize_text (struct tokenizer *tokenizer, rspamd_mempool_t * pool, f_str_t if (processed < FEATURE_WINDOW_SIZE) { /* Just fill a hashpipe */ hashpipe[FEATURE_WINDOW_SIZE - ++processed] = - fstrhash_lowercase (&token, is_utf); + fstrhash_lowercase (&token, is_utf); } else { /* Shift hashpipe */ @@ -75,16 +83,18 @@ osb_tokenize_text (struct tokenizer *tokenizer, rspamd_mempool_t * pool, f_str_t hashpipe[i] = hashpipe[i - 1]; } hashpipe[0] = fstrhash_lowercase (&token, is_utf); - processed ++; + processed++; for (i = 1; i < FEATURE_WINDOW_SIZE; i++) { h1 = hashpipe[0] * primes[0] + hashpipe[i] * primes[i << 1]; - h2 = hashpipe[0] * primes[1] + hashpipe[i] * primes[(i << 1) - 1]; + h2 = hashpipe[0] * primes[1] + hashpipe[i] * + primes[(i << 1) - 1]; new = rspamd_mempool_alloc0 (pool, sizeof (token_node_t)); new->h1 = h1; new->h2 = h2; if (save_token) { - new->extra = (uintptr_t)rspamd_mempool_fstrdup (pool, &token); + new->extra = + (uintptr_t)rspamd_mempool_fstrdup (pool, &token); } if (g_tree_lookup (*tree, new) == NULL) { diff --git a/src/tokenizers/tokenizers.c b/src/tokenizers/tokenizers.c index 448dcd53e..eb7a489e5 100644 --- a/src/tokenizers/tokenizers.c +++ b/src/tokenizers/tokenizers.c @@ -30,11 +30,11 @@ #include "main.h" #include "tokenizers.h" -struct tokenizer tokenizers[] = { +struct tokenizer tokenizers[] = { {"osb-text", osb_tokenize_text, get_next_word}, }; -const int primes[] = { +const int primes[] = { 1, 7, 3, 13, 5, 29, @@ -48,38 +48,38 @@ const int primes[] = { }; const gchar t_delimiters[255] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 }; -struct tokenizer * +struct tokenizer * get_tokenizer (const char *name) { - guint i; + guint i; for (i = 0; i < sizeof (tokenizers) / sizeof (tokenizers[0]); i++) { if (strcmp (tokenizers[i].name, name) == 0) { @@ -93,7 +93,7 @@ get_tokenizer (const char *name) int token_node_compare_func (gconstpointer a, gconstpointer b) { - const token_node_t *aa = a, *bb = b; + const token_node_t *aa = a, *bb = b; if (aa->h1 == bb->h1) { return aa->h2 - bb->h2; @@ -106,9 +106,9 @@ token_node_compare_func (gconstpointer a, gconstpointer b) gchar * get_next_word (f_str_t * buf, f_str_t * token, GList **exceptions) { - gsize remain, pos; - guchar *p; - struct process_exception *ex = NULL; + gsize remain, pos; + guchar *p; + struct process_exception *ex = NULL; if (buf == NULL) { return NULL; @@ -165,7 +165,7 @@ get_next_word (f_str_t * buf, f_str_t * token, GList **exceptions) token->len++; pos++; remain--; - p ++; + p++; } if (remain == 0) { @@ -177,30 +177,34 @@ get_next_word (f_str_t * buf, f_str_t * token, GList **exceptions) /* Struct to access gmime headers */ struct raw_header { - struct raw_header *next; - char *name; - char *value; + struct raw_header *next; + char *name; + char *value; }; typedef struct _GMimeHeader { - GHashTable *hash; - GHashTable *writers; - struct raw_header *headers; + GHashTable *hash; + GHashTable *writers; + struct raw_header *headers; } local_GMimeHeader; int -tokenize_headers (rspamd_mempool_t * pool, struct rspamd_task *task, GTree ** tree) +tokenize_headers (rspamd_mempool_t * pool, + struct rspamd_task *task, + GTree ** tree) { - token_node_t *new = NULL; - f_str_t headername; - f_str_t headervalue; + token_node_t *new = NULL; + f_str_t headername; + f_str_t headervalue; if (*tree == NULL) { *tree = g_tree_new (token_node_compare_func); - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t) g_tree_destroy, *tree); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t) g_tree_destroy, + *tree); } #ifndef GMIME24 - struct raw_header *h; + struct raw_header *h; h = GMIME_OBJECT (task->message)->headers->headers; while (h) { @@ -219,10 +223,10 @@ tokenize_headers (rspamd_mempool_t * pool, struct rspamd_task *task, GTree ** tr h = h->next; } #else - GMimeHeaderList *ls; - GMimeHeaderIter *iter; - const char *name; - const char *value; + GMimeHeaderList *ls; + GMimeHeaderIter *iter; + const char *name; + const char *value; ls = GMIME_OBJECT (task->message)->headers; iter = g_mime_header_iter_new (); @@ -254,13 +258,14 @@ tokenize_headers (rspamd_mempool_t * pool, struct rspamd_task *task, GTree ** tr void tokenize_subject (struct rspamd_task *task, GTree ** tree) { - f_str_t subject; - const gchar *sub; - struct tokenizer *osb_tokenizer; + f_str_t subject; + const gchar *sub; + struct tokenizer *osb_tokenizer; if (*tree == NULL) { *tree = g_tree_new (token_node_compare_func); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t) g_tree_destroy, *tree); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t) g_tree_destroy, *tree); } osb_tokenizer = get_tokenizer ("osb-text"); @@ -269,12 +274,24 @@ tokenize_subject (struct rspamd_task *task, GTree ** tree) if (task->subject != NULL) { subject.begin = task->subject; subject.len = strlen (task->subject); - osb_tokenizer->tokenize_func (osb_tokenizer, task->task_pool, &subject, tree, FALSE, TRUE, NULL); + osb_tokenizer->tokenize_func (osb_tokenizer, + task->task_pool, + &subject, + tree, + FALSE, + TRUE, + NULL); } if ((sub = g_mime_message_get_subject (task->message)) != NULL) { subject.begin = (gchar *)sub; subject.len = strlen (sub); - osb_tokenizer->tokenize_func (osb_tokenizer, task->task_pool, &subject, tree, FALSE, TRUE, NULL); + osb_tokenizer->tokenize_func (osb_tokenizer, + task->task_pool, + &subject, + tree, + FALSE, + TRUE, + NULL); } } diff --git a/src/tokenizers/tokenizers.h b/src/tokenizers/tokenizers.h index 207602dc8..883f38058 100644 --- a/src/tokenizers/tokenizers.h +++ b/src/tokenizers/tokenizers.h @@ -19,22 +19,30 @@ typedef struct token_node_s { /* Common tokenizer structure */ struct tokenizer { gchar *name; - gint (*tokenize_func)(struct tokenizer *tokenizer, rspamd_mempool_t *pool, f_str_t *input, - GTree **cur, gboolean save_token, gboolean is_utf, GList *exceptions); - gchar* (*get_next_word)(f_str_t *buf, f_str_t *token, GList **exceptions); + gint (*tokenize_func)(struct tokenizer *tokenizer, rspamd_mempool_t *pool, + f_str_t *input, + GTree **cur, gboolean save_token, gboolean is_utf, GList *exceptions); + gchar * (*get_next_word)(f_str_t *buf, f_str_t *token, GList **exceptions); }; /* Compare two token nodes */ int token_node_compare_func (gconstpointer a, gconstpointer b); /* Get tokenizer structure by name or return NULL if this name is not found */ -struct tokenizer* get_tokenizer (const char *name); +struct tokenizer * get_tokenizer (const char *name); /* Get next word from specified f_str_t buf */ -gchar* get_next_word (f_str_t *buf, f_str_t *token, GList **exceptions); +gchar * get_next_word (f_str_t *buf, f_str_t *token, GList **exceptions); /* OSB tokenize function */ -int osb_tokenize_text (struct tokenizer *tokenizer, rspamd_mempool_t *pool, f_str_t *input, - GTree **cur, gboolean save_token, gboolean is_utf, GList *exceptions); +int osb_tokenize_text (struct tokenizer *tokenizer, + rspamd_mempool_t *pool, + f_str_t *input, + GTree **cur, + gboolean save_token, + gboolean is_utf, + GList *exceptions); /* Common tokenizer for headers */ -int tokenize_headers (rspamd_mempool_t *pool, struct rspamd_task *task, GTree **cur); +int tokenize_headers (rspamd_mempool_t *pool, + struct rspamd_task *task, + GTree **cur); /* Make tokens for a subject */ void tokenize_subject (struct rspamd_task *task, GTree ** tree); diff --git a/src/worker.c b/src/worker.c index 229ee1a4e..77cb9fcd1 100644 --- a/src/worker.c +++ b/src/worker.c @@ -50,42 +50,42 @@ gpointer init_worker (struct rspamd_config *cfg); void start_worker (struct rspamd_worker *worker); worker_t normal_worker = { - "normal", /* Name */ - init_worker, /* Init function */ - start_worker, /* Start function */ - TRUE, /* Has socket */ - FALSE, /* Non unique */ - FALSE, /* Non threaded */ - TRUE, /* Killable */ - SOCK_STREAM /* TCP socket */ + "normal", /* Name */ + init_worker, /* Init function */ + start_worker, /* Start function */ + TRUE, /* Has socket */ + FALSE, /* Non unique */ + FALSE, /* Non threaded */ + TRUE, /* Killable */ + SOCK_STREAM /* TCP socket */ }; /* * Worker's context */ struct rspamd_worker_ctx { - guint32 timeout; - struct timeval io_tv; - /* Detect whether this worker is mime worker */ - gboolean is_mime; + guint32 timeout; + struct timeval io_tv; + /* Detect whether this worker is mime worker */ + gboolean is_mime; /* HTTP worker */ - gboolean is_http; - /* JSON output */ - gboolean is_json; + gboolean is_http; + /* JSON output */ + gboolean is_json; /* Allow learning throught worker */ - gboolean allow_learn; + gboolean allow_learn; /* DNS resolver */ - struct rspamd_dns_resolver *resolver; + struct rspamd_dns_resolver *resolver; /* Current tasks */ - guint32 tasks; + guint32 tasks; /* Limit of tasks */ - guint32 max_tasks; + guint32 max_tasks; /* Classify threads */ - guint32 classify_threads; + guint32 classify_threads; /* Classify threads */ - GThreadPool *classify_pool; + GThreadPool *classify_pool; /* Events base */ - struct event_base *ev_base; + struct event_base *ev_base; }; /* @@ -94,18 +94,18 @@ struct rspamd_worker_ctx { static void reduce_tasks_count (gpointer arg) { - guint32 *tasks = arg; + guint32 *tasks = arg; - (*tasks) --; + (*tasks)--; } static gint rspamd_worker_body_handler (struct rspamd_http_connection *conn, - struct rspamd_http_message *msg, - const gchar *chunk, gsize len) + struct rspamd_http_message *msg, + const gchar *chunk, gsize len) { - struct rspamd_task *task = (struct rspamd_task *) conn->ud; - struct rspamd_worker_ctx *ctx; + struct rspamd_task *task = (struct rspamd_task *) conn->ud; + struct rspamd_worker_ctx *ctx; ctx = task->worker->ctx; @@ -137,14 +137,15 @@ rspamd_worker_body_handler (struct rspamd_http_connection *conn, static void rspamd_worker_error_handler (struct rspamd_http_connection *conn, GError *err) { - struct rspamd_task *task = (struct rspamd_task *) conn->ud; + struct rspamd_task *task = (struct rspamd_task *) conn->ud; msg_info ("abnormally closing connection from: %s, error: %s", - rspamd_inet_address_to_string (&task->client_addr), err->message); + rspamd_inet_address_to_string (&task->client_addr), err->message); if (task->state != CLOSING_CONNECTION) { /* We still need to write a reply */ task->error_code = err->code; - task->last_error = rspamd_mempool_strdup (task->task_pool, err->message); + task->last_error = + rspamd_mempool_strdup (task->task_pool, err->message); task->state = WRITE_REPLY; rspamd_protocol_write_reply (task); } @@ -156,13 +157,13 @@ rspamd_worker_error_handler (struct rspamd_http_connection *conn, GError *err) static gint rspamd_worker_finish_handler (struct rspamd_http_connection *conn, - struct rspamd_http_message *msg) + struct rspamd_http_message *msg) { - struct rspamd_task *task = (struct rspamd_task *) conn->ud; + struct rspamd_task *task = (struct rspamd_task *) conn->ud; if (task->state == CLOSING_CONNECTION) { msg_debug ("normally closing connection from: %s", - rspamd_inet_address_to_string (&task->client_addr)); + rspamd_inet_address_to_string (&task->client_addr)); destroy_session (task->s); } else { @@ -183,21 +184,23 @@ rspamd_worker_finish_handler (struct rspamd_http_connection *conn, static void accept_socket (gint fd, short what, void *arg) { - struct rspamd_worker *worker = (struct rspamd_worker *) arg; - struct rspamd_worker_ctx *ctx; - struct rspamd_task *new_task; - rspamd_inet_addr_t addr; - gint nfd; + struct rspamd_worker *worker = (struct rspamd_worker *) arg; + struct rspamd_worker_ctx *ctx; + struct rspamd_task *new_task; + rspamd_inet_addr_t addr; + gint nfd; ctx = worker->ctx; if (ctx->max_tasks != 0 && ctx->tasks > ctx->max_tasks) { - msg_info ("current tasks is now: %uD while maximum is: %uD", ctx->tasks, ctx->max_tasks); + msg_info ("current tasks is now: %uD while maximum is: %uD", + ctx->tasks, + ctx->max_tasks); return; } if ((nfd = - rspamd_accept_from_socket (fd, &addr)) == -1) { + rspamd_accept_from_socket (fd, &addr)) == -1) { msg_warn ("accept failed: %s", strerror (errno)); return; } @@ -209,8 +212,8 @@ accept_socket (gint fd, short what, void *arg) new_task = rspamd_task_new (worker); msg_info ("accepted connection from %s port %d", - rspamd_inet_address_to_string (&addr), - rspamd_inet_address_get_port (&addr)); + rspamd_inet_address_to_string (&addr), + rspamd_inet_address_get_port (&addr)); /* Copy some variables */ new_task->sock = nfd; @@ -220,26 +223,35 @@ accept_socket (gint fd, short what, void *arg) worker->srv->stat->connections_count++; new_task->resolver = ctx->resolver; - new_task->http_conn = rspamd_http_connection_new (rspamd_worker_body_handler, - rspamd_worker_error_handler, rspamd_worker_finish_handler, 0, RSPAMD_HTTP_SERVER); + new_task->http_conn = rspamd_http_connection_new ( + rspamd_worker_body_handler, + rspamd_worker_error_handler, + rspamd_worker_finish_handler, + 0, + RSPAMD_HTTP_SERVER); new_task->ev_base = ctx->ev_base; - ctx->tasks ++; - rspamd_mempool_add_destructor (new_task->task_pool, (rspamd_mempool_destruct_t)reduce_tasks_count, &ctx->tasks); + ctx->tasks++; + rspamd_mempool_add_destructor (new_task->task_pool, + (rspamd_mempool_destruct_t)reduce_tasks_count, &ctx->tasks); /* Set up async session */ new_task->s = new_async_session (new_task->task_pool, rspamd_task_fin, - rspamd_task_restore, rspamd_task_free_hard, new_task); + rspamd_task_restore, rspamd_task_free_hard, new_task); new_task->classify_pool = ctx->classify_pool; - rspamd_http_connection_read_message (new_task->http_conn, new_task, nfd, &ctx->io_tv, ctx->ev_base); + rspamd_http_connection_read_message (new_task->http_conn, + new_task, + nfd, + &ctx->io_tv, + ctx->ev_base); } gpointer init_worker (struct rspamd_config *cfg) { - struct rspamd_worker_ctx *ctx; - GQuark type; + struct rspamd_worker_ctx *ctx; + GQuark type; type = g_quark_try_string ("normal"); @@ -250,32 +262,35 @@ init_worker (struct rspamd_config *cfg) ctx->classify_threads = 1; rspamd_rcl_register_worker_option (cfg, type, "mime", - rspamd_rcl_parse_struct_boolean, ctx, - G_STRUCT_OFFSET (struct rspamd_worker_ctx, is_mime), 0); + rspamd_rcl_parse_struct_boolean, ctx, + G_STRUCT_OFFSET (struct rspamd_worker_ctx, is_mime), 0); rspamd_rcl_register_worker_option (cfg, type, "http", - rspamd_rcl_parse_struct_boolean, ctx, - G_STRUCT_OFFSET (struct rspamd_worker_ctx, is_http), 0); + rspamd_rcl_parse_struct_boolean, ctx, + G_STRUCT_OFFSET (struct rspamd_worker_ctx, is_http), 0); rspamd_rcl_register_worker_option (cfg, type, "json", - rspamd_rcl_parse_struct_boolean, ctx, - G_STRUCT_OFFSET (struct rspamd_worker_ctx, is_json), 0); + rspamd_rcl_parse_struct_boolean, ctx, + G_STRUCT_OFFSET (struct rspamd_worker_ctx, is_json), 0); rspamd_rcl_register_worker_option (cfg, type, "allow_learn", - rspamd_rcl_parse_struct_boolean, ctx, - G_STRUCT_OFFSET (struct rspamd_worker_ctx, allow_learn), 0); + rspamd_rcl_parse_struct_boolean, ctx, + G_STRUCT_OFFSET (struct rspamd_worker_ctx, allow_learn), 0); rspamd_rcl_register_worker_option (cfg, type, "timeout", - rspamd_rcl_parse_struct_time, ctx, - G_STRUCT_OFFSET (struct rspamd_worker_ctx, timeout), RSPAMD_CL_FLAG_TIME_INTEGER); + rspamd_rcl_parse_struct_time, ctx, + G_STRUCT_OFFSET (struct rspamd_worker_ctx, + timeout), RSPAMD_CL_FLAG_TIME_INTEGER); rspamd_rcl_register_worker_option (cfg, type, "max_tasks", - rspamd_rcl_parse_struct_integer, ctx, - G_STRUCT_OFFSET (struct rspamd_worker_ctx, max_tasks), RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_parse_struct_integer, ctx, + G_STRUCT_OFFSET (struct rspamd_worker_ctx, + max_tasks), RSPAMD_CL_FLAG_INT_32); rspamd_rcl_register_worker_option (cfg, type, "classify_threads", - rspamd_rcl_parse_struct_integer, ctx, - G_STRUCT_OFFSET (struct rspamd_worker_ctx, classify_threads), RSPAMD_CL_FLAG_INT_32); + rspamd_rcl_parse_struct_integer, ctx, + G_STRUCT_OFFSET (struct rspamd_worker_ctx, + classify_threads), RSPAMD_CL_FLAG_INT_32); return ctx; } @@ -286,9 +301,9 @@ init_worker (struct rspamd_config *cfg) void start_worker (struct rspamd_worker *worker) { - struct rspamd_worker_ctx *ctx = worker->ctx; - GError *err = NULL; - struct lua_locked_state *nL; + struct rspamd_worker_ctx *ctx = worker->ctx; + GError *err = NULL; + struct lua_locked_state *nL; ctx->ev_base = rspamd_prepare_worker (worker, "normal", accept_socket); msec_to_tv (ctx->timeout, &ctx->io_tv); @@ -296,13 +311,19 @@ start_worker (struct rspamd_worker *worker) start_map_watch (worker->srv->cfg, ctx->ev_base); - ctx->resolver = dns_resolver_init (worker->srv->logger, ctx->ev_base, worker->srv->cfg); + ctx->resolver = dns_resolver_init (worker->srv->logger, + ctx->ev_base, + worker->srv->cfg); /* Create classify pool */ ctx->classify_pool = NULL; if (ctx->classify_threads > 1) { nL = init_lua_locked (worker->srv->cfg); - ctx->classify_pool = g_thread_pool_new (process_statfiles_threaded, nL, ctx->classify_threads, TRUE, &err); + ctx->classify_pool = g_thread_pool_new (process_statfiles_threaded, + nL, + ctx->classify_threads, + TRUE, + &err); if (err != NULL) { msg_err ("pool create failed: %s", err->message); ctx->classify_pool = NULL; @@ -316,6 +337,6 @@ start_worker (struct rspamd_worker *worker) exit (EXIT_SUCCESS); } -/* - * vi:ts=4 +/* + * vi:ts=4 */ |