From cc86efe070f62fbebce8a9be11f4979e4e4fa6fa Mon Sep 17 00:00:00 2001 From: Paruyr Gevorgyan Date: Fri, 17 Oct 2014 15:15:07 +0200 Subject: [PATCH] Fix several issues of Poco::IPAddress with supporting for IPv6 format. In current implementation "scope" part of IPv6 is not taken into consideration in several parts of code. --- Net/src/IPAddress.cpp | 74 ++++++++++++++++++--------------------- Net/src/IPAddressImpl.cpp | 34 ++++++++++++++---- 2 files changed, 63 insertions(+), 45 deletions(-) diff --git a/Net/src/IPAddress.cpp b/Net/src/IPAddress.cpp index 30e509002..211f35de8 100644 --- a/Net/src/IPAddress.cpp +++ b/Net/src/IPAddress.cpp @@ -53,7 +53,7 @@ IPAddress::IPAddress(const IPAddress& addr) if (addr.family() == IPv4) newIPv4(addr.addr()); else - newIPv6(addr.addr()); + newIPv6(addr.addr(), addr.scope()); } @@ -118,7 +118,7 @@ IPAddress::IPAddress(const std::string& addr, Family family) else if (family == IPv6) { IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); - newIPv6(addr6.addr()); + newIPv6(addr6.addr(), addr6.scope()); return; } #endif @@ -222,7 +222,7 @@ IPAddress& IPAddress::operator = (const IPAddress& addr) if (addr.family() == IPAddress::IPv4) newIPv4(addr.addr()); else - newIPv6(addr.addr()); + newIPv6(addr.addr(), addr.scope()); } return *this; } @@ -341,7 +341,13 @@ bool IPAddress::operator == (const IPAddress& a) const poco_socklen_t l1 = length(); poco_socklen_t l2 = a.length(); if (l1 == l2) + { +#if defined(POCO_HAVE_IPv6) + if ( scope() != a.scope() ) + return false; +#endif return std::memcmp(addr(), a.addr(), l1) == 0; + } else return false; } @@ -349,12 +355,7 @@ bool IPAddress::operator == (const IPAddress& a) const bool IPAddress::operator != (const IPAddress& a) const { - poco_socklen_t l1 = length(); - poco_socklen_t l2 = a.length(); - if (l1 == l2) - return std::memcmp(addr(), a.addr(), l1) != 0; - else - return true; + return !(*this == a); } @@ -363,7 +364,13 @@ bool IPAddress::operator < (const IPAddress& a) const poco_socklen_t l1 = length(); poco_socklen_t l2 = a.length(); if (l1 == l2) + { +#if defined(POCO_HAVE_IPv6) + if ( scope() != a.scope() ) + return scope() < a.scope(); +#endif return std::memcmp(addr(), a.addr(), l1) < 0; + } else return l1 < l2; } @@ -371,34 +378,19 @@ bool IPAddress::operator < (const IPAddress& a) const bool IPAddress::operator <= (const IPAddress& a) const { - poco_socklen_t l1 = length(); - poco_socklen_t l2 = a.length(); - if (l1 == l2) - return std::memcmp(addr(), a.addr(), l1) <= 0; - else - return l1 < l2; + return !(a < *this); } bool IPAddress::operator > (const IPAddress& a) const { - poco_socklen_t l1 = length(); - poco_socklen_t l2 = a.length(); - if (l1 == l2) - return std::memcmp(addr(), a.addr(), l1) > 0; - else - return l1 > l2; + return a < *this; } bool IPAddress::operator >= (const IPAddress& a) const { - poco_socklen_t l1 = length(); - poco_socklen_t l2 = a.length(); - if (l1 == l2) - return std::memcmp(addr(), a.addr(), l1) >= 0; - else - return l1 > l2; + return !(*this < a); } @@ -415,9 +407,10 @@ IPAddress IPAddress::operator & (const IPAddress& other) const #if defined(POCO_HAVE_IPv6) else if (family() == IPv6) { - IPv6AddressImpl t(pImpl()->addr()); - IPv6AddressImpl o(other.pImpl()->addr()); - return IPAddress((t & o).addr(), sizeof(struct in6_addr)); + const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); + const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); + const IPv6AddressImpl r = t & o; + return IPAddress(r.addr(), r.scope(), sizeof(struct in6_addr)); } #endif else @@ -441,9 +434,10 @@ IPAddress IPAddress::operator | (const IPAddress& other) const #if defined(POCO_HAVE_IPv6) else if (family() == IPv6) { - IPv6AddressImpl t(pImpl()->addr()); - IPv6AddressImpl o(other.pImpl()->addr()); - return IPAddress((t | o).addr(), sizeof(struct in6_addr)); + const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); + const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); + const IPv6AddressImpl r = t | o; + return IPAddress(r.addr(), r.scope(), sizeof(struct in6_addr)); } #endif else @@ -467,9 +461,10 @@ IPAddress IPAddress::operator ^ (const IPAddress& other) const #if defined(POCO_HAVE_IPv6) else if (family() == IPv6) { - IPv6AddressImpl t(pImpl()->addr()); - IPv6AddressImpl o(other.pImpl()->addr()); - return IPAddress((t ^ o).addr(), sizeof(struct in6_addr)); + const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); + const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); + const IPv6AddressImpl r = t ^ o; + return IPAddress(r.addr(), r.scope(), sizeof(struct in6_addr)); } #endif else @@ -490,8 +485,9 @@ IPAddress IPAddress::operator ~ () const #if defined(POCO_HAVE_IPv6) else if (family() == IPv6) { - IPv6AddressImpl self(this->pImpl()->addr()); - return IPAddress((~self).addr(), sizeof(struct in6_addr)); + const IPv6AddressImpl self(pImpl()->addr(), pImpl()->scope()); + const IPv6AddressImpl r = ~self; + return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); } #endif else @@ -541,7 +537,7 @@ IPAddress IPAddress::parse(const std::string& addr) IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr)); if (impl6 != IPv6AddressImpl()) { - result.newIPv6(impl6.addr()); + result.newIPv6(impl6.addr(), impl6.scope()); return true; } #endif diff --git a/Net/src/IPAddressImpl.cpp b/Net/src/IPAddressImpl.cpp index b237711b5..20b250436 100644 --- a/Net/src/IPAddressImpl.cpp +++ b/Net/src/IPAddressImpl.cpp @@ -104,6 +104,9 @@ IPv4AddressImpl::IPv4AddressImpl(const IPv4AddressImpl& addr) IPv4AddressImpl& IPv4AddressImpl::operator = (const IPv4AddressImpl& addr) { + if (this == &addr) + return *this; + std::memcpy(&_addr, &addr._addr, sizeof(_addr)); return *this; } @@ -371,6 +374,9 @@ IPv6AddressImpl::IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(addr._scop IPv6AddressImpl& IPv6AddressImpl::operator = (const IPv6AddressImpl& addr) { + if (this == &addr) + return *this; + _scope = addr._scope; std::memcpy(&_addr, &addr._addr, sizeof(_addr)); return *this; @@ -671,13 +677,18 @@ void IPv6AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet IPAddressImpl* IPv6AddressImpl::clone() const { - return new IPv6AddressImpl(&_addr, _scope); + return new IPv6AddressImpl(*this); } IPv6AddressImpl IPv6AddressImpl::operator & (const IPv6AddressImpl& addr) const { - IPv6AddressImpl result(&_addr); + if (_scope != addr._scope) { + throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match " + "with the source one."); + } + + IPv6AddressImpl result(*this); #ifdef POCO_OS_FAMILY_WINDOWS result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0]; result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1]; @@ -699,7 +710,12 @@ IPv6AddressImpl IPv6AddressImpl::operator & (const IPv6AddressImpl& addr) const IPv6AddressImpl IPv6AddressImpl::operator | (const IPv6AddressImpl& addr) const { - IPv6AddressImpl result(&_addr); + if (_scope != addr._scope) { + throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match " + "with the source one."); + } + + IPv6AddressImpl result(*this); #ifdef POCO_OS_FAMILY_WINDOWS result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0]; result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1]; @@ -721,7 +737,13 @@ IPv6AddressImpl IPv6AddressImpl::operator | (const IPv6AddressImpl& addr) const IPv6AddressImpl IPv6AddressImpl::operator ^ (const IPv6AddressImpl& addr) const { - IPv6AddressImpl result(&_addr); + if (_scope != addr._scope) { + throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match " + "with the source one."); + } + + IPv6AddressImpl result(*this); + #ifdef POCO_OS_FAMILY_WINDOWS result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0]; result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1]; @@ -743,7 +765,7 @@ IPv6AddressImpl IPv6AddressImpl::operator ^ (const IPv6AddressImpl& addr) const IPv6AddressImpl IPv6AddressImpl::operator ~ () const { - IPv6AddressImpl result(&_addr); + IPv6AddressImpl result(*this); #ifdef POCO_OS_FAMILY_WINDOWS result._addr.s6_addr16[0] ^= 0xffff; result._addr.s6_addr16[1] ^= 0xffff; @@ -765,7 +787,7 @@ IPv6AddressImpl IPv6AddressImpl::operator ~ () const bool IPv6AddressImpl::operator == (const IPv6AddressImpl& addr) const { - return 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); + return _scope == addr._scope && 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); }