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.

This commit is contained in:
Paruyr Gevorgyan 2014-10-17 15:15:07 +02:00
parent 49e856aa89
commit cc86efe070
2 changed files with 63 additions and 45 deletions

View File

@ -53,7 +53,7 @@ IPAddress::IPAddress(const IPAddress& addr)
if (addr.family() == IPv4) if (addr.family() == IPv4)
newIPv4(addr.addr()); newIPv4(addr.addr());
else 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) else if (family == IPv6)
{ {
IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr));
newIPv6(addr6.addr()); newIPv6(addr6.addr(), addr6.scope());
return; return;
} }
#endif #endif
@ -222,7 +222,7 @@ IPAddress& IPAddress::operator = (const IPAddress& addr)
if (addr.family() == IPAddress::IPv4) if (addr.family() == IPAddress::IPv4)
newIPv4(addr.addr()); newIPv4(addr.addr());
else else
newIPv6(addr.addr()); newIPv6(addr.addr(), addr.scope());
} }
return *this; return *this;
} }
@ -341,7 +341,13 @@ bool IPAddress::operator == (const IPAddress& a) const
poco_socklen_t l1 = length(); poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length(); poco_socklen_t l2 = a.length();
if (l1 == l2) if (l1 == l2)
{
#if defined(POCO_HAVE_IPv6)
if ( scope() != a.scope() )
return false;
#endif
return std::memcmp(addr(), a.addr(), l1) == 0; return std::memcmp(addr(), a.addr(), l1) == 0;
}
else else
return false; return false;
} }
@ -349,12 +355,7 @@ bool IPAddress::operator == (const IPAddress& a) const
bool IPAddress::operator != (const IPAddress& a) const bool IPAddress::operator != (const IPAddress& a) const
{ {
poco_socklen_t l1 = length(); return !(*this == a);
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) != 0;
else
return true;
} }
@ -363,7 +364,13 @@ bool IPAddress::operator < (const IPAddress& a) const
poco_socklen_t l1 = length(); poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length(); poco_socklen_t l2 = a.length();
if (l1 == l2) 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; return std::memcmp(addr(), a.addr(), l1) < 0;
}
else else
return l1 < l2; return l1 < l2;
} }
@ -371,34 +378,19 @@ bool IPAddress::operator < (const IPAddress& a) const
bool IPAddress::operator <= (const IPAddress& a) const bool IPAddress::operator <= (const IPAddress& a) const
{ {
poco_socklen_t l1 = length(); return !(a < *this);
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) <= 0;
else
return l1 < l2;
} }
bool IPAddress::operator > (const IPAddress& a) const bool IPAddress::operator > (const IPAddress& a) const
{ {
poco_socklen_t l1 = length(); return a < *this;
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) > 0;
else
return l1 > l2;
} }
bool IPAddress::operator >= (const IPAddress& a) const bool IPAddress::operator >= (const IPAddress& a) const
{ {
poco_socklen_t l1 = length(); return !(*this < a);
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) >= 0;
else
return l1 > l2;
} }
@ -415,9 +407,10 @@ IPAddress IPAddress::operator & (const IPAddress& other) const
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
else if (family() == IPv6) else if (family() == IPv6)
{ {
IPv6AddressImpl t(pImpl()->addr()); const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope());
IPv6AddressImpl o(other.pImpl()->addr()); const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope());
return IPAddress((t & o).addr(), sizeof(struct in6_addr)); const IPv6AddressImpl r = t & o;
return IPAddress(r.addr(), r.scope(), sizeof(struct in6_addr));
} }
#endif #endif
else else
@ -441,9 +434,10 @@ IPAddress IPAddress::operator | (const IPAddress& other) const
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
else if (family() == IPv6) else if (family() == IPv6)
{ {
IPv6AddressImpl t(pImpl()->addr()); const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope());
IPv6AddressImpl o(other.pImpl()->addr()); const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope());
return IPAddress((t | o).addr(), sizeof(struct in6_addr)); const IPv6AddressImpl r = t | o;
return IPAddress(r.addr(), r.scope(), sizeof(struct in6_addr));
} }
#endif #endif
else else
@ -467,9 +461,10 @@ IPAddress IPAddress::operator ^ (const IPAddress& other) const
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
else if (family() == IPv6) else if (family() == IPv6)
{ {
IPv6AddressImpl t(pImpl()->addr()); const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope());
IPv6AddressImpl o(other.pImpl()->addr()); const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope());
return IPAddress((t ^ o).addr(), sizeof(struct in6_addr)); const IPv6AddressImpl r = t ^ o;
return IPAddress(r.addr(), r.scope(), sizeof(struct in6_addr));
} }
#endif #endif
else else
@ -490,8 +485,9 @@ IPAddress IPAddress::operator ~ () const
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
else if (family() == IPv6) else if (family() == IPv6)
{ {
IPv6AddressImpl self(this->pImpl()->addr()); const IPv6AddressImpl self(pImpl()->addr(), pImpl()->scope());
return IPAddress((~self).addr(), sizeof(struct in6_addr)); const IPv6AddressImpl r = ~self;
return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope());
} }
#endif #endif
else else
@ -541,7 +537,7 @@ IPAddress IPAddress::parse(const std::string& addr)
IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr)); IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr));
if (impl6 != IPv6AddressImpl()) if (impl6 != IPv6AddressImpl())
{ {
result.newIPv6(impl6.addr()); result.newIPv6(impl6.addr(), impl6.scope());
return true; return true;
} }
#endif #endif

View File

@ -104,6 +104,9 @@ IPv4AddressImpl::IPv4AddressImpl(const IPv4AddressImpl& addr)
IPv4AddressImpl& IPv4AddressImpl::operator = (const IPv4AddressImpl& addr) IPv4AddressImpl& IPv4AddressImpl::operator = (const IPv4AddressImpl& addr)
{ {
if (this == &addr)
return *this;
std::memcpy(&_addr, &addr._addr, sizeof(_addr)); std::memcpy(&_addr, &addr._addr, sizeof(_addr));
return *this; return *this;
} }
@ -371,6 +374,9 @@ IPv6AddressImpl::IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(addr._scop
IPv6AddressImpl& IPv6AddressImpl::operator = (const IPv6AddressImpl& addr) IPv6AddressImpl& IPv6AddressImpl::operator = (const IPv6AddressImpl& addr)
{ {
if (this == &addr)
return *this;
_scope = addr._scope; _scope = addr._scope;
std::memcpy(&_addr, &addr._addr, sizeof(_addr)); std::memcpy(&_addr, &addr._addr, sizeof(_addr));
return *this; return *this;
@ -671,13 +677,18 @@ void IPv6AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet
IPAddressImpl* IPv6AddressImpl::clone() const IPAddressImpl* IPv6AddressImpl::clone() const
{ {
return new IPv6AddressImpl(&_addr, _scope); return new IPv6AddressImpl(*this);
} }
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 #ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0]; result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0];
result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1]; 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 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 #ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0]; result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0];
result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1]; 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 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 #ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0]; result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0];
result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1]; 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 IPv6AddressImpl::operator ~ () const
{ {
IPv6AddressImpl result(&_addr); IPv6AddressImpl result(*this);
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr16[0] ^= 0xffff; result._addr.s6_addr16[0] ^= 0xffff;
result._addr.s6_addr16[1] ^= 0xffff; result._addr.s6_addr16[1] ^= 0xffff;
@ -765,7 +787,7 @@ IPv6AddressImpl IPv6AddressImpl::operator ~ () const
bool IPv6AddressImpl::operator == (const IPv6AddressImpl& addr) 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));
} }