From c54091c8ed26b98ceabcb3f82237b847e328769a Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 2 Oct 2001 06:06:15 +0000 Subject: [PATCH] IPv6 addresses containing mapped IPv4 addresses generate the same hash value as the equivalent IPv4 address. This is now true regardless of the value of address_only. Document. --- lib/isc/include/isc/sockaddr.h | 5 ++- lib/isc/sockaddr.c | 65 ++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/lib/isc/include/isc/sockaddr.h b/lib/isc/include/isc/sockaddr.h index 69b90a833d..8d0b2d4966 100644 --- a/lib/isc/include/isc/sockaddr.h +++ b/lib/isc/include/isc/sockaddr.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sockaddr.h,v 1.35 2001/01/09 21:57:33 bwelling Exp $ */ +/* $Id: sockaddr.h,v 1.36 2001/10/02 06:06:13 marka Exp $ */ #ifndef ISC_SOCKADDR_H #define ISC_SOCKADDR_H 1 @@ -64,6 +64,9 @@ isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only); /* * Return a hash value for the socket address 'sockaddr'. If 'address_only' * is ISC_TRUE, the hash value will not depend on the port. + * + * IPv6 addresses containing mapped IPv4 addresses generate the same hash + * value as the equivalent IPv4 address. */ void diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c index 6f23cd0e1c..14c7655f9d 100644 --- a/lib/isc/sockaddr.c +++ b/lib/isc/sockaddr.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sockaddr.c,v 1.49 2001/09/17 06:58:18 marka Exp $ */ +/* $Id: sockaddr.c,v 1.50 2001/10/02 06:06:15 marka Exp $ */ #include @@ -175,47 +175,45 @@ isc_sockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size) { unsigned int isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { - unsigned int length; - const unsigned char *s; + unsigned int length = 0; + const unsigned char *s = NULL; unsigned int h = 0; unsigned int g; + unsigned int p = 0; const struct in6_addr *in6; REQUIRE(sockaddr != NULL); - if (address_only) { - switch (sockaddr->type.sa.sa_family) { - case AF_INET: - return (ntohl(sockaddr->type.sin.sin_addr.s_addr)); - case AF_INET6: - in6 = &sockaddr->type.sin6.sin6_addr; - if (IN6_IS_ADDR_V4MAPPED(in6)) { - g = (in6->s6_addr[12] << 24) | - (in6->s6_addr[13] << 16) | - (in6->s6_addr[14] << 8) | - in6->s6_addr[15]; - return (g); - } + switch (sockaddr->type.sa.sa_family) { + case AF_INET: + h = ntohl(sockaddr->type.sin.sin_addr.s_addr); + p = ntohs(sockaddr->type.sin.sin_port); + break; + case AF_INET6: + in6 = &sockaddr->type.sin6.sin6_addr; + if (IN6_IS_ADDR_V4MAPPED(in6)) { + h = (in6->s6_addr[12] << 24) | + (in6->s6_addr[13] << 16) | + (in6->s6_addr[14] << 8) | + in6->s6_addr[15]; + } else { s = (const unsigned char *)&sockaddr-> - type.sin6.sin6_addr; + type.sin6.sin6_addr; length = sizeof sockaddr->type.sin6.sin6_addr; - break; - default: - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_SOCKADDR, - ISC_MSG_UNKNOWNFAMILY, - "unknown " - "address family: %d"), - (int)sockaddr->type.sa.sa_family); - s = (const unsigned char *)&sockaddr->type; - length = sockaddr->length; } - } else { + p = ntohs(sockaddr->type.sin6.sin6_port); + break; + default: + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_SOCKADDR, + ISC_MSG_UNKNOWNFAMILY, + "unknown address family: %d"), + (int)sockaddr->type.sa.sa_family); s = (const unsigned char *)&sockaddr->type; length = sockaddr->length; + p = 0; } - while (length > 0) { h = ( h << 4 ) + *s; if ((g = ( h & 0xf0000000 )) != 0) { @@ -225,6 +223,13 @@ isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { s++; length--; } + if (!address_only) { + h = h ^ (p << 4); + if ((g = ( h & 0xf0000000 )) != 0) { + h = h ^ (g >> 24); + h = h ^ g; + } + } return (h); }