]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: net_addr2ip() - Optimize for parsing IPv4 addresses
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 3 Nov 2017 23:43:41 +0000 (01:43 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 7 Nov 2017 19:22:49 +0000 (21:22 +0200)
src/lib/net.c
src/lib/test-net.c

index 2facbd97d71f636a25be42a49b0e29a25990b139..66031ffa08de798c46633d921d991fe166c9c195 100644 (file)
@@ -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
index 6c4d8e167956eac00ba10c89cb688db6ee4fec32..62630b66a50c26e4d5b3b8bea88013888a983bbe 100644 (file)
@@ -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);