@@ -480,7 +480,7 @@ struct rspamd_classifier_config * rspamd_config_find_classifier ( | |||
* 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_compressed_t **tree); | |||
void rspamd_ucl_add_conf_macros (struct ucl_parser *parser, | |||
struct rspamd_config *cfg); |
@@ -1005,27 +1005,13 @@ rspamd_ucl_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) | |||
} | |||
gboolean | |||
rspamd_config_parse_ip_list (const gchar *ip_list, radix_tree_t **tree) | |||
rspamd_config_parse_ip_list (const gchar *ip_list, radix_compressed_t **tree) | |||
{ | |||
gchar **strvec, **cur; | |||
struct in_addr ina; | |||
guint32 mask; | |||
strvec = g_strsplit_set (ip_list, ",", 0); | |||
cur = strvec; | |||
while (*cur != NULL) { | |||
/* XXX: handle only ipv4 addresses */ | |||
if (parse_ipmask_v4 (*cur, &ina, &mask)) { | |||
if (*tree == NULL) { | |||
*tree = radix_tree_create (); | |||
} | |||
radix32tree_add (*tree, htonl (ina.s_addr), mask, 1); | |||
} | |||
cur++; | |||
if (*tree == NULL) { | |||
*tree = radix_create_compressed (); | |||
} | |||
return (*tree != NULL); | |||
return (rspamd_radix_add_iplist (ip_list, ",; ", *tree) > 0); | |||
} | |||
/* |
@@ -798,65 +798,7 @@ radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value) | |||
{ | |||
radix_compressed_t *tree = (radix_compressed_t *)st; | |||
gchar *token, *ipnet, *err_str, **strv, **cur; | |||
struct in_addr ina; | |||
struct in6_addr ina6; | |||
guint k = 0; | |||
gint af; | |||
/* Split string if there are multiple items inside a single string */ | |||
strv = g_strsplit_set ((gchar *)key, " ,;", 0); | |||
cur = strv; | |||
while (*cur) { | |||
af = AF_UNSPEC; | |||
if (**cur == '\0') { | |||
cur++; | |||
continue; | |||
} | |||
/* Extract ipnet */ | |||
ipnet = *cur; | |||
token = strsep (&ipnet, "/"); | |||
if (ipnet != NULL) { | |||
errno = 0; | |||
/* 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)); | |||
k = 32; | |||
} | |||
} | |||
/* Check IP */ | |||
if (inet_pton (AF_INET, token, &ina) == 1) { | |||
af = AF_INET; | |||
} | |||
else if (inet_pton (AF_INET6, token, &ina6) == 1) { | |||
af = AF_INET6; | |||
} | |||
else { | |||
msg_warn ("invalid IP address: %s", token); | |||
} | |||
if (af == AF_INET) { | |||
if (k > 32) { | |||
k = 32; | |||
} | |||
radix_insert_compressed (tree, (guint8 *)&ina, sizeof (ina), 32 - k, 1); | |||
} | |||
else if (af == AF_INET6){ | |||
if (k > 128) { | |||
k = 128; | |||
} | |||
radix_insert_compressed (tree, (guint8 *)&ina6, sizeof (ina6), 128 - k, 1); | |||
} | |||
cur++; | |||
} | |||
g_strfreev (strv); | |||
rspamd_radix_add_iplist ((gchar *)key, " ,;", tree); | |||
} | |||
/* Helpers */ |
@@ -887,6 +887,78 @@ radix_find_compressed_addr (radix_compressed_t *tree, rspamd_inet_addr_t *addr) | |||
return RADIX_NO_VALUE; | |||
} | |||
gint | |||
rspamd_radix_add_iplist (const gchar *list, const gchar *separators, | |||
radix_compressed_t *tree) | |||
{ | |||
gchar *token, *ipnet, *err_str, **strv, **cur; | |||
struct in_addr ina; | |||
struct in6_addr ina6; | |||
guint k = 0; | |||
gint af; | |||
gint res = 0; | |||
/* Split string if there are multiple items inside a single string */ | |||
strv = g_strsplit_set (list, separators, 0); | |||
cur = strv; | |||
while (*cur) { | |||
af = AF_UNSPEC; | |||
if (**cur == '\0') { | |||
cur++; | |||
continue; | |||
} | |||
/* Extract ipnet */ | |||
ipnet = *cur; | |||
token = strsep (&ipnet, "/"); | |||
if (ipnet != NULL) { | |||
errno = 0; | |||
/* 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)); | |||
k = 32; | |||
} | |||
} | |||
/* Check IP */ | |||
if (inet_pton (AF_INET, token, &ina) == 1) { | |||
af = AF_INET; | |||
} | |||
else if (inet_pton (AF_INET6, token, &ina6) == 1) { | |||
af = AF_INET6; | |||
} | |||
else { | |||
msg_warn ("invalid IP address: %s", token); | |||
} | |||
if (af == AF_INET) { | |||
if (k > 32) { | |||
k = 32; | |||
} | |||
radix_insert_compressed (tree, (guint8 *)&ina, sizeof (ina), | |||
32 - k, 1); | |||
res ++; | |||
} | |||
else if (af == AF_INET6){ | |||
if (k > 128) { | |||
k = 128; | |||
} | |||
radix_insert_compressed (tree, (guint8 *)&ina6, sizeof (ina6), | |||
128 - k, 1); | |||
res ++; | |||
} | |||
cur++; | |||
} | |||
g_strfreev (strv); | |||
return res; | |||
} | |||
/* | |||
* vi:ts=4 | |||
*/ |
@@ -117,4 +117,14 @@ void radix_destroy_compressed (radix_compressed_t *tree); | |||
radix_compressed_t *radix_create_compressed (void); | |||
/** | |||
* Insert list of ip addresses and masks to the radix tree | |||
* @param list string line of addresses | |||
* @param separators string of characters used as separators | |||
* @param tree target tree | |||
* @return number of elements inserted | |||
*/ | |||
gint rspamd_radix_add_iplist (const gchar *list, const gchar *separators, | |||
radix_compressed_t *tree); | |||
#endif |
@@ -1855,43 +1855,6 @@ rspamd_str_pool_copy (gconstpointer data, gpointer ud) | |||
return data ? rspamd_mempool_strdup (pool, data) : NULL; | |||
} | |||
gboolean | |||
parse_ipmask_v4 (const char *line, struct in_addr *ina, int *mask) | |||
{ | |||
const char *pos; | |||
char ip_buf[INET_ADDRSTRLEN + 1], mask_buf[3] = { '\0', '\0', '\0' }; | |||
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 (mask_buf, pos + 1, sizeof (mask_buf)); | |||
} | |||
else { | |||
rspamd_strlcpy (ip_buf, line, sizeof (ip_buf)); | |||
} | |||
if (!inet_aton (ip_buf, ina)) { | |||
return FALSE; | |||
} | |||
if (mask_buf[0] != '\0') { | |||
/* Also parse mask */ | |||
*mask = (mask_buf[0] - '0') * 10 + mask_buf[1] - '0'; | |||
if (*mask > 32) { | |||
return FALSE; | |||
} | |||
} | |||
else { | |||
*mask = 32; | |||
} | |||
*mask = G_MAXUINT32 << (32 - *mask); | |||
return TRUE; | |||
} | |||
static volatile sig_atomic_t saved_signo[NSIG]; | |||
static | |||
@@ -2253,7 +2216,7 @@ rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type, | |||
*/ | |||
gchar * | |||
rspamd_encode_base32(guchar *in, gsize inlen) | |||
rspamd_encode_base32 (guchar *in, gsize inlen) | |||
{ | |||
gint remain = -1, r, x; | |||
gsize i; |
@@ -407,15 +407,6 @@ void rspamd_hash_table_copy (GHashTable *src, GHashTable *dst, | |||
*/ | |||
gpointer rspamd_str_pool_copy (gconstpointer data, gpointer ud); | |||
/** | |||
* Parse ipv4 address with optional mask in CIDR format | |||
* @param line cidr notation of ipv4 address | |||
* @param ina destination address | |||
* @param mask destination mask | |||
* @return | |||
*/ | |||
gboolean parse_ipmask_v4 (const char *line, struct in_addr *ina, int *mask); | |||
/** | |||
* Read passphrase from tty | |||
* @param buf buffer to fill with a password | |||
@@ -495,6 +486,6 @@ int rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type, | |||
* @param inlen input length | |||
* @return freshly allocated base32 encoding of a specified string | |||
*/ | |||
gchar * rspamd_encode_base32(guchar *in, gsize inlen); | |||
gchar * rspamd_encode_base32 (guchar *in, gsize inlen); | |||
#endif |