From: Christos Tsantilas Date: Sun, 7 Aug 2011 10:26:09 +0000 (+0300) Subject: author: Christos Tsantilas , Amos Jeffries , Amos Jeffries Bug fix: The Ip::Address::IsAnyAddr method return false for IPv4 anyaddr. - The ip::Address::IsAnyAddr() returns true only for ipv6 anyaddr (0000:0000:0000:0000:0000:0000:0000:0000) and returns false when we have an ipv4 anyaddr (0000:0000:0000:0000:0000:FFFF:0000:0000) - The ip::Address::IsIPv4 method returns false in the case of IPv4 anyaddr. The above can cause bugs, eg: - inside Ip::Address::SetIPv4(). When it is called for an IPv6 anyaddr the ip address will not considred as anyaddr any morei (it IsAnyAddr will return false). - inside cache_cf.cc file inside dump_generic_http_port function: if (s->s.IsAnyAddr() && !s->s.IsIPv6()) storeAppendPrintf(e, " ipv4"); The if condition in the above statement can never be true. But the s->s can be an ipv4 anyaddr. - other places where the code will not work as expected in the case we are listening to an ipv4 anyaddr ip address. This patch: - moving the IsIPv4/6 to base purely on the v4-mapped or not - making both protocols ANYADDR match the same test - making both protocols NOADDR match the same test - Fixing the IsIPv4/6 documentation to match the implementation --- diff --git a/src/ip/Address.cc b/src/ip/Address.cc index 420b968928..6c521873d8 100644 --- a/src/ip/Address.cc +++ b/src/ip/Address.cc @@ -173,19 +173,19 @@ Ip::Address::IsSockAddr() const bool Ip::Address::IsIPv4() const { - return IsAnyAddr() || IsNoAddr() || IN6_IS_ADDR_V4MAPPED( &m_SocketAddr.sin6_addr ); + return IN6_IS_ADDR_V4MAPPED( &m_SocketAddr.sin6_addr ); } bool Ip::Address::IsIPv6() const { - return IsAnyAddr() || IsNoAddr() || !IN6_IS_ADDR_V4MAPPED( &m_SocketAddr.sin6_addr ); + return !IsIPv4(); } bool Ip::Address::IsAnyAddr() const { - return IN6_IS_ADDR_UNSPECIFIED( &m_SocketAddr.sin6_addr ); + return IN6_IS_ADDR_UNSPECIFIED( &m_SocketAddr.sin6_addr ) || IN6_ARE_ADDR_EQUAL( &m_SocketAddr.sin6_addr, &v4_anyaddr); ; } /// NOTE: Does NOT clear the Port stored. Ony the Address and Type. @@ -237,6 +237,11 @@ Ip::Address::SetIPv4() return true; } + if ( IsNoAddr() ) { + m_SocketAddr.sin6_addr = v4_noaddr; + return true; + } + if ( IsIPv4()) return true; @@ -279,7 +284,8 @@ bool Ip::Address::IsNoAddr() const { // IFF the address == 0xff..ff (all ones) - return IN6_ARE_ADDR_EQUAL( &m_SocketAddr.sin6_addr, &v6_noaddr ); + return IN6_ARE_ADDR_EQUAL( &m_SocketAddr.sin6_addr, &v6_noaddr ) + || IN6_ARE_ADDR_EQUAL( &m_SocketAddr.sin6_addr, &v4_noaddr ); } void diff --git a/src/ip/Address.h b/src/ip/Address.h index 15920ca901..8792d9c589 100644 --- a/src/ip/Address.h +++ b/src/ip/Address.h @@ -123,16 +123,14 @@ public: /* methods */ /** Test whether content can be used as an IPv4 address - \retval true if content was received as an IPv4 address \retval true if content was received as an IPv4-Mapped address \retval false if content was received as a non-mapped IPv6 native address. */ bool IsIPv4() const; /** Test whether content can be used as an IPv6 address. - \retval true if --enable-ipv6 has been compiled. - \retval false if --disable-ipv6 has been compiled. - \retval false if --with-ipv6-split-stack has been compiled AND content is IPv4-mapped. + \retval true if content is a non IPv4-mapped address. + \retval false if content is IPv4-mapped. */ bool IsIPv6() const;