]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Use incremental hashing in the isc_sockaddr_hash() function
authorOndřej Surý <ondrej@isc.org>
Tue, 12 Sep 2023 14:33:19 +0000 (16:33 +0200)
committerOndřej Surý <ondrej@isc.org>
Tue, 19 Sep 2023 17:51:51 +0000 (19:51 +0200)
Instead of copying address back and forth when hashing addr+port, we can
use incremental hashing.  Additionally, switch from 64-bit
isc_hash_function to 32-bit isc_hash32() as the resulting value is
32-bit.

lib/isc/include/isc/sockaddr.h
lib/isc/sockaddr.c

index 9523865c5ae20b15fce67c5051a1e59f0761451b..b9dda2b0c23b644657faf1f9a5625da8fdfb13f7 100644 (file)
@@ -85,7 +85,7 @@ isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
  * If 'b''s scope is zero then 'a''s scope will be ignored.
  */
 
-unsigned int
+uint32_t
 isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, bool address_only);
 /*%<
  * Return a hash value for the socket address 'sockaddr'.  If 'address_only'
index 765e73e566091b7daf0c3c0f6e3ec4e6293d4587..020cc58ae998488409a412b8680e492277aa8467 100644 (file)
@@ -187,51 +187,49 @@ isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
        }
 }
 
-unsigned int
+uint32_t
 isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, bool address_only) {
-       unsigned int length = 0;
-       const unsigned char *s = NULL;
-       unsigned int h = 0;
+       REQUIRE(sockaddr != NULL);
+
+       size_t len = 0;
+       const uint8_t *s = NULL;
        unsigned int p = 0;
        const struct in6_addr *in6;
+       isc_hash32_t hash;
 
-       REQUIRE(sockaddr != NULL);
+       isc_hash32_init(&hash);
 
        switch (sockaddr->type.sa.sa_family) {
        case AF_INET:
-               s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
-               p = ntohs(sockaddr->type.sin.sin_port);
-               length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
+               s = (const uint8_t *)&sockaddr->type.sin.sin_addr;
+               len = sizeof(sockaddr->type.sin.sin_addr.s_addr);
+               if (!address_only) {
+                       p = ntohs(sockaddr->type.sin.sin_port);
+               }
                break;
        case AF_INET6:
                in6 = &sockaddr->type.sin6.sin6_addr;
-               s = (const unsigned char *)in6;
+               s = (const uint8_t *)in6;
                if (IN6_IS_ADDR_V4MAPPED(in6)) {
                        s += 12;
-                       length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
+                       len = sizeof(sockaddr->type.sin.sin_addr.s_addr);
                } else {
-                       length = sizeof(sockaddr->type.sin6.sin6_addr);
+                       len = sizeof(sockaddr->type.sin6.sin6_addr);
+               }
+               if (!address_only) {
+                       p = ntohs(sockaddr->type.sin6.sin6_port);
                }
-               p = ntohs(sockaddr->type.sin6.sin6_port);
                break;
        default:
-               UNEXPECTED_ERROR("unknown address family: %d",
-                                (int)sockaddr->type.sa.sa_family);
-               s = (const unsigned char *)&sockaddr->type;
-               length = sockaddr->length;
-               p = 0;
+               UNREACHABLE();
        }
 
-       uint8_t buf[sizeof(struct sockaddr_storage) + sizeof(p)];
-       memmove(buf, s, length);
+       isc_hash32_hash(&hash, s, len, true);
        if (!address_only) {
-               memmove(buf + length, &p, sizeof(p));
-               h = isc_hash_function(buf, length + sizeof(p), true);
-       } else {
-               h = isc_hash_function(buf, length, true);
+               isc_hash32_hash(&hash, &p, sizeof(p), true);
        }
 
-       return (h);
+       return (isc_hash32_finalize(&hash));
 }
 
 void