struct rspamd_rcl_section {
struct rspamd_rcl_sections_map *top;
- const gchar *name; /**< name of section */
- const gchar *key_attr;
- const gchar *default_key;
+ std::string name; /**< name of section */
+ std::optional<std::string> key_attr;
+ std::optional<std::string> default_key;
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 */
- ankerl::unordered_dense::map<std::string, struct rspamd_rcl_section> subsections;
+ bool required; /**< whether this param is required */
+ bool strict_type; /**< whether we need strict type */
+ ankerl::unordered_dense::map<std::string, std::shared_ptr<struct rspamd_rcl_section>> subsections;
ankerl::unordered_dense::map<std::string, struct rspamd_rcl_default_handler_data> default_parser; /**< generic parsing fields */
rspamd_rcl_section_fin_t fin; /** called at the end of section parsing */
gpointer fin_ud;
};
struct rspamd_rcl_sections_map {
- ankerl::unordered_dense::map<std::string, struct rspamd_rcl_section> sections;
+ ankerl::unordered_dense::map<std::string, std::shared_ptr<struct rspamd_rcl_section>> sections;
+ std::vector<std::shared_ptr<struct rspamd_rcl_section>> sections_order;
ankerl::unordered_dense::map<int, struct rspamd_worker_cfg_parser> workers_parser;
ankerl::unordered_dense::set<std::string> lua_modules_seen;
};
dns = ucl_object_lookup(obj, "dns");
if (maybe_subsection && dns != nullptr) {
if (!rspamd_rcl_section_parse_defaults(cfg,
- maybe_subsection.value().get(), cfg->cfg_pool, dns,
+ *maybe_subsection.value().get(), cfg->cfg_pool, dns,
cfg, err)) {
return FALSE;
}
upstream = ucl_object_lookup_any(obj, "upstream", "upstreams", nullptr);
if (maybe_subsection && upstream != nullptr) {
if (!rspamd_rcl_section_parse_defaults(cfg,
- maybe_subsection.value().get(), cfg->cfg_pool,
+ *maybe_subsection.value().get(), cfg->cfg_pool,
upstream, cfg, err)) {
return FALSE;
}
LL_FOREACH(neighbours, cur)
{
- if (!rspamd_rcl_process_section(cfg, maybe_subsection.value().get(), cfg, cur,
+ if (!rspamd_rcl_process_section(cfg, *maybe_subsection.value().get(), cfg, cur,
pool, err)) {
return FALSE;
}
description);
}
- struct rspamd_rcl_symbol_data sd;
- sd.gr = gr;
- sd.cfg = cfg;
+ struct rspamd_rcl_symbol_data sd = {
+ .gr = gr,
+ .cfg = cfg,
+ };
/* Handle symbols */
if (const auto *val = ucl_object_lookup(obj, "symbols"); val != nullptr && ucl_object_type(val) == UCL_OBJECT) {
auto subsection = rspamd::find_map(section->subsections, "symbols");
g_assert(subsection.has_value());
- if (!rspamd_rcl_process_section(cfg, subsection.value().get(), &sd, val,
+ if (!rspamd_rcl_process_section(cfg, *subsection.value().get(), &sd, val,
pool, err)) {
return FALSE;
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
- const ucl_object_t *val, *cur;
- struct rspamd_config *cfg = ud;
- const gchar *data;
+ auto *cfg = static_cast<rspamd_config *>(ud);
+ const char *data;
if (obj->type == UCL_OBJECT) {
- GHashTable *mods_seen = g_hash_table_new(rspamd_strcase_hash,
- rspamd_strcase_equal);
- val = ucl_object_lookup(obj, "path");
+ const auto *val = ucl_object_lookup(obj, "path");
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_tostring_safe(cur, &data)) {
- if (!rspamd_rcl_add_lua_plugins_path(cfg,
- rspamd_mempool_strdup(cfg->cfg_pool, data),
+ if (!rspamd_rcl_add_lua_plugins_path(section->top,
+ cfg,
+ data,
TRUE,
- mods_seen,
err)) {
- g_hash_table_unref(mods_seen);
-
return FALSE;
}
}
CFG_RCL_ERROR,
EINVAL,
"path attribute is missing");
- g_hash_table_unref(mods_seen);
return FALSE;
}
val = ucl_object_lookup(obj, "fallback_path");
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_tostring_safe(cur, &data)) {
- if (!rspamd_rcl_add_lua_plugins_path(cfg,
- rspamd_mempool_strdup(cfg->cfg_pool, data),
+ if (!rspamd_rcl_add_lua_plugins_path(section->top,
+ cfg,
+ data,
FALSE,
- mods_seen,
err)) {
- g_hash_table_unref(mods_seen);
return FALSE;
}
val = ucl_object_lookup(obj, "try_path");
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_tostring_safe(cur, &data)) {
- if (!rspamd_rcl_add_lua_plugins_path(cfg,
- rspamd_mempool_strdup(cfg->cfg_pool, data),
+ if (!rspamd_rcl_add_lua_plugins_path(section->top,
+ cfg,
+ data,
FALSE,
- mods_seen,
err)) {
- g_hash_table_unref(mods_seen);
return FALSE;
}
}
}
}
-
- g_hash_table_unref(mods_seen);
}
else if (ucl_object_tostring_safe(obj, &data)) {
- if (!rspamd_rcl_add_lua_plugins_path(cfg,
- rspamd_mempool_strdup(cfg->cfg_pool, data), TRUE, nullptr, err)) {
+ if (!rspamd_rcl_add_lua_plugins_path(section->top, cfg, data, TRUE, err)) {
return FALSE;
}
}
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
- struct statfile_parser_data *stud = ud;
- struct rspamd_classifier_config *ccf;
- struct rspamd_config *cfg;
- const ucl_object_t *val;
- struct rspamd_statfile_config *st;
+ auto *stud = (struct statfile_parser_data *) ud;
GList *labels;
g_assert(key != nullptr);
- cfg = stud->cfg;
- ccf = stud->ccf;
+ auto *cfg = stud->cfg;
+ auto *ccf = stud->ccf;
- st = rspamd_config_new_statfile(cfg, nullptr);
+ auto *st = rspamd_config_new_statfile(cfg, nullptr);
st->symbol = rspamd_mempool_strdup(cfg->cfg_pool, key);
- if (rspamd_rcl_section_parse_defaults(cfg, section, pool, obj, st, err)) {
+ if (rspamd_rcl_section_parse_defaults(cfg, *section, pool, obj, st, err)) {
ccf->statfiles = rspamd_mempool_glist_prepend(pool, ccf->statfiles, st);
if (st->label != nullptr) {
- labels = g_hash_table_lookup(ccf->labels, st->label);
+ labels = (GList *) g_hash_table_lookup(ccf->labels, st->label);
if (labels != nullptr) {
+ /* Must use append to preserve the head stored in the hash table */
labels = g_list_append(labels, st);
}
else {
st->opts = (ucl_object_t *) obj;
st->clcf = ccf;
- val = ucl_object_lookup(obj, "spam");
+ const auto *val = ucl_object_lookup(obj, "spam");
if (val == nullptr) {
msg_info_config(
"statfile %s has no explicit 'spam' setting, trying to guess by symbol",
struct rspamd_rcl_section *section,
GError **err)
{
- const ucl_object_t *val, *cur;
- ucl_object_iter_t it = nullptr;
- struct rspamd_config *cfg = ud;
- struct statfile_parser_data stud;
- const gchar *st_key;
- struct rspamd_classifier_config *ccf;
- gboolean res = TRUE;
- struct rspamd_rcl_section *stat_section;
- struct rspamd_tokenizer_config *tkcf = nullptr;
- lua_State *L = cfg->lua_state;
+ auto *cfg = static_cast<rspamd_config *>(ud);
g_assert(key != nullptr);
- ccf = rspamd_config_new_classifier(cfg, nullptr);
+ auto *ccf = rspamd_config_new_classifier(cfg, nullptr);
+ auto *tkcf = (rspamd_tokenizer_config *) nullptr;
ccf->classifier = rspamd_mempool_strdup(cfg->cfg_pool, key);
- if (rspamd_rcl_section_parse_defaults(cfg, section, cfg->cfg_pool, obj,
+ if (rspamd_rcl_section_parse_defaults(cfg, *section, cfg->cfg_pool, obj,
ccf, err)) {
- HASH_FIND_STR(section->subsections, "statfile", stat_section);
+ auto stat_section = rspamd::find_map(section->subsections, "statfile");
if (ccf->classifier == nullptr) {
- ccf->classifier = "bayes";
+ ccf->classifier = rspamd_mempool_strdup(cfg->cfg_pool, "bayes");
}
if (ccf->name == nullptr) {
ccf->name = ccf->classifier;
}
- it = ucl_object_iterate_new(obj);
+ auto it = ucl_object_iterate_new(obj);
+ const auto *val = obj;
+ auto res = TRUE;
while ((val = ucl_object_iterate_safe(it, true)) != nullptr && res) {
- st_key = ucl_object_key(val);
+ const auto *st_key = ucl_object_key(val);
if (st_key != nullptr) {
if (g_ascii_strcasecmp(st_key, "statfile") == 0) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
- stud.cfg = cfg;
- stud.ccf = ccf;
- res = rspamd_rcl_process_section(cfg, stat_section, &stud,
+ struct statfile_parser_data stud = {.cfg = cfg, .ccf = ccf};
+ res = rspamd_rcl_process_section(cfg, *stat_section.value().get(), &stud,
cur, cfg->cfg_pool, err);
if (!res) {
}
}
else if (g_ascii_strcasecmp(st_key, "tokenizer") == 0) {
- tkcf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*tkcf));
+ tkcf = rspamd_mempool_alloc0_type(cfg->cfg_pool, rspamd_tokenizer_config);
if (ucl_object_type(val) == UCL_STRING) {
tkcf->name = ucl_object_tostring(val);
}
else if (ucl_object_type(val) == UCL_OBJECT) {
- cur = ucl_object_lookup(val, "name");
+ const auto *cur = ucl_object_lookup(val, "name");
if (cur != nullptr) {
tkcf->name = ucl_object_tostring(cur);
tkcf->opts = val;
}
if (tkcf == nullptr) {
- tkcf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*tkcf));
+ tkcf = rspamd_mempool_alloc0_type(cfg->cfg_pool, rspamd_tokenizer_config);
tkcf->name = nullptr;
}
ccf->tokenizer = tkcf;
/* Handle lua conditions */
- val = ucl_object_lookup_any(obj, "learn_condition", nullptr);
+ const auto *val = ucl_object_lookup_any(obj, "learn_condition", nullptr);
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_type(cur) == UCL_STRING) {
gint ref_idx;
lua_script = ucl_object_tolstring(cur, &slen);
- ref_idx = rspamd_lua_function_ref_from_str(L,
+ ref_idx = rspamd_lua_function_ref_from_str(RSPAMD_LUA_CFG_STATE(cfg),
lua_script, slen, "learn_condition", err);
if (ref_idx == LUA_NOREF) {
return FALSE;
}
- rspamd_lua_add_ref_dtor(L, cfg->cfg_pool, ref_idx);
+ rspamd_lua_add_ref_dtor(RSPAMD_LUA_CFG_STATE(cfg), cfg->cfg_pool, ref_idx);
ccf->learn_conditions = rspamd_mempool_glist_append(
cfg->cfg_pool,
ccf->learn_conditions,
val = ucl_object_lookup_any(obj, "classify_condition", nullptr);
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_type(cur) == UCL_STRING) {
gint ref_idx;
lua_script = ucl_object_tolstring(cur, &slen);
- ref_idx = rspamd_lua_function_ref_from_str(L,
+ ref_idx = rspamd_lua_function_ref_from_str(RSPAMD_LUA_CFG_STATE(cfg),
lua_script, slen, "classify_condition", err);
if (ref_idx == LUA_NOREF) {
return FALSE;
}
- rspamd_lua_add_ref_dtor(L, cfg->cfg_pool, ref_idx);
+ rspamd_lua_add_ref_dtor(RSPAMD_LUA_CFG_STATE(cfg), cfg->cfg_pool, ref_idx);
ccf->classify_conditions = rspamd_mempool_glist_append(
cfg->cfg_pool,
ccf->classify_conditions,
ccf->opts = (ucl_object_t *) obj;
cfg->classifiers = g_list_prepend(cfg->classifiers, ccf);
- return res;
+ return TRUE;
}
static gboolean
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_config *cfg = ud;
+ auto *cfg = static_cast<rspamd_config *>(ud);
void *composite;
const gchar *composite_name;
composite_name = key;
- const ucl_object_t *val = ucl_object_lookup(obj, "enabled");
+ const auto *val = ucl_object_lookup(obj, "enabled");
if (val != nullptr && !ucl_object_toboolean(val)) {
msg_info_config("composite %s is disabled", composite_name);
return TRUE;
struct rspamd_rcl_section *section,
GError **err)
{
- ucl_object_iter_t it = nullptr;
- const ucl_object_t *cur;
- gboolean success = TRUE;
+ auto success = TRUE;
- it = ucl_object_iterate_new(obj);
+ auto it = ucl_object_iterate_new(obj);
+ const auto *cur = obj;
while ((cur = ucl_object_iterate_safe(it, true))) {
success = rspamd_rcl_composite_handler(pool, cur,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_config *cfg = ud;
- const ucl_object_t *hostval, *pathval;
- ucl_object_t *neigh;
- gboolean has_port = FALSE, has_proto = FALSE;
- GString *urlstr;
+ auto *cfg = static_cast<rspamd_config *>(ud);
+ auto has_port = FALSE, has_proto = FALSE;
const gchar *p;
if (key == nullptr) {
return FALSE;
}
- hostval = ucl_object_lookup(obj, "host");
+ const auto *hostval = ucl_object_lookup(obj, "host");
if (hostval == nullptr || ucl_object_type(hostval) != UCL_STRING) {
g_set_error(err,
return FALSE;
}
- neigh = ucl_object_typed_new(UCL_OBJECT);
+ auto *neigh = ucl_object_typed_new(UCL_OBJECT);
ucl_object_insert_key(neigh, ucl_object_copy(hostval), "host", 0, false);
if ((p = strrchr(ucl_object_tostring(hostval), ':')) != nullptr) {
}
/* Now make url */
- urlstr = g_string_sized_new(63);
- pathval = ucl_object_lookup(obj, "path");
+ auto urlstr = std::string{};
+ const auto *pathval = ucl_object_lookup(obj, "path");
if (!has_proto) {
- g_string_append_len(urlstr, "http://", sizeof("http://") - 1);
+ urlstr += "http://";
}
- g_string_append(urlstr, ucl_object_tostring(hostval));
+ urlstr += ucl_object_tostring(hostval);
if (!has_port) {
- g_string_append(urlstr, ":11334");
+ urlstr += ":11334";
}
if (pathval == nullptr) {
- g_string_append(urlstr, "/");
+ urlstr += "/";
}
else {
- g_string_append(urlstr, ucl_object_tostring(pathval));
+ urlstr += ucl_object_tostring(pathval);
}
ucl_object_insert_key(neigh,
- ucl_object_fromlstring(urlstr->str, urlstr->len),
+ ucl_object_fromlstring(urlstr.data(), urlstr.size()),
"url", 0, false);
- g_string_free(urlstr, TRUE);
ucl_object_insert_key(cfg->neighbours, neigh, key, 0, true);
return TRUE;
struct rspamd_rcl_section *
-rspamd_rcl_add_section(struct rspamd_rcl_section **top,
+rspamd_rcl_add_section(struct rspamd_rcl_sections_map **top,
+ struct rspamd_rcl_section *parent_section,
const gchar *name, const gchar *key_attr, rspamd_rcl_handler_t handler,
enum ucl_type type, gboolean required, gboolean strict_type)
{
- struct rspamd_rcl_section *new;
- ucl_object_t *parent_doc;
-
- new = g_malloc0(sizeof(struct rspamd_rcl_section));
- new->name = name;
- new->key_attr = key_attr;
- new->handler = handler;
- new->type = type;
- new->strict_type = strict_type;
-
- if (*top == nullptr) {
- parent_doc = nullptr;
- new->doc_ref = nullptr;
- }
- else {
- parent_doc = (*top)->doc_ref;
- new->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(parent_doc,
- nullptr,
- name,
- type,
- nullptr,
- 0,
- nullptr,
- 0));
- }
-
- HASH_ADD_KEYPTR(hh, *top, new->name, strlen(new->name), new);
- return new;
+ return rspamd_rcl_add_section_doc(top, parent_section, name, key_attr, handler,
+ type, required, strict_type, nullptr, nullptr);
}
struct rspamd_rcl_section *
-rspamd_rcl_add_section_doc(struct rspamd_rcl_section **top,
+rspamd_rcl_add_section_doc(struct rspamd_rcl_sections_map **top,
+ struct rspamd_rcl_section *parent_section,
const gchar *name, const gchar *key_attr, rspamd_rcl_handler_t handler,
enum ucl_type type, gboolean required, gboolean strict_type,
ucl_object_t *doc_target,
const gchar *doc_string)
{
- struct rspamd_rcl_section *new_section;
-
- new_section = g_malloc0(sizeof(struct rspamd_rcl_section));
- new_section->name = name;
- new_section->key_attr = key_attr;
- new_section->handler = handler;
- new_section->type = type;
- new_section->strict_type = strict_type;
-
- new_section->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(doc_target,
- doc_string,
- name,
- type,
- nullptr,
- 0,
- nullptr,
- 0));
-
- HASH_ADD_KEYPTR(hh, *top, new_section->name, strlen(new_section->name), new_section);
- return new_section;
+ if (top == nullptr) {
+ g_error("invalid arguments to rspamd_rcl_add_section");
+ return nullptr;
+ }
+ if (*top == nullptr) {
+ *top = new rspamd_rcl_sections_map;
+ }
+
+ auto fill_section = [&](struct rspamd_rcl_section *section) {
+ section->name = name;
+ if (key_attr) {
+ section->key_attr = std::string{key_attr};
+ }
+ section->handler = handler;
+ section->type = type;
+ section->strict_type = strict_type;
+
+ if (doc_target == nullptr) {
+ if (parent_section && parent_section->doc_ref) {
+ section->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(parent_section->doc_ref,
+ doc_string,
+ name,
+ type,
+ nullptr,
+ 0,
+ nullptr,
+ 0));
+ }
+ else {
+ section->doc_ref = nullptr;
+ }
+ }
+ else {
+ section->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(doc_target,
+ doc_string,
+ name,
+ type,
+ nullptr,
+ 0,
+ nullptr,
+ 0));
+ }
+ section->top = *top;
+ };
+
+ /* Select the appropriate container and insert section inside it */
+ if (parent_section) {
+ auto it = parent_section->subsections.insert(std::make_pair(std::string{name},
+ std::make_shared<rspamd_rcl_section>()));
+ if (!it.second) {
+ g_error("invalid arguments to rspamd_rcl_add_section");
+ return nullptr;
+ }
+
+ fill_section(it.first->second.get());
+ return it.first->second.get();
+ }
+ else {
+ auto it = (*top)->sections.insert(std::make_pair(std::string{name},
+ std::make_shared<rspamd_rcl_section>()));
+ if (!it.second) {
+ g_error("invalid arguments to rspamd_rcl_add_section");
+ return nullptr;
+ }
+
+ (*top)->sections_order.push_back(it.first->second);
+ fill_section(it.first->second.get());
+ return it.first->second.get();
+ }
}
struct rspamd_rcl_default_handler_data *
gint flags,
const gchar *doc_string)
{
- struct rspamd_rcl_default_handler_data *nhandler;
+ auto it = section->default_parser.emplace(std::make_pair(std::string{name}, rspamd_rcl_default_handler_data{}));
- nhandler = g_malloc0(sizeof(struct rspamd_rcl_default_handler_data));
- nhandler->key = g_strdup(name);
- nhandler->handler = handler;
- nhandler->pd.offset = offset;
- nhandler->pd.flags = flags;
+ auto &nhandler = it.first->second;
+ nhandler.key = name;
+ nhandler.handler = handler;
+ nhandler.pd.offset = offset;
+ nhandler.pd.flags = flags;
if (section->doc_ref != nullptr) {
rspamd_rcl_add_doc_obj(section->doc_ref,
0);
}
- HASH_ADD_KEYPTR(hh, section->default_parser, nhandler->key, strlen(nhandler->key), nhandler);
- return nhandler;
+ return &nhandler;
}
-struct rspamd_rcl_section *
+struct rspamd_rcl_sections_map *
rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
{
- struct rspamd_rcl_section *new = nullptr, *sub, *ssub;
-
+ auto *top = new rspamd_rcl_sections_map;
/*
* Important notice:
* the order of parsing is equal to order of this initialization, therefore
* Logging section
*/
if (!(skip_sections && g_hash_table_lookup(skip_sections, "logging"))) {
- sub = rspamd_rcl_add_section_doc(&new,
- "logging", nullptr,
- rspamd_rcl_logging_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Configure rspamd logging");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "logging", nullptr,
+ rspamd_rcl_logging_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Configure rspamd logging");
/* Default handlers */
rspamd_rcl_add_default_handler(sub,
"log_buffer",
/**
* Options section
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "options", nullptr,
- rspamd_rcl_options_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Global rspamd options");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "options", nullptr,
+ rspamd_rcl_options_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Global rspamd options");
rspamd_rcl_add_default_handler(sub,
"cache_file",
rspamd_rcl_parse_struct_string,
G_STRUCT_OFFSET(struct rspamd_config, cache_reload_time),
RSPAMD_CL_FLAG_TIME_FLOAT,
"How often cache reload should be performed");
+
/* Old DNS configuration */
rspamd_rcl_add_default_handler(sub,
"dns_nameserver",
"Events backend to use: kqueue, epoll, select, poll or auto (default: auto)");
/* Neighbours configuration */
- rspamd_rcl_add_section_doc(&sub->subsections, "neighbours", "name",
+ rspamd_rcl_add_section_doc(&top, sub, "neighbours", "name",
rspamd_rcl_neighbours_handler,
UCL_OBJECT, FALSE, TRUE,
cfg->doc_strings,
"List of members of Rspamd cluster");
/* New DNS configuration */
- ssub = rspamd_rcl_add_section_doc(&sub->subsections, "dns", nullptr, nullptr,
- UCL_OBJECT, FALSE, TRUE,
- cfg->doc_strings,
- "Options for DNS resolver");
+ auto *ssub = rspamd_rcl_add_section_doc(&top, sub, "dns", nullptr, nullptr,
+ UCL_OBJECT, FALSE, TRUE,
+ cfg->doc_strings,
+ "Options for DNS resolver");
rspamd_rcl_add_default_handler(ssub,
"nameserver",
rspamd_rcl_parse_struct_ucl,
/* New upstreams configuration */
- ssub = rspamd_rcl_add_section_doc(&sub->subsections, "upstream", nullptr, nullptr,
+ ssub = rspamd_rcl_add_section_doc(&top, sub, "upstream", nullptr, nullptr,
UCL_OBJECT, FALSE, TRUE,
cfg->doc_strings,
"Upstreams configuration parameters");
/**
* Symbols and actions sections
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "actions", nullptr,
- rspamd_rcl_actions_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Actions configuration");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "actions", nullptr,
+ rspamd_rcl_actions_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Actions configuration");
rspamd_rcl_add_default_handler(sub,
"unknown_weight",
rspamd_rcl_parse_struct_double,
}
if (!(skip_sections && g_hash_table_lookup(skip_sections, "group"))) {
- sub = rspamd_rcl_add_section_doc(&new,
- "group", "name",
- rspamd_rcl_group_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Symbol groups configuration");
- ssub = rspamd_rcl_add_section_doc(&sub->subsections, "symbols", "name",
- rspamd_rcl_symbol_handler,
- UCL_OBJECT, FALSE, TRUE,
- cfg->doc_strings,
- "Symbols configuration");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "group", "name",
+ rspamd_rcl_group_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Symbol groups configuration");
+ rspamd_rcl_add_section_doc(&top, sub, "symbols", "name",
+ rspamd_rcl_symbol_handler,
+ UCL_OBJECT, FALSE, TRUE,
+ cfg->doc_strings,
+ "Symbols configuration");
/* Group part */
rspamd_rcl_add_default_handler(sub,
/**
* Worker section
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "worker", "type",
- rspamd_rcl_worker_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Workers common options");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr, "worker", "type",
+ rspamd_rcl_worker_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Workers common options");
rspamd_rcl_add_default_handler(sub,
"count",
rspamd_rcl_parse_struct_integer,
/**
* Modules handler
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "modules", nullptr,
- rspamd_rcl_modules_handler,
- UCL_OBJECT,
- FALSE,
- FALSE,
- cfg->doc_strings,
- "Lua plugins to load");
+ rspamd_rcl_add_section_doc(&top, nullptr,
+ "modules", nullptr,
+ rspamd_rcl_modules_handler,
+ UCL_OBJECT,
+ FALSE,
+ FALSE,
+ cfg->doc_strings,
+ "Lua plugins to load");
}
if (!(skip_sections && g_hash_table_lookup(skip_sections, "classifier"))) {
/**
* Classifiers handler
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "classifier", "type",
- rspamd_rcl_classifier_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "CLassifier options");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "classifier", "type",
+ rspamd_rcl_classifier_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "CLassifier options");
/* Default classifier is 'bayes' for now */
sub->default_key = "bayes";
/*
* Statfile defaults
*/
- ssub = rspamd_rcl_add_section_doc(&sub->subsections,
- "statfile", "symbol",
- rspamd_rcl_statfile_handler,
- UCL_OBJECT,
- TRUE,
- TRUE,
- sub->doc_ref,
- "Statfiles options");
+ auto *ssub = rspamd_rcl_add_section_doc(&top, sub,
+ "statfile", "symbol",
+ rspamd_rcl_statfile_handler,
+ UCL_OBJECT,
+ TRUE,
+ TRUE,
+ sub->doc_ref,
+ "Statfiles options");
rspamd_rcl_add_default_handler(ssub,
"label",
rspamd_rcl_parse_struct_string,
/**
* Composites handlers
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "composite", "name",
- rspamd_rcl_composite_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Rspamd composite symbols");
- sub = rspamd_rcl_add_section_doc(&new,
- "composites", nullptr,
- rspamd_rcl_composites_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Rspamd composite symbols");
+ rspamd_rcl_add_section_doc(&top, nullptr,
+ "composite", "name",
+ rspamd_rcl_composite_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Rspamd composite symbols");
+ rspamd_rcl_add_section_doc(&top, nullptr,
+ "composites", nullptr,
+ rspamd_rcl_composites_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Rspamd composite symbols");
}
if (!(skip_sections && g_hash_table_lookup(skip_sections, "lua"))) {
/**
* Lua handler
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "lua", nullptr,
- rspamd_rcl_lua_handler,
- UCL_STRING,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Lua files to load");
- }
-
- return new;
-}
-
-struct rspamd_rcl_section *
-rspamd_rcl_config_get_section(struct rspamd_rcl_section *top,
- const char *path)
-{
- struct rspamd_rcl_section *cur, *found = nullptr;
- char **path_components;
- gint ncomponents, i;
-
-
- if (path == nullptr) {
- return top;
- }
-
- path_components = g_strsplit_set(path, "/", -1);
- ncomponents = g_strv_length(path_components);
-
- cur = top;
- for (i = 0; i < ncomponents; i++) {
- if (cur == nullptr) {
- g_strfreev(path_components);
- return nullptr;
- }
- HASH_FIND_STR(cur, path_components[i], found);
- if (found == nullptr) {
- g_strfreev(path_components);
- return nullptr;
- }
- cur = found;
+ rspamd_rcl_add_section_doc(&top, nullptr,
+ "lua", nullptr,
+ rspamd_rcl_lua_handler,
+ UCL_STRING,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Lua files to load");
}
- g_strfreev(path_components);
- return found;
+ return top;
}
static bool
g_assert(obj != nullptr);
g_assert(sec.handler != nullptr);
- if (sec.key_attr != nullptr) {
+ if (sec.key_attr) {
it = ucl_object_iterate_new(obj);
while ((cur = ucl_object_iterate_full(it, UCL_ITERATE_EXPLICIT)) != nullptr) {
return true;
}
else {
- if (sec.key_attr != nullptr) {
+ if (sec.key_attr) {
/* First of all search for required attribute and use it as a key */
- cur = ucl_object_lookup(obj, sec.key_attr);
+ cur = ucl_object_lookup(obj, sec.key_attr.value().c_str());
if (cur == nullptr) {
- if (sec.default_key == nullptr) {
+ if (!sec.default_key) {
g_set_error(err, CFG_RCL_ERROR, EINVAL, "required attribute "
"'%s' is missing for section '%s', current key: %s",
- sec.key_attr,
- sec.name,
- ucl_object_emit(obj, UCL_EMIT_CONFIG));
+ sec.key_attr.value().c_str(),
+ sec.name.c_str(),
+ ucl_object_key(obj));
return false;
}
else {
msg_info("using default key '%s' for mandatory field '%s' "
"for section '%s'",
- sec.default_key, sec.key_attr,
- sec.name);
- key = sec.default_key;
+ sec.default_key.value().c_str(), sec.key_attr.value().c_str(),
+ sec.name.c_str());
+ key = sec.default_key.value().c_str();
}
}
else if (ucl_object_type(cur) != UCL_STRING) {
g_set_error(err, CFG_RCL_ERROR, EINVAL, "required attribute %s"
" is not a string for section %s",
- sec.key_attr, sec.name);
+ sec.key_attr.value().c_str(), sec.name.c_str());
return false;
}
}
gboolean
-rspamd_rcl_parse(struct rspamd_rcl_section *top,
+rspamd_rcl_parse(struct rspamd_rcl_sections_map *top,
struct rspamd_config *cfg,
gpointer ptr, rspamd_mempool_t *pool,
const ucl_object_t *obj, GError **err)
}
/* Iterate over known sections and ignore unknown ones */
- HASH_ITER(hh, top, cur, tmp)
- {
- if (strcmp(cur->name, "*") == 0) {
+ for (const auto &sec_ptr: top->sections_order) {
+ if (sec_ptr->name == "*") {
/* Default section handler */
+ const auto *cur_obj = obj;
LL_FOREACH(obj, cur_obj)
{
- HASH_FIND_STR(top, ucl_object_key(cur_obj), found_sec);
-
- if (found_sec == nullptr) {
- if (cur->handler != nullptr) {
- if (!rspamd_rcl_process_section(cfg, cur, ptr, cur_obj,
+ if (!top->sections.contains(ucl_object_key(cur_obj))) {
+ if (sec_ptr->handler != nullptr) {
+ if (!rspamd_rcl_process_section(cfg, *sec_ptr, ptr, cur_obj,
pool, err)) {
return FALSE;
}
}
else {
rspamd_rcl_section_parse_defaults(cfg,
- cur,
+ *sec_ptr,
pool,
cur_obj,
ptr,
}
}
else {
- found = ucl_object_lookup(obj, cur->name);
+ const auto *found = ucl_object_lookup(obj, sec_ptr->name.c_str());
if (found == nullptr) {
- if (cur->required) {
+ if (sec_ptr->required) {
g_set_error(err, CFG_RCL_ERROR, ENOENT,
- "required section %s is missing", cur->name);
+ "required section %s is missing", sec_ptr->name.c_str());
return FALSE;
}
}
else {
/* Check type */
- if (cur->strict_type) {
- if (cur->type != found->type) {
+ if (sec_ptr->strict_type) {
+ if (sec_ptr->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", sec_ptr->name.c_str());
return FALSE;
}
}
+ const auto *cur_obj = found;
LL_FOREACH(found, cur_obj)
{
- if (cur->handler != nullptr) {
- if (!rspamd_rcl_process_section(cfg, cur, ptr, cur_obj,
+ if (sec_ptr->handler != nullptr) {
+ if (!rspamd_rcl_process_section(cfg, *sec_ptr, ptr, cur_obj,
pool, err)) {
return FALSE;
}
}
else {
- rspamd_rcl_section_parse_defaults(cfg, cur,
+ rspamd_rcl_section_parse_defaults(cfg, *sec_ptr,
pool,
cur_obj,
ptr,
}
}
}
- if (cur->fin) {
- cur->fin(pool, cur->fin_ud);
+ if (sec_ptr->fin) {
+ sec_ptr->fin(pool, sec_ptr->fin_ud);
}
}
EINVAL,
"default configuration must be an object for section %s "
"(actual type is %s)",
- section.name, ucl_object_type_to_string(ucl_object_type(obj)));
+ section.name.c_str(), ucl_object_type_to_string(ucl_object_type(obj)));
return FALSE;
}
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
union {
gint *ip;
gint32 *i32p;
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
gdouble *target;
target = (gdouble *) (((gchar *) pd->user_struct) + pd->offset);
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
union {
gint *psec;
guint32 *pu32;
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
struct rspamd_cryptobox_keypair **target, *kp;
target = (struct rspamd_cryptobox_keypair **) (((gchar *) pd->user_struct) +
*target = kp;
}
else {
- gchar *dump = ucl_object_emit(obj, UCL_EMIT_JSON_COMPACT);
+ gchar *dump = (char *) ucl_object_emit(obj, UCL_EMIT_JSON_COMPACT);
g_set_error(err,
CFG_RCL_ERROR,
EINVAL,
"cannot load the keypair specified: %s; section: %s; value: %s",
- ucl_object_key(obj), section->name, dump);
+ ucl_object_key(obj), section->name.c_str(), dump);
free(dump);
return FALSE;
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
struct rspamd_cryptobox_pubkey **target, *pk;
gsize len;
const gchar *str;
- gint keypair_type = RSPAMD_KEYPAIR_KEX,
- keypair_mode = RSPAMD_CRYPTOBOX_MODE_25519;
+ rspamd_cryptobox_keypair_type keypair_type = RSPAMD_KEYPAIR_KEX;
+ rspamd_cryptobox_mode keypair_mode = RSPAMD_CRYPTOBOX_MODE_25519;
if (pd->flags & RSPAMD_CL_FLAG_SIGNKEY) {
keypair_type = RSPAMD_KEYPAIR_SIGN;
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
gpointer *target;
gchar *val, **strvec, **cvec;
const ucl_object_t *cur;
/* Go to the next object */
continue;
case UCL_INT:
- val = rspamd_mempool_alloc(pool, num_str_len);
+ val = (gchar *) rspamd_mempool_alloc(pool, num_str_len);
rspamd_snprintf(val, num_str_len, "%L", cur->value.iv);
break;
case UCL_FLOAT:
- val = rspamd_mempool_alloc(pool, num_str_len);
+ val = (gchar *) rspamd_mempool_alloc(pool, num_str_len);
rspamd_snprintf(val, num_str_len, "%f", cur->value.dv);
break;
case UCL_BOOLEAN:
- val = rspamd_mempool_alloc(pool, num_str_len);
+ val = (gchar *) rspamd_mempool_alloc(pool, num_str_len);
rspamd_snprintf(val, num_str_len, "%s",
((gboolean) cur->value.iv) ? "true" : "false");
break;
#endif
if (!is_hash && *target != nullptr) {
- *target = g_list_reverse(*target);
+ *target = g_list_reverse(*(GList **) target);
if (need_destructor) {
rspamd_mempool_add_destructor(pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
const ucl_object_t **target;
target = (const ucl_object_t **) (((gchar *) pd->user_struct) + pd->offset);
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
gboolean *target;
target = (gboolean *) (((gchar *) pd->user_struct) + pd->offset);
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
rspamd_inet_addr_t **target;
const gchar *val;
gsize size;
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
GPtrArray **target, *tmp_addr = nullptr;
const gchar *val;
ucl_object_iter_t it;
return TRUE;
}
-static guint
-rspamd_worker_param_key_hash(gconstpointer p)
-{
- const struct rspamd_worker_param_key *k = p;
- rspamd_cryptobox_fast_hash_state_t st;
-
- rspamd_cryptobox_fast_hash_init(&st, rspamd_hash_seed());
- rspamd_cryptobox_fast_hash_update(&st, k->name, strlen(k->name));
- rspamd_cryptobox_fast_hash_update(&st, &k->ptr, sizeof(gpointer));
-
- return rspamd_cryptobox_fast_hash_final(&st);
-}
-
-static gboolean
-rspamd_worker_param_key_equal(gconstpointer p1, gconstpointer p2)
-{
- const struct rspamd_worker_param_key *k1 = p1, *k2 = p2;
-
- if (k1->ptr == k2->ptr) {
- return strcmp(k1->name, k2->name) == 0;
- }
-
- return FALSE;
-}
-
void rspamd_rcl_register_worker_option(struct rspamd_config *cfg,
GQuark type,
const gchar *name,
gint flags,
const gchar *doc_string)
{
- struct rspamd_worker_param_parser *nhandler;
- struct rspamd_worker_cfg_parser *nparser;
- struct rspamd_worker_param_key srch;
- const ucl_object_t *doc_workers, *doc_target;
- ucl_object_t *doc_obj;
-
- nparser = g_hash_table_lookup(cfg->wrk_parsers, &type);
-
- if (nparser == nullptr) {
- rspamd_rcl_register_worker_parser(cfg, type, nullptr, nullptr);
- nparser = g_hash_table_lookup(cfg->wrk_parsers, &type);
+ auto parser_it = cfg->rcl_parser->workers_parser.try_emplace(type, rspamd_worker_cfg_parser{});
+ auto &parser = parser_it.first->second;
+ auto handler_it = parser.parsers.try_emplace(std::make_pair(std::string{name}, target), rspamd_worker_param_parser{});
- g_assert(nparser != nullptr);
- }
-
- srch.name = name;
- srch.ptr = target;
-
- nhandler = g_hash_table_lookup(nparser->parsers, &srch);
- if (nhandler != nullptr) {
+ if (!handler_it.second) {
msg_warn_config(
"handler for parameter %s is already registered for worker type %s",
name,
return;
}
- nhandler =
- rspamd_mempool_alloc0(cfg->cfg_pool,
- sizeof(struct rspamd_worker_param_parser));
- nhandler->key.name = name;
- nhandler->key.ptr = target;
- nhandler->parser.flags = flags;
- nhandler->parser.offset = offset;
- nhandler->parser.user_struct = target;
- nhandler->handler = handler;
-
- g_hash_table_insert(nparser->parsers, &nhandler->key, nhandler);
+ auto nhandler = handler_it.first->second;
+ nhandler.parser.flags = flags;
+ nhandler.parser.offset = offset;
+ nhandler.parser.user_struct = target;
+ nhandler.handler = handler;
- doc_workers = ucl_object_lookup(cfg->doc_strings, "workers");
+ const auto *doc_workers = ucl_object_lookup(cfg->doc_strings, "workers");
if (doc_workers == nullptr) {
- doc_obj = ucl_object_typed_new(UCL_OBJECT);
+ auto *doc_obj = ucl_object_typed_new(UCL_OBJECT);
ucl_object_insert_key(cfg->doc_strings, doc_obj, "workers", 0, false);
doc_workers = doc_obj;
}
- doc_target = ucl_object_lookup(doc_workers, g_quark_to_string(type));
+ const auto *doc_target = ucl_object_lookup(doc_workers, g_quark_to_string(type));
if (doc_target == nullptr) {
- doc_obj = ucl_object_typed_new(UCL_OBJECT);
+ auto *doc_obj = ucl_object_typed_new(UCL_OBJECT);
ucl_object_insert_key((ucl_object_t *) doc_workers, doc_obj,
g_quark_to_string(type), 0, true);
doc_target = doc_obj;
0);
}
-
-void rspamd_rcl_register_worker_parser(struct rspamd_rcl_sections_map *sections, gint type,
- gboolean (*func)(ucl_object_t *, gpointer), gpointer ud)
-{
- struct rspamd_worker_cfg_parser *nparser;
-
- nparser = g_hash_table_lookup(cfg->wrk_parsers, &type);
-
- if (nparser == nullptr) {
- /* Allocate new parser for this worker */
- nparser =
- rspamd_mempool_alloc0(cfg->cfg_pool,
- sizeof(struct rspamd_worker_cfg_parser));
- nparser->type = type;
- nparser->parsers = g_hash_table_new(rspamd_worker_param_key_hash,
- rspamd_worker_param_key_equal);
- rspamd_mempool_add_destructor(cfg->cfg_pool,
- (rspamd_mempool_destruct_t) g_hash_table_unref, nparser->parsers);
-
- g_hash_table_insert(cfg->wrk_parsers, &nparser->type, nparser);
- }
-
- nparser->def_obj_parser = func;
- nparser->def_ud = ud;
-}
-
/* Checksum functions */
static int
rspamd_rcl_emitter_append_c(unsigned char c, size_t nchars, void *ud)
{
- rspamd_cryptobox_hash_state_t *hs = ud;
+ auto *hs = (rspamd_cryptobox_hash_state_t *) ud;
guint64 d[2];
d[0] = nchars;
static int
rspamd_rcl_emitter_append_len(unsigned const char *str, size_t len, void *ud)
{
- rspamd_cryptobox_hash_state_t *hs = ud;
+ auto *hs = (rspamd_cryptobox_hash_state_t *) ud;
rspamd_cryptobox_hash_update(hs, str, len);
static int
rspamd_rcl_emitter_append_int(int64_t elt, void *ud)
{
- rspamd_cryptobox_hash_state_t *hs = ud;
+ auto *hs = (rspamd_cryptobox_hash_state_t *) ud;
rspamd_cryptobox_hash_update(hs, (const guchar *) &elt, sizeof(elt));
static int
rspamd_rcl_emitter_append_double(double elt, void *ud)
{
- rspamd_cryptobox_hash_state_t *hs = ud;
+ auto *hs = (rspamd_cryptobox_hash_state_t *) ud;
rspamd_cryptobox_hash_update(hs, (const guchar *) &elt, sizeof(elt));
return 0;
}
-void rspamd_rcl_section_free(gpointer p)
+void rspamd_rcl_sections_free(struct rspamd_rcl_sections_map *sections)
{
- struct rspamd_rcl_section *top = p, *cur, *tmp;
- struct rspamd_rcl_default_handler_data *dh, *dhtmp;
-
- HASH_ITER(hh, top, cur, tmp)
- {
- HASH_DEL(top, cur);
-
- if (cur->subsections) {
- rspamd_rcl_section_free(cur->subsections);
- }
-
- HASH_ITER(hh, cur->default_parser, dh, dhtmp)
- {
- HASH_DEL(cur->default_parser, dh);
- g_free(dh->key);
- g_free(dh);
- }
-
- ucl_object_unref(cur->doc_ref);
- g_free(cur);
- }
+ delete sections;
}
/**
*/
void rspamd_rcl_maybe_apply_lua_transform(struct rspamd_config *cfg)
{
- lua_State *L = cfg->lua_state;
+ auto *L = RSPAMD_LUA_CFG_STATE(cfg);
gint err_idx, ret;
gchar str[PATH_MAX];
static const char *transform_script = "lua_cfg_transform";