From 6ec67947dadeba207104ac0e2c65c9e10a3a580d Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 1 Oct 2014 15:58:23 +0100 Subject: [PATCH] Rework addresses parsing. --- src/libserver/cfg_file.h | 2 +- src/libserver/cfg_utils.c | 22 +++--------- src/libutil/map.c | 60 +------------------------------- src/libutil/radix.c | 72 +++++++++++++++++++++++++++++++++++++++ src/libutil/radix.h | 10 ++++++ src/libutil/util.c | 39 +-------------------- src/libutil/util.h | 11 +----- 7 files changed, 90 insertions(+), 126 deletions(-) diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h index a16541ebe..7e3d60db8 100644 --- a/src/libserver/cfg_file.h +++ b/src/libserver/cfg_file.h @@ -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); diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c index 4d2b86880..aecef53d4 100644 --- a/src/libserver/cfg_utils.c +++ b/src/libserver/cfg_utils.c @@ -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); } /* diff --git a/src/libutil/map.c b/src/libutil/map.c index 7d0313d95..89ab75b64 100644 --- a/src/libutil/map.c +++ b/src/libutil/map.c @@ -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 */ diff --git a/src/libutil/radix.c b/src/libutil/radix.c index acf276285..240a7d67d 100644 --- a/src/libutil/radix.c +++ b/src/libutil/radix.c @@ -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 */ diff --git a/src/libutil/radix.h b/src/libutil/radix.h index 38af00b51..5bf6a1dd8 100644 --- a/src/libutil/radix.h +++ b/src/libutil/radix.h @@ -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 diff --git a/src/libutil/util.c b/src/libutil/util.c index a4117d3c3..73ab64453 100644 --- a/src/libutil/util.c +++ b/src/libutil/util.c @@ -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; diff --git a/src/libutil/util.h b/src/libutil/util.h index 1b95ab8a0..40d8004e3 100644 --- a/src/libutil/util.h +++ b/src/libutil/util.h @@ -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 -- 2.39.5