| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774 |
- //
- // IPAddress.cpp
- //
- // $Id: //poco/Main/Net/src/IPAddress.cpp#16 $
- //
- // Library: Net
- // Package: NetCore
- // Module: IPAddress
- //
- // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
- // and Contributors.
- //
- // Permission is hereby granted, free of charge, to any person or organization
- // obtaining a copy of the software and accompanying documentation covered by
- // this license (the "Software") to use, reproduce, display, distribute,
- // execute, and transmit the Software, and to prepare derivative works of the
- // Software, and to permit third-parties to whom the Software is furnished to
- // do so, all subject to the following:
- //
- // The copyright notices in the Software and this entire statement, including
- // the above license grant, this restriction and the following disclaimer,
- // must be included in all copies of the Software, in whole or in part, and
- // all derivative works of the Software, unless such copies or derivative
- // works are solely in the form of machine-executable object code generated by
- // a source language processor.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
- // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
- // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
- // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- // DEALINGS IN THE SOFTWARE.
- //
- #include "Poco/Net/IPAddress.h"
- #include "Poco/Net/NetException.h"
- #include "Poco/RefCountedObject.h"
- #include "Poco/NumberFormatter.h"
- #include "Poco/Types.h"
- #include <algorithm>
- #include <cstring>
- using Poco::RefCountedObject;
- using Poco::NumberFormatter;
- using Poco::UInt8;
- using Poco::UInt16;
- using Poco::UInt32;
- namespace Poco {
- namespace Net {
- //
- // IPAddressImpl
- //
- class IPAddressImpl: public RefCountedObject
- {
- public:
- virtual std::string toString() const = 0;
- virtual poco_socklen_t length() const = 0;
- virtual const void* addr() const = 0;
- virtual IPAddress::Family family() const = 0;
- virtual int af() const = 0;
- virtual bool isWildcard() const = 0;
- virtual bool isBroadcast() const = 0;
- virtual bool isLoopback() const = 0;
- virtual bool isMulticast() const = 0;
- virtual bool isLinkLocal() const = 0;
- virtual bool isSiteLocal() const = 0;
- virtual bool isIPv4Mapped() const = 0;
- virtual bool isIPv4Compatible() const = 0;
- virtual bool isWellKnownMC() const = 0;
- virtual bool isNodeLocalMC() const = 0;
- virtual bool isLinkLocalMC() const = 0;
- virtual bool isSiteLocalMC() const = 0;
- virtual bool isOrgLocalMC() const = 0;
- virtual bool isGlobalMC() const = 0;
- virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0;
- protected:
- IPAddressImpl()
- {
- }
-
- virtual ~IPAddressImpl()
- {
- }
- private:
- IPAddressImpl(const IPAddressImpl&);
- IPAddressImpl& operator = (const IPAddressImpl&);
- };
- class IPv4AddressImpl: public IPAddressImpl
- {
- public:
- IPv4AddressImpl()
- {
- std::memset(&_addr, 0, sizeof(_addr));
- }
-
- IPv4AddressImpl(const void* addr)
- {
- std::memcpy(&_addr, addr, sizeof(_addr));
- }
-
- std::string toString() const
- {
- const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
- std::string result;
- result.reserve(16);
- result.append(NumberFormatter::format(bytes[0]));
- result.append(".");
- result.append(NumberFormatter::format(bytes[1]));
- result.append(".");
- result.append(NumberFormatter::format(bytes[2]));
- result.append(".");
- result.append(NumberFormatter::format(bytes[3]));
- return result;
- }
- poco_socklen_t length() const
- {
- return sizeof(_addr);
- }
-
- const void* addr() const
- {
- return &_addr;
- }
-
- IPAddress::Family family() const
- {
- return IPAddress::IPv4;
- }
-
- int af() const
- {
- return AF_INET;
- }
-
- bool isWildcard() const
- {
- return _addr.s_addr == INADDR_ANY;
- }
-
- bool isBroadcast() const
- {
- return _addr.s_addr == INADDR_NONE;
- }
-
- bool isLoopback() const
- {
- return ntohl(_addr.s_addr) == 0x7F000001; // 127.0.0.1
- }
-
- bool isMulticast() const
- {
- return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24
- }
-
- bool isLinkLocal() const
- {
- return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16
- }
-
- bool isSiteLocal() const
- {
- UInt32 addr = ntohl(_addr.s_addr);
- return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24
- (addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16
- addr >= 0xAC100000 && addr <= 0xAC1FFFFF; // 172.16.0.0 to 172.31.255.255
- }
-
- bool isIPv4Compatible() const
- {
- return true;
- }
- bool isIPv4Mapped() const
- {
- return true;
- }
- bool isWellKnownMC() const
- {
- return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8
- }
-
- bool isNodeLocalMC() const
- {
- return false;
- }
-
- bool isLinkLocalMC() const
- {
- return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24
- }
-
- bool isSiteLocalMC() const
- {
- return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16
- }
-
- bool isOrgLocalMC() const
- {
- return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16
- }
-
- bool isGlobalMC() const
- {
- UInt32 addr = ntohl(_addr.s_addr);
- return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255
- }
- static IPv4AddressImpl* parse(const std::string& addr)
- {
- if (addr.empty()) return 0;
- #if defined(_WIN32)
- struct in_addr ia;
- ia.s_addr = inet_addr(addr.c_str());
- if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
- return 0;
- else
- return new IPv4AddressImpl(&ia);
- #else
- struct in_addr ia;
- if (inet_aton(addr.c_str(), &ia))
- return new IPv4AddressImpl(&ia);
- else
- return 0;
- #endif
- }
-
- void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
- {
- poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET);
-
- _addr.s_addr &= static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr;
- _addr.s_addr |= static_cast<const IPv4AddressImpl*>(pSet)->_addr.s_addr & ~static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr;
- }
-
- private:
- struct in_addr _addr;
- };
- #if defined(POCO_HAVE_IPv6)
- class IPv6AddressImpl: public IPAddressImpl
- {
- public:
- IPv6AddressImpl()
- {
- std::memset(&_addr, 0, sizeof(_addr));
- }
- IPv6AddressImpl(const void* addr)
- {
- std::memcpy(&_addr, addr, sizeof(_addr));
- }
- std::string toString() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- if (isIPv4Compatible() || isIPv4Mapped())
- {
- std::string result;
- result.reserve(24);
- if (words[5] == 0)
- result.append("::");
- else
- result.append("::FFFF:");
- const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
- result.append(NumberFormatter::format(bytes[12]));
- result.append(".");
- result.append(NumberFormatter::format(bytes[13]));
- result.append(".");
- result.append(NumberFormatter::format(bytes[14]));
- result.append(".");
- result.append(NumberFormatter::format(bytes[15]));
- return result;
- }
- else
- {
- std::string result;
- result.reserve(46);
- bool zeroSequence = false;
- int i = 0;
- while (i < 8)
- {
- if (!zeroSequence && words[i] == 0)
- {
- int zi = i;
- while (zi < 8 && words[zi] == 0) ++zi;
- if (zi > i + 1)
- {
- i = zi;
- result.append(":");
- zeroSequence = true;
- }
- }
- if (i > 0) result.append(":");
- if (i < 8) result.append(NumberFormatter::formatHex(ntohs(words[i++])));
- }
- return result;
- }
- }
-
- poco_socklen_t length() const
- {
- return sizeof(_addr);
- }
- const void* addr() const
- {
- return &_addr;
- }
- IPAddress::Family family() const
- {
- return IPAddress::IPv6;
- }
- int af() const
- {
- return AF_INET6;
- }
- bool isWildcard() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
- words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0;
- }
-
- bool isBroadcast() const
- {
- return false;
- }
-
- bool isLoopback() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
- words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 1;
- }
-
- bool isMulticast() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return (words[0] & 0xFFE0) == 0xFF00;
- }
-
- bool isLinkLocal() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return (words[0] & 0xFFE0) == 0xFE80;
- }
-
- bool isSiteLocal() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return (words[0] & 0xFFE0) == 0xFEC0;
- }
-
- bool isIPv4Compatible() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0;
- }
- bool isIPv4Mapped() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0xFFFF;
- }
- bool isWellKnownMC() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return (words[0] & 0xFFF0) == 0xFF00;
- }
-
- bool isNodeLocalMC() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return (words[0] & 0xFFEF) == 0xFF01;
- }
-
- bool isLinkLocalMC() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return (words[0] & 0xFFEF) == 0xFF02;
- }
-
- bool isSiteLocalMC() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return (words[0] & 0xFFEF) == 0xFF05;
- }
-
- bool isOrgLocalMC() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return (words[0] & 0xFFEF) == 0xFF08;
- }
-
- bool isGlobalMC() const
- {
- const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
- return (words[0] & 0xFFEF) == 0xFF0F;
- }
- static IPv6AddressImpl* parse(const std::string& addr)
- {
- if (addr.empty()) return 0;
- #if defined(_WIN32)
- struct addrinfo* pAI;
- struct addrinfo hints;
- std::memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_NUMERICHOST;
- int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI);
- if (rc == 0)
- {
- IPv6AddressImpl* pResult = new IPv6AddressImpl(&reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_addr);
- freeaddrinfo(pAI);
- return pResult;
- }
- else return 0;
- #else
- struct in6_addr ia;
- if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1)
- return new IPv6AddressImpl(&ia);
- else
- return 0;
- #endif
- }
-
- void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
- {
- throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses");
- }
- private:
- struct in6_addr _addr;
- };
- #endif // POCO_HAVE_IPv6
- //
- // IPAddress
- //
- IPAddress::IPAddress(): _pImpl(new IPv4AddressImpl)
- {
- }
- IPAddress::IPAddress(const IPAddress& addr): _pImpl(addr._pImpl)
- {
- _pImpl->duplicate();
- }
- IPAddress::IPAddress(Family family): _pImpl(0)
- {
- if (family == IPv4)
- _pImpl = new IPv4AddressImpl();
- #if defined(POCO_HAVE_IPv6)
- else if (family == IPv6)
- _pImpl = new IPv6AddressImpl();
- #endif
- else Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
- }
- IPAddress::IPAddress(const std::string& addr)
- {
- _pImpl = IPv4AddressImpl::parse(addr);
- #if defined(POCO_HAVE_IPv6)
- if (!_pImpl)
- _pImpl = IPv6AddressImpl::parse(addr);
- #endif
- if (!_pImpl) throw InvalidAddressException(addr);
- }
- IPAddress::IPAddress(const std::string& addr, Family family): _pImpl(0)
- {
- if (family == IPv4)
- _pImpl = IPv4AddressImpl::parse(addr);
- #if defined(POCO_HAVE_IPv6)
- else if (family == IPv6)
- _pImpl = IPv6AddressImpl::parse(addr);
- #endif
- else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
- }
- IPAddress::IPAddress(const void* addr, poco_socklen_t length)
- {
- if (length == sizeof(struct in_addr))
- _pImpl = new IPv4AddressImpl(addr);
- #if defined(POCO_HAVE_IPv6)
- else if (length == sizeof(struct in6_addr))
- _pImpl = new IPv6AddressImpl(addr);
- #endif
- else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()");
- }
- IPAddress::~IPAddress()
- {
- _pImpl->release();
- }
- IPAddress& IPAddress::operator = (const IPAddress& addr)
- {
- if (&addr != this)
- {
- _pImpl->release();
- _pImpl = addr._pImpl;
- _pImpl->duplicate();
- }
- return *this;
- }
- void IPAddress::swap(IPAddress& address)
- {
- std::swap(_pImpl, address._pImpl);
- }
-
- IPAddress::Family IPAddress::family() const
- {
- return _pImpl->family();
- }
-
- std::string IPAddress::toString() const
- {
- return _pImpl->toString();
- }
- bool IPAddress::isWildcard() const
- {
- return _pImpl->isWildcard();
- }
-
- bool IPAddress::isBroadcast() const
- {
- return _pImpl->isBroadcast();
- }
- bool IPAddress::isLoopback() const
- {
- return _pImpl->isLoopback();
- }
- bool IPAddress::isMulticast() const
- {
- return _pImpl->isMulticast();
- }
-
- bool IPAddress::isUnicast() const
- {
- return !isWildcard() && !isBroadcast() && !isMulticast();
- }
-
- bool IPAddress::isLinkLocal() const
- {
- return _pImpl->isLinkLocal();
- }
- bool IPAddress::isSiteLocal() const
- {
- return _pImpl->isSiteLocal();
- }
- bool IPAddress::isIPv4Compatible() const
- {
- return _pImpl->isIPv4Compatible();
- }
- bool IPAddress::isIPv4Mapped() const
- {
- return _pImpl->isIPv4Mapped();
- }
- bool IPAddress::isWellKnownMC() const
- {
- return _pImpl->isWellKnownMC();
- }
- bool IPAddress::isNodeLocalMC() const
- {
- return _pImpl->isNodeLocalMC();
- }
- bool IPAddress::isLinkLocalMC() const
- {
- return _pImpl->isLinkLocalMC();
- }
- bool IPAddress::isSiteLocalMC() const
- {
- return _pImpl->isSiteLocalMC();
- }
- bool IPAddress::isOrgLocalMC() const
- {
- return _pImpl->isOrgLocalMC();
- }
- bool IPAddress::isGlobalMC() const
- {
- return _pImpl->isGlobalMC();
- }
- 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 false;
- }
- 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;
- }
- 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;
- }
- 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;
- }
- 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;
- }
- 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;
- }
- poco_socklen_t IPAddress::length() const
- {
- return _pImpl->length();
- }
-
- const void* IPAddress::addr() const
- {
- return _pImpl->addr();
- }
- int IPAddress::af() const
- {
- return _pImpl->af();
- }
- void IPAddress::init(IPAddressImpl* pImpl)
- {
- _pImpl->release();
- _pImpl = pImpl;
- }
- IPAddress IPAddress::parse(const std::string& addr)
- {
- return IPAddress(addr);
- }
- bool IPAddress::tryParse(const std::string& addr, IPAddress& result)
- {
- IPAddressImpl* pImpl = IPv4AddressImpl::parse(addr);
- #if defined(POCO_HAVE_IPv6)
- if (!pImpl) pImpl = IPv6AddressImpl::parse(addr);
- #endif
- if (pImpl)
- {
- result.init(pImpl);
- return true;
- }
- else return false;
- }
- void IPAddress::mask(const IPAddress& mask)
- {
- IPAddress null;
- _pImpl->mask(mask._pImpl, null._pImpl);
- }
- void IPAddress::mask(const IPAddress& mask, const IPAddress& set)
- {
- _pImpl->mask(mask._pImpl, set._pImpl);
- }
- } } // namespace Poco::Net
|