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.2.34~250 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3f0c3d58e777d468233ee7529b9e68aa18d0baa5;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 2facbd97d7..66031ffa08 100644 --- a/src/lib/net.c +++ b/src/lib/net.c @@ -952,10 +952,48 @@ const char *net_ip2addr(const struct ip_addr *ip) #endif } +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 */ #ifdef HAVE_IPV6 diff --git a/src/lib/test-net.c b/src/lib/test-net.c index 6c4d8e1679..62630b66a5 100644 --- a/src/lib/test-net.c +++ b/src/lib/test-net.c @@ -71,12 +71,22 @@ static void test_net_ip2addr(void) ip.family == AF_INET && ntohl(ip.u.ip4.s_addr) == (0x7f000001)); #ifdef HAVE_IPV6 + 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);