|
|
@@ -49,11 +49,13 @@ struct rspamd_ucl_map_cbdata { |
|
|
|
static gchar* rspamd_ucl_read_cb (memory_pool_t * pool, gchar * chunk, gint len, struct map_cb_data *data); |
|
|
|
static void rspamd_ucl_fin_cb (memory_pool_t * pool, struct map_cb_data *data); |
|
|
|
|
|
|
|
gboolean |
|
|
|
parse_host_port_priority (memory_pool_t *pool, const gchar *str, gchar **addr, guint16 *port, guint *priority) |
|
|
|
static gboolean |
|
|
|
parse_host_port_priority_strv (memory_pool_t *pool, gchar **tokens, |
|
|
|
gchar **addr, guint16 *port, guint *priority, guint default_port) |
|
|
|
{ |
|
|
|
gchar **tokens, *err_str, *cur_tok; |
|
|
|
struct addrinfo hints, *res; |
|
|
|
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 { |
|
|
@@ -61,70 +63,46 @@ parse_host_port_priority (memory_pool_t *pool, const gchar *str, gchar **addr, g |
|
|
|
struct sockaddr_in6 v6; |
|
|
|
} addr_holder; |
|
|
|
|
|
|
|
tokens = g_strsplit_set (str, ":", 0); |
|
|
|
if (!tokens || !tokens[0]) { |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
/* Now try to parse host and write address to ina */ |
|
|
|
memset (&hints, 0, sizeof (hints)); |
|
|
|
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ |
|
|
|
hints.ai_socktype = SOCK_STREAM; /* Type of the socket */ |
|
|
|
hints.ai_flags = 0; |
|
|
|
hints.ai_protocol = 0; /* Any protocol */ |
|
|
|
hints.ai_canonname = NULL; |
|
|
|
hints.ai_addr = NULL; |
|
|
|
hints.ai_next = NULL; |
|
|
|
|
|
|
|
if (strcmp (tokens[0], "*") == 0) { |
|
|
|
/* XXX: actually we still cannot listen on multiply protocols */ |
|
|
|
if (pool != NULL) { |
|
|
|
*addr = memory_pool_alloc (pool, INET_ADDRSTRLEN + 1); |
|
|
|
} |
|
|
|
rspamd_strlcpy (*addr, "0.0.0.0", INET_ADDRSTRLEN + 1); |
|
|
|
goto port_parse; |
|
|
|
} |
|
|
|
else { |
|
|
|
cur_tok = tokens[0]; |
|
|
|
} |
|
|
|
hints.ai_flags = AI_NUMERICSERV; |
|
|
|
|
|
|
|
if ((r = getaddrinfo (cur_tok, NULL, &hints, &res)) == 0) { |
|
|
|
memcpy (&addr_holder, res->ai_addr, MIN (sizeof (addr_holder), res->ai_addrlen)); |
|
|
|
if (res->ai_family == AF_INET) { |
|
|
|
if (pool != NULL) { |
|
|
|
*addr = memory_pool_alloc (pool, INET_ADDRSTRLEN + 1); |
|
|
|
} |
|
|
|
inet_ntop (res->ai_family, &addr_holder.v4.sin_addr, *addr, INET_ADDRSTRLEN + 1); |
|
|
|
} |
|
|
|
else { |
|
|
|
if (pool != NULL) { |
|
|
|
*addr = memory_pool_alloc (pool, INET6_ADDRSTRLEN + 1); |
|
|
|
} |
|
|
|
inet_ntop (res->ai_family, &addr_holder.v6.sin6_addr, *addr, INET6_ADDRSTRLEN + 1); |
|
|
|
} |
|
|
|
freeaddrinfo (res); |
|
|
|
cur_tok = tokens[0]; |
|
|
|
|
|
|
|
if (strcmp (cur_tok, "*v6") == 0) { |
|
|
|
hints.ai_family = AF_INET6; |
|
|
|
hints.ai_flags |= AI_PASSIVE; |
|
|
|
cur_tok = NULL; |
|
|
|
} |
|
|
|
else if (strcmp (cur_tok, "*v4") == 0) { |
|
|
|
hints.ai_family = AF_INET; |
|
|
|
hints.ai_flags |= AI_PASSIVE; |
|
|
|
cur_tok = NULL; |
|
|
|
} |
|
|
|
else { |
|
|
|
msg_err ("address resolution for %s failed: %s", tokens[0], gai_strerror (r)); |
|
|
|
goto err; |
|
|
|
hints.ai_family = AF_UNSPEC; |
|
|
|
} |
|
|
|
|
|
|
|
port_parse: |
|
|
|
if (tokens[1] != NULL) { |
|
|
|
/* Port part */ |
|
|
|
rspamd_strlcpy (portbuf, tokens[1], sizeof (portbuf)); |
|
|
|
cur_port = portbuf; |
|
|
|
if (port != NULL) { |
|
|
|
errno = 0; |
|
|
|
port_parsed = strtoul (tokens[1], &err_str, 10); |
|
|
|
if (*err_str != '\0' || errno != 0) { |
|
|
|
msg_warn ("cannot parse port: %s, at symbol %c, error: %s", tokens[1], *err_str, strerror (errno)); |
|
|
|
goto err; |
|
|
|
hints.ai_flags ^= AI_NUMERICSERV; |
|
|
|
} |
|
|
|
if (port_parsed > G_MAXUINT16) { |
|
|
|
else if (port_parsed > G_MAXUINT16) { |
|
|
|
errno = ERANGE; |
|
|
|
msg_warn ("cannot parse port: %s, error: %s", tokens[1], *err_str, strerror (errno)); |
|
|
|
goto err; |
|
|
|
hints.ai_flags ^= AI_NUMERICSERV; |
|
|
|
} |
|
|
|
else { |
|
|
|
*port = port_parsed; |
|
|
|
} |
|
|
|
*port = port_parsed; |
|
|
|
} |
|
|
|
if (priority != NULL) { |
|
|
|
if (port != NULL) { |
|
|
@@ -139,24 +117,69 @@ port_parse: |
|
|
|
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)); |
|
|
|
goto err; |
|
|
|
} |
|
|
|
*priority = priority_parsed; |
|
|
|
else { |
|
|
|
*priority = priority_parsed; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if (default_port != 0) { |
|
|
|
rspamd_snprintf (portbuf, sizeof (portbuf), "%u", default_port); |
|
|
|
cur_port = portbuf; |
|
|
|
} |
|
|
|
else { |
|
|
|
cur_port = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if ((r = getaddrinfo (cur_tok, cur_port, &hints, &res)) == 0) { |
|
|
|
memcpy (&addr_holder, res->ai_addr, MIN (sizeof (addr_holder), res->ai_addrlen)); |
|
|
|
if (res->ai_family == AF_INET) { |
|
|
|
if (pool != NULL) { |
|
|
|
*addr = memory_pool_alloc (pool, INET_ADDRSTRLEN + 1); |
|
|
|
} |
|
|
|
inet_ntop (res->ai_family, &addr_holder.v4.sin_addr, *addr, INET_ADDRSTRLEN + 1); |
|
|
|
} |
|
|
|
else { |
|
|
|
if (pool != NULL) { |
|
|
|
*addr = memory_pool_alloc (pool, INET6_ADDRSTRLEN + 1); |
|
|
|
} |
|
|
|
inet_ntop (res->ai_family, &addr_holder.v6.sin6_addr, *addr, INET6_ADDRSTRLEN + 1); |
|
|
|
} |
|
|
|
freeaddrinfo (res); |
|
|
|
} |
|
|
|
else { |
|
|
|
msg_err ("address resolution for %s failed: %s", tokens[0], gai_strerror (r)); |
|
|
|
goto err; |
|
|
|
} |
|
|
|
|
|
|
|
/* Restore errno */ |
|
|
|
errno = saved_errno; |
|
|
|
g_strfreev (tokens); |
|
|
|
return TRUE; |
|
|
|
|
|
|
|
err: |
|
|
|
errno = saved_errno; |
|
|
|
g_strfreev (tokens); |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
gboolean |
|
|
|
parse_host_port_priority (memory_pool_t *pool, const gchar *str, gchar **addr, guint16 *port, guint *priority) |
|
|
|
{ |
|
|
|
gchar **tokens; |
|
|
|
gboolean ret; |
|
|
|
|
|
|
|
tokens = g_strsplit_set (str, ":", 0); |
|
|
|
if (!tokens || !tokens[0]) { |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
ret = parse_host_port_priority_strv (pool, tokens, addr, port, priority, 0); |
|
|
|
|
|
|
|
g_strfreev (tokens); |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
gboolean |
|
|
|
parse_host_port (memory_pool_t *pool, const gchar *str, gchar **addr, guint16 *port) |
|
|
|
{ |
|
|
@@ -173,28 +196,58 @@ gboolean |
|
|
|
parse_bind_line (struct config_file *cfg, struct worker_conf *cf, const gchar *str) |
|
|
|
{ |
|
|
|
struct rspamd_worker_bind_conf *cnf; |
|
|
|
gchar **tokens, *tmp; |
|
|
|
gboolean ret; |
|
|
|
|
|
|
|
if (str == NULL) |
|
|
|
return 0; |
|
|
|
if (str == NULL) { |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
tokens = g_strsplit_set (str, ":", 0); |
|
|
|
if (!tokens || !tokens[0]) { |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
cnf = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_worker_bind_conf)); |
|
|
|
cnf->bind_port = DEFAULT_BIND_PORT; |
|
|
|
cnf->bind_host = memory_pool_strdup (cfg->cfg_pool, str); |
|
|
|
cnf->ai = AF_UNSPEC; |
|
|
|
|
|
|
|
if (str[0] == '/' || str[0] == '.') { |
|
|
|
cnf->bind_host = memory_pool_strdup (cfg->cfg_pool, str); |
|
|
|
cnf->is_unix = TRUE; |
|
|
|
if (*tokens[0] == '/' || *tokens[0] == '.') { |
|
|
|
cnf->ai = AF_UNIX; |
|
|
|
LL_PREPEND (cf->bind_conf, cnf); |
|
|
|
return TRUE; |
|
|
|
} |
|
|
|
else { |
|
|
|
else if (strcmp (tokens[0], "*") == 0) { |
|
|
|
/* We need to add two listen entries: one for ipv4 and one for ipv6 */ |
|
|
|
tmp = tokens[0]; |
|
|
|
tokens[0] = "*v4"; |
|
|
|
cnf->ai = AF_INET; |
|
|
|
if ((ret = parse_host_port_priority_strv (cfg->cfg_pool, tokens, |
|
|
|
&cnf->bind_host, &cnf->bind_port, NULL, DEFAULT_BIND_PORT))) { |
|
|
|
LL_PREPEND (cf->bind_conf, cnf); |
|
|
|
} |
|
|
|
cnf = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_worker_bind_conf)); |
|
|
|
cnf->bind_port = DEFAULT_BIND_PORT; |
|
|
|
cnf->bind_host = memory_pool_strdup (cfg->cfg_pool, str); |
|
|
|
if (parse_host_port (cfg->cfg_pool, str, &cnf->bind_host, &cnf->bind_port)) { |
|
|
|
cnf->ai = AF_INET6; |
|
|
|
tokens[0] = "*v6"; |
|
|
|
if ((ret &= parse_host_port_priority_strv (cfg->cfg_pool, tokens, |
|
|
|
&cnf->bind_host, &cnf->bind_port, NULL, DEFAULT_BIND_PORT))) { |
|
|
|
LL_PREPEND (cf->bind_conf, cnf); |
|
|
|
} |
|
|
|
tokens[0] = tmp; |
|
|
|
} |
|
|
|
else { |
|
|
|
if ((ret = parse_host_port_priority_strv (cfg->cfg_pool, tokens, |
|
|
|
&cnf->bind_host, &cnf->bind_port, NULL, DEFAULT_BIND_PORT))) { |
|
|
|
LL_PREPEND (cf->bind_conf, cnf); |
|
|
|
return TRUE; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return FALSE; |
|
|
|
g_strfreev (tokens); |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
@@ -220,7 +273,6 @@ init_defaults (struct config_file *cfg) |
|
|
|
/* 20 Kb */ |
|
|
|
cfg->max_diff = 20480; |
|
|
|
|
|
|
|
cfg->max_statfile_size = DEFAULT_STATFILE_SIZE; |
|
|
|
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); |