From: Timo Sirainen Date: Fri, 3 Nov 2017 23:43:41 +0000 (+0200) Subject: lib: net_addr2ip() - Optimize for parsing IPv4 addresses X-Git-Tag: 2.3.0.rc1~576 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1c0491ba032261214900e0795efd49b3e264da9d;p=thirdparty%2Fdovecot%2Fcore.git lib: net_addr2ip() - Optimize for parsing IPv4 addresses --- diff --git a/src/lib/net.c b/src/lib/net.c index 1e7763d748..ce24b8bedc 100644 --- a/src/lib/net.c +++ b/src/lib/net.c @@ -892,10 +892,48 @@ const char *net_ip2addr(const struct ip_addr *ip) return addr; } +static bool net_addr2ip_inet4_fast(const char *addr, struct ip_addr *ip) +{ + uint8_t *s_addr = (void *)&ip->u.ip4.s_addr; + unsigned int i, num; + + if (str_parse_uint(addr, &num, &addr) < 0) + return FALSE; + if (*addr == '\0' && num <= 0xffffffff) { + /* single-number IPv4 address */ + ip->u.ip4.s_addr = htonl(num); + ip->family = AF_INET; + return TRUE; + } + + /* try to parse as a.b.c.d */ + i = 0; + for (;;) { + if (num >= 256) + return FALSE; + s_addr[i] = num; + if (i == 3) + break; + i++; + if (*addr != '.') + return FALSE; + addr++; + if (str_parse_uint(addr, &num, &addr) < 0) + return FALSE; + } + if (*addr != '\0') + return FALSE; + ip->family = AF_INET; + return TRUE; +} + int net_addr2ip(const char *addr, struct ip_addr *ip) { int ret; + if (net_addr2ip_inet4_fast(addr, ip)) + return 0; + if (strchr(addr, ':') != NULL) { /* IPv6 */ T_BEGIN { diff --git a/src/lib/test-net.c b/src/lib/test-net.c index 23a90efefa..b6b88bc368 100644 --- a/src/lib/test-net.c +++ b/src/lib/test-net.c @@ -65,12 +65,22 @@ static void test_net_ip2addr(void) test_assert(net_addr2ip("127.0.0.1", &ip) == 0 && ip.family == AF_INET && ntohl(ip.u.ip4.s_addr) == (0x7f000001)); + test_assert(net_addr2ip("2130706433", &ip) == 0 && + ip.family == AF_INET && + ntohl(ip.u.ip4.s_addr) == (0x7f000001)); + test_assert(strcmp(net_ip2addr(&ip), "127.0.0.1") == 0); + test_assert(net_addr2ip("255.254.253.252", &ip) == 0 && + ip.family == AF_INET && + ntohl(ip.u.ip4.s_addr) == (0xfffefdfc)); + test_assert(strcmp(net_ip2addr(&ip), "255.254.253.252") == 0); test_assert(net_addr2ip("::5", &ip) == 0 && ip.family == AF_INET6 && ip.u.ip6.s6_addr[15] == 5); + test_assert(strcmp(net_ip2addr(&ip), "::5") == 0); test_assert(net_addr2ip("[::5]", &ip) == 0 && ip.family == AF_INET6 && ip.u.ip6.s6_addr[15] == 5); + test_assert(strcmp(net_ip2addr(&ip), "::5") == 0); ip.family = 123; test_assert(net_addr2ip("abc", &ip) < 0 && ip.family == 123);