From fd6eab56f4f13174b0cfeee2b30f0e956b7ba97c Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 1 Apr 2015 15:33:46 +0100 Subject: [PATCH] Parse more forms of IP addresses. [::1]:port [::1] 127.0.0.1:port --- src/libutil/addr.c | 94 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 12 deletions(-) diff --git a/src/libutil/addr.c b/src/libutil/addr.c index 38cd73200..4a48ab7e8 100644 --- a/src/libutil/addr.c +++ b/src/libutil/addr.c @@ -346,6 +346,10 @@ rspamd_parse_inet_address (rspamd_inet_addr_t **target, const char *src) gboolean ret = FALSE; rspamd_inet_addr_t *addr = NULL; union sa_inet su; + const char *end; + char ipbuf[INET6_ADDRSTRLEN + 1]; + guint iplen; + guint portnum; g_assert (src != NULL); g_assert (target != NULL); @@ -355,18 +359,84 @@ rspamd_parse_inet_address (rspamd_inet_addr_t **target, const char *src) if (src[0] == '/' || src[0] == '.') { return rspamd_parse_unix_path (target, src); } - else if (inet_pton (AF_INET, src, &su.s4.sin_addr) == 1) { - addr = rspamd_inet_addr_create (AF_INET); - memcpy (&addr->u.in.addr.s4.sin_addr, &su.s4.sin_addr, - sizeof (struct in_addr)); - ret = TRUE; - } - else if (ipv6_status == RSPAMD_IPV6_SUPPORTED && - inet_pton (AF_INET6, src, &su.s6.sin6_addr) == 1) { - addr = rspamd_inet_addr_create (AF_INET6); - memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr, - sizeof (struct in6_addr)); - ret = TRUE; + + if (src[0] == '[') { + /* Ipv6 address in format [::1]:port or just [::1] */ + end = strrchr (src + 1, ']'); + + if (end == NULL) { + return FALSE; + } + + iplen = end - src - 1; + + if (iplen == 0 || iplen > sizeof (ipbuf)) { + return FALSE; + } + + rspamd_strlcpy (ipbuf, src + 1, iplen); + + if (ipv6_status == RSPAMD_IPV6_SUPPORTED && + inet_pton (AF_INET6, ipbuf, &su.s6.sin6_addr) == 1) { + addr = rspamd_inet_addr_create (AF_INET6); + memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr, + sizeof (struct in6_addr)); + ret = TRUE; + } + + if (ret && end[1] == ':') { + /* Port part */ + portnum = strtoul (end + 1, NULL, 10); + rspamd_inet_address_set_port (addr, portnum); + } + } + else { + + if ((end = strchr (src, ':')) != NULL) { + /* This is either port number and ipv4 addr or ipv6 addr */ + if (ipv6_status == RSPAMD_IPV6_SUPPORTED && + inet_pton (AF_INET6, src, &su.s6.sin6_addr) == 1) { + addr = rspamd_inet_addr_create (AF_INET6); + memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr, + sizeof (struct in6_addr)); + ret = TRUE; + } + else { + /* Not ipv6, so try ip:port */ + iplen = end - src; + + if (iplen > sizeof (ipbuf)) { + return FALSE; + } + else { + rspamd_strlcpy (ipbuf, src, iplen); + } + + if (inet_pton (AF_INET, ipbuf, &su.s4.sin_addr) == 1) { + addr = rspamd_inet_addr_create (AF_INET); + memcpy (&addr->u.in.addr.s4.sin_addr, &su.s4.sin_addr, + sizeof (struct in_addr)); + portnum = strtoul (end + 1, NULL, 10); + rspamd_inet_address_set_port (addr, portnum); + ret = TRUE; + } + } + } + else { + if (inet_pton (AF_INET, src, &su.s4.sin_addr) == 1) { + addr = rspamd_inet_addr_create (AF_INET); + memcpy (&addr->u.in.addr.s4.sin_addr, &su.s4.sin_addr, + sizeof (struct in_addr)); + ret = TRUE; + } + else if (ipv6_status == RSPAMD_IPV6_SUPPORTED && + inet_pton (AF_INET6, src, &su.s6.sin6_addr) == 1) { + addr = rspamd_inet_addr_create (AF_INET6); + memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr, + sizeof (struct in6_addr)); + ret = TRUE; + } + } } if (ret && target) { -- 2.39.5