# HG changeset patch # User Timo Sirainen # Date 1509752621 -7200 # Node ID da6cf4b7caf4e4879572000ee39c3d99593fc5d8 # Parent 7d5634889da8ec0df193878a0326098008347959 lib: net_addr2ip() - Optimize for parsing IPv4 addresses diff -r 7d5634889da8 -r da6cf4b7caf4 src/lib/net.c --- a/src/lib/net.c Sat Nov 04 01:42:37 2017 +0200 +++ b/src/lib/net.c Sat Nov 04 01:43:41 2017 +0200 @@ -952,10 +952,48 @@ #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 -r 7d5634889da8 -r da6cf4b7caf4 src/lib/test-net.c --- a/src/lib/test-net.c Sat Nov 04 01:42:37 2017 +0200 +++ b/src/lib/test-net.c Sat Nov 04 01:43:41 2017 +0200 @@ -71,12 +71,22 @@ 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);