aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/poco/Net/src/NetworkInterface.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/poco/Net/src/NetworkInterface.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/poco/Net/src/NetworkInterface.cpp')
-rw-r--r--contrib/libs/poco/Net/src/NetworkInterface.cpp1827
1 files changed, 1827 insertions, 0 deletions
diff --git a/contrib/libs/poco/Net/src/NetworkInterface.cpp b/contrib/libs/poco/Net/src/NetworkInterface.cpp
new file mode 100644
index 0000000000..e3b1c24f7b
--- /dev/null
+++ b/contrib/libs/poco/Net/src/NetworkInterface.cpp
@@ -0,0 +1,1827 @@
+//
+// NetworkInterface.cpp
+//
+// Library: Net
+// Package: NetCore
+// Module: NetworkInterface
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Net/NetworkInterface.h"
+
+
+#ifdef POCO_NET_HAS_INTERFACE
+
+
+#include "Poco/Net/DatagramSocket.h"
+#include "Poco/Net/NetException.h"
+#include "Poco/NumberFormatter.h"
+#include "Poco/NumberParser.h"
+#include "Poco/StringTokenizer.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/Format.h"
+#if defined(POCO_OS_FAMILY_WINDOWS)
+ #if defined(POCO_WIN32_UTF8)
+ #include "Poco/UnicodeConverter.h"
+ #endif
+ #include "Poco/Error.h"
+ #include <wincrypt.h>
+ #include <iphlpapi.h>
+ #include <ipifcons.h>
+#endif
+#include <cstring>
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+
+
+using Poco::NumberFormatter;
+using Poco::FastMutex;
+using Poco::format;
+
+
+std::ostream& operator << (std::ostream& os, const Poco::Net::NetworkInterface::MACAddress& mac)
+{
+ std::ios state(0);
+ state.copyfmt(os);
+ for (unsigned i = 0; i < mac.size(); ++i)
+ {
+ if (i > 0) os << Poco::Net::NetworkInterface::MAC_SEPARATOR;
+ os << std::hex << std::setw(2) << std::setfill('0') << (unsigned) mac[i];
+ }
+ os.copyfmt(state);
+ return os;
+}
+
+
+namespace Poco {
+namespace Net {
+
+
+//
+// NetworkInterfaceImpl
+//
+
+class NetworkInterfaceImpl: public Poco::RefCountedObject
+{
+public:
+ typedef NetworkInterface::AddressTuple AddressTuple;
+ typedef NetworkInterface::AddressList AddressList;
+ typedef NetworkInterface::Type Type;
+
+ NetworkInterfaceImpl(unsigned index);
+ NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, NetworkInterface::MACAddress* pMACAddress = 0);
+ NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index = 0, NetworkInterface::MACAddress* pMACAddress = 0);
+ NetworkInterfaceImpl(const std::string& name,
+ const std::string& displayName,
+ const std::string& adapterName,
+ const IPAddress& address,
+ const IPAddress& subnetMask,
+ const IPAddress& broadcastAddress,
+ unsigned index,
+ NetworkInterface::MACAddress* pMACAddress = 0);
+
+ unsigned index() const;
+ const std::string& name() const;
+ const std::string& displayName() const;
+ const std::string& adapterName() const;
+ const IPAddress& firstAddress(IPAddress::Family family) const;
+ void addAddress(const AddressTuple& address);
+ const IPAddress& address(unsigned index) const;
+ const NetworkInterface::AddressList& addressList() const;
+ bool hasAddress(const IPAddress& address) const;
+ const IPAddress& subnetMask(unsigned index) const;
+ const IPAddress& broadcastAddress(unsigned index) const;
+ const IPAddress& destAddress(unsigned index) const;
+ const NetworkInterface::MACAddress& macAddress() const;
+ bool supportsIPv4() const;
+ bool supportsIPv6() const;
+
+ void setName(const std::string& name);
+ void setDisplayName(const std::string& name);
+ void setAdapterName(const std::string& name);
+ void addAddress(const IPAddress& addr);
+ void setMACAddress(const NetworkInterface::MACAddress& addr);
+ void setMACAddress(const void *addr, std::size_t len);
+
+ unsigned mtu() const;
+ unsigned ifindex() const;
+ Type type() const;
+
+ bool broadcast() const;
+ bool loopback() const;
+ bool multicast() const;
+ bool pointToPoint() const;
+ bool running() const;
+ bool up() const;
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+ void setFlags(DWORD flags, DWORD iftype);
+ void setRunning(bool running);
+#else
+ void setFlags(short flags);
+#endif
+
+ void setUp(bool up);
+ void setMTU(unsigned mtu);
+ void setType(Type type);
+ void setIndex(unsigned index);
+ void setPhyParams();
+
+protected:
+ ~NetworkInterfaceImpl();
+
+private:
+ std::string _name;
+ std::string _displayName;
+ std::string _adapterName;
+ AddressList _addressList;
+ unsigned _index;
+ bool _broadcast;
+ bool _loopback;
+ bool _multicast;
+ bool _pointToPoint;
+ bool _up;
+ bool _running;
+ unsigned _mtu;
+ Type _type;
+
+ NetworkInterface::MACAddress _macAddress;
+
+ friend class NetworkInterface;
+};
+
+
+NetworkInterfaceImpl::NetworkInterfaceImpl(unsigned index):
+ _index(index),
+ _broadcast(false),
+ _loopback(false),
+ _multicast(false),
+ _pointToPoint(false),
+ _up(false),
+ _running(false),
+ _mtu(0),
+ _type(NetworkInterface::NI_TYPE_OTHER)
+{
+}
+
+
+NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, NetworkInterface::MACAddress* pMACAddress):
+ _name(name),
+ _displayName(displayName),
+ _adapterName(adapterName),
+ _index(index),
+ _broadcast(false),
+ _loopback(false),
+ _multicast(false),
+ _pointToPoint(false),
+ _up(false),
+ _running(false),
+ _mtu(0),
+ _type(NetworkInterface::NI_TYPE_OTHER)
+{
+ _addressList.push_back(AddressTuple(address, IPAddress(), IPAddress()));
+ setPhyParams();
+ if (pMACAddress) setMACAddress(*pMACAddress);
+}
+
+
+NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index, NetworkInterface::MACAddress* pMACAddress):
+ _name(name),
+ _displayName(displayName),
+ _adapterName(adapterName),
+ _index(index),
+ _broadcast(false),
+ _loopback(false),
+ _multicast(false),
+ _pointToPoint(false),
+ _up(false),
+ _running(false),
+ _mtu(0),
+ _type(NetworkInterface::NI_TYPE_OTHER)
+{
+ setPhyParams();
+ if (pMACAddress) setMACAddress(*pMACAddress);
+}
+
+
+NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name,
+ const std::string& displayName,
+ const std::string& adapterName,
+ const IPAddress& address,
+ const IPAddress& subnetMask,
+ const IPAddress& broadcastAddress,
+ unsigned index,
+ NetworkInterface::MACAddress* pMACAddress):
+ _name(name),
+ _displayName(displayName),
+ _adapterName(adapterName),
+ _index(index),
+ _broadcast(false),
+ _loopback(false),
+ _multicast(false),
+ _pointToPoint(false),
+ _up(false),
+ _running(false),
+ _mtu(0),
+ _type(NetworkInterface::NI_TYPE_OTHER)
+{
+ _addressList.push_back(AddressTuple(address, subnetMask, broadcastAddress));
+ setPhyParams();
+ if (pMACAddress) setMACAddress(*pMACAddress);
+}
+
+
+void NetworkInterfaceImpl::setPhyParams()
+{
+#if !defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_VXWORKS)
+ struct ifreq ifr;
+ std::strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ);
+ DatagramSocket ds(SocketAddress::IPv4);
+
+ ds.impl()->ioctl(SIOCGIFFLAGS, &ifr);
+ setFlags(ifr.ifr_flags);
+
+ ds.impl()->ioctl(SIOCGIFMTU, &ifr);
+ setMTU(ifr.ifr_mtu);
+#endif
+}
+
+
+NetworkInterfaceImpl::~NetworkInterfaceImpl()
+{
+}
+
+
+bool NetworkInterfaceImpl::supportsIPv4() const
+{
+ AddressList::const_iterator it = _addressList.begin();
+ AddressList::const_iterator end = _addressList.end();
+ for (; it != end; ++it)
+ {
+ if (IPAddress::IPv4 == it->get<NetworkInterface::IP_ADDRESS>().family())
+ return true;
+ }
+
+ return false;
+}
+
+
+bool NetworkInterfaceImpl::supportsIPv6() const
+{
+#ifdef POCO_HAVE_IPv6
+ AddressList::const_iterator it = _addressList.begin();
+ AddressList::const_iterator end = _addressList.end();
+ for (; it != end; ++it)
+ {
+ if (IPAddress::IPv6 == it->get<NetworkInterface::IP_ADDRESS>().family())
+ return true;
+ }
+#endif
+ return false;
+}
+
+
+inline unsigned NetworkInterfaceImpl::index() const
+{
+ return _index;
+}
+
+
+inline const std::string& NetworkInterfaceImpl::name() const
+{
+ return _name;
+}
+
+
+inline const std::string& NetworkInterfaceImpl::displayName() const
+{
+ return _displayName;
+}
+
+
+inline const std::string& NetworkInterfaceImpl::adapterName() const
+{
+ return _adapterName;
+}
+
+
+const IPAddress& NetworkInterfaceImpl::firstAddress(IPAddress::Family family) const
+{
+ AddressList::const_iterator it = _addressList.begin();
+ AddressList::const_iterator end = _addressList.end();
+ for (;it != end; ++it)
+ {
+ const IPAddress& addr = it->get<NetworkInterface::IP_ADDRESS>();
+ if (addr.family() == family) return addr;
+ }
+
+ throw NotFoundException(format("%s family address not found.", (family == IPAddress::IPv4) ? std::string("IPv4") : std::string("IPv6")));
+}
+
+
+inline void NetworkInterfaceImpl::addAddress(const AddressTuple& address)
+{
+ _addressList.push_back(address);
+}
+
+
+bool NetworkInterfaceImpl::hasAddress(const IPAddress& address) const
+{
+ NetworkInterface::ConstAddressIterator it = _addressList.begin();
+ NetworkInterface::ConstAddressIterator end = _addressList.end();
+ for (; it != end; ++it)
+ {
+ if (it->get<NetworkInterface::IP_ADDRESS>() == address)
+ return true;
+ }
+ return false;
+}
+
+
+inline const IPAddress& NetworkInterfaceImpl::address(unsigned index) const
+{
+ if (index < _addressList.size()) return _addressList[index].get<NetworkInterface::IP_ADDRESS>();
+ else throw NotFoundException(Poco::format("No address with index %u.", index));
+}
+
+
+inline const NetworkInterface::AddressList& NetworkInterfaceImpl::addressList() const
+{
+ return _addressList;
+}
+
+
+const IPAddress& NetworkInterfaceImpl::subnetMask(unsigned index) const
+{
+ if (index < _addressList.size())
+ return _addressList[index].get<NetworkInterface::SUBNET_MASK>();
+
+ throw NotFoundException(Poco::format("No subnet mask with index %u.", index));
+}
+
+
+const IPAddress& NetworkInterfaceImpl::broadcastAddress(unsigned index) const
+{
+ if (index < _addressList.size())
+ return _addressList[index].get<NetworkInterface::BROADCAST_ADDRESS>();
+
+ throw NotFoundException(Poco::format("No subnet mask with index %u.", index));
+}
+
+
+const IPAddress& NetworkInterfaceImpl::destAddress(unsigned index) const
+{
+ if (!pointToPoint())
+ throw InvalidAccessException("Only PPP addresses have destination address.");
+ else if (index < _addressList.size())
+ return _addressList[index].get<NetworkInterface::BROADCAST_ADDRESS>();
+
+ throw NotFoundException(Poco::format("No address with index %u.", index));
+}
+
+
+const NetworkInterface::MACAddress& NetworkInterfaceImpl::macAddress() const
+{
+ return _macAddress;
+}
+
+
+inline unsigned NetworkInterfaceImpl::mtu() const
+{
+ return _mtu;
+}
+
+
+inline NetworkInterface::Type NetworkInterfaceImpl::type() const
+{
+ return _type;
+}
+
+
+inline bool NetworkInterfaceImpl::broadcast() const
+{
+ return _broadcast;
+}
+
+
+inline bool NetworkInterfaceImpl::loopback() const
+{
+ return _loopback;
+}
+
+
+inline bool NetworkInterfaceImpl::multicast() const
+{
+ return _multicast;
+}
+
+
+inline bool NetworkInterfaceImpl::pointToPoint() const
+{
+ return _pointToPoint;
+}
+
+
+inline bool NetworkInterfaceImpl::running() const
+{
+ return _running;
+}
+
+
+inline bool NetworkInterfaceImpl::up() const
+{
+ return _up;
+}
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+
+
+void NetworkInterfaceImpl::setFlags(DWORD flags, DWORD iftype)
+{
+ _running = _up = false;
+ switch (iftype) {
+ case IF_TYPE_ETHERNET_CSMACD:
+ case IF_TYPE_ISO88025_TOKENRING:
+ case IF_TYPE_IEEE80211:
+ _multicast = _broadcast = true;
+ break;
+ case IF_TYPE_SOFTWARE_LOOPBACK:
+ _loopback = true;
+ break;
+ case IF_TYPE_PPP:
+ case IF_TYPE_ATM:
+ case IF_TYPE_TUNNEL:
+ case IF_TYPE_IEEE1394:
+ _pointToPoint = true;
+ break;
+ }
+ if (!(flags & IP_ADAPTER_NO_MULTICAST))
+ _multicast = true;
+}
+
+
+void NetworkInterfaceImpl::setRunning(bool running)
+{
+ _running = running;
+}
+
+
+#else
+
+
+void NetworkInterfaceImpl::setFlags(short flags)
+{
+#ifdef POCO_OS_FAMILY_UNIX
+ _broadcast = ((flags & IFF_BROADCAST) != 0);
+ _loopback = ((flags & IFF_LOOPBACK) != 0);
+ _multicast = ((flags & IFF_MULTICAST) != 0);
+ _pointToPoint = ((flags & IFF_POINTOPOINT) != 0);
+ _running = ((flags & IFF_RUNNING) != 0);
+ _up = ((flags & IFF_UP) != 0);
+#endif
+}
+
+
+#endif
+
+
+inline void NetworkInterfaceImpl::setUp(bool up)
+{
+ _up = up;
+}
+
+
+inline void NetworkInterfaceImpl::setMTU(unsigned mtu)
+{
+ _mtu = mtu;
+}
+
+
+inline void NetworkInterfaceImpl::setType(Type type)
+{
+ _type = type;
+}
+
+
+inline void NetworkInterfaceImpl::setIndex(unsigned index)
+{
+ _index = index;
+}
+
+
+inline void NetworkInterfaceImpl::setName(const std::string& name)
+{
+ _name = name;
+}
+
+
+inline void NetworkInterfaceImpl::setDisplayName(const std::string& name)
+{
+ _displayName = name;
+}
+
+
+inline void NetworkInterfaceImpl::setAdapterName(const std::string& name)
+{
+ _adapterName = name;
+}
+
+
+inline void NetworkInterfaceImpl::addAddress(const IPAddress& addr)
+{
+ _addressList.push_back(addr);
+}
+
+
+inline void NetworkInterfaceImpl::setMACAddress(const NetworkInterface::MACAddress& addr)
+{
+ _macAddress = addr;
+}
+
+
+inline void NetworkInterfaceImpl::setMACAddress(const void *addr, std::size_t len)
+{
+ _macAddress.clear();
+ _macAddress.insert(_macAddress.end(), static_cast<const unsigned char*>(addr), static_cast<const unsigned char*>(addr) + len);
+}
+
+
+//
+// NetworkInterface
+//
+
+
+FastMutex NetworkInterface::_mutex;
+
+
+NetworkInterface::NetworkInterface(unsigned index):
+ _pImpl(new NetworkInterfaceImpl(index))
+{
+}
+
+
+NetworkInterface::NetworkInterface(const NetworkInterface& interfc):
+ _pImpl(interfc._pImpl)
+{
+ _pImpl->duplicate();
+}
+
+
+NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, MACAddress* pMACAddress):
+ _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, address, index, pMACAddress))
+{
+}
+
+
+NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index, MACAddress* pMACAddress):
+ _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, index, pMACAddress))
+{
+}
+
+
+NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, unsigned index, MACAddress* pMACAddress):
+ _pImpl(new NetworkInterfaceImpl(name, name, name, address, index, pMACAddress))
+{
+}
+
+
+NetworkInterface::NetworkInterface(const std::string& name,
+ const std::string& displayName,
+ const std::string& adapterName,
+ const IPAddress& address,
+ const IPAddress& subnetMask,
+ const IPAddress& broadcastAddress,
+ unsigned index,
+ MACAddress* pMACAddress):
+ _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, address, subnetMask, broadcastAddress, index, pMACAddress))
+{
+}
+
+
+NetworkInterface::NetworkInterface(const std::string& name,
+ const IPAddress& address,
+ const IPAddress& subnetMask,
+ const IPAddress& broadcastAddress,
+ unsigned index,
+ MACAddress* pMACAddress):
+ _pImpl(new NetworkInterfaceImpl(name, name, name, address, subnetMask, broadcastAddress, index, pMACAddress))
+{
+}
+
+
+NetworkInterface::~NetworkInterface()
+{
+ _pImpl->release();
+}
+
+
+NetworkInterface& NetworkInterface::operator = (const NetworkInterface& interfc)
+{
+ NetworkInterface tmp(interfc);
+ swap(tmp);
+ return *this;
+}
+
+
+void NetworkInterface::swap(NetworkInterface& other)
+{
+ using std::swap;
+ swap(_pImpl, other._pImpl);
+}
+
+
+unsigned NetworkInterface::index() const
+{
+ return _pImpl->index();
+}
+
+
+const std::string& NetworkInterface::name() const
+{
+ return _pImpl->name();
+}
+
+
+const std::string& NetworkInterface::displayName() const
+{
+ return _pImpl->displayName();
+}
+
+
+const std::string& NetworkInterface::adapterName() const
+{
+ return _pImpl->adapterName();
+}
+
+
+const IPAddress& NetworkInterface::firstAddress(IPAddress::Family family) const
+{
+ return _pImpl->firstAddress(family);
+}
+
+
+void NetworkInterface::firstAddress(IPAddress& addr, IPAddress::Family family) const
+{
+ try
+ {
+ addr = firstAddress(family);
+ }
+ catch (NotFoundException&)
+ {
+ addr = IPAddress(family);
+ }
+}
+
+
+void NetworkInterface::addAddress(const IPAddress& address)
+{
+ _pImpl->addAddress(AddressTuple(address, IPAddress(), IPAddress()));
+}
+
+
+void NetworkInterface::addAddress(const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress)
+{
+ _pImpl->addAddress(AddressTuple(address, subnetMask, broadcastAddress));
+}
+
+
+const IPAddress& NetworkInterface::address(unsigned index) const
+{
+ return _pImpl->address(index);
+}
+
+
+const NetworkInterface::AddressList& NetworkInterface::addressList() const
+{
+ return _pImpl->addressList();
+}
+
+
+const IPAddress& NetworkInterface::subnetMask(unsigned index) const
+{
+ return _pImpl->subnetMask(index);
+}
+
+
+const IPAddress& NetworkInterface::broadcastAddress(unsigned index) const
+{
+ return _pImpl->broadcastAddress(index);
+}
+
+
+const NetworkInterface::MACAddress& NetworkInterface::macAddress() const
+{
+ return _pImpl->macAddress();
+}
+
+
+const IPAddress& NetworkInterface::destAddress(unsigned index) const
+{
+ return _pImpl->destAddress(index);
+}
+
+
+unsigned NetworkInterface::mtu() const
+{
+ return _pImpl->mtu();
+}
+
+
+NetworkInterface::Type NetworkInterface::type() const
+{
+ return _pImpl->type();
+}
+
+
+bool NetworkInterface::supportsIP() const
+{
+ return _pImpl->supportsIPv4() || _pImpl->supportsIPv6();
+}
+
+
+bool NetworkInterface::supportsIPv4() const
+{
+ return _pImpl->supportsIPv4();
+}
+
+
+bool NetworkInterface::supportsIPv6() const
+{
+ return _pImpl->supportsIPv6();
+}
+
+
+bool NetworkInterface::supportsBroadcast() const
+{
+ return _pImpl->broadcast();
+}
+
+
+bool NetworkInterface::supportsMulticast() const
+{
+ return _pImpl->multicast();
+}
+
+
+bool NetworkInterface::isLoopback() const
+{
+ return _pImpl->loopback();
+}
+
+
+bool NetworkInterface::isPointToPoint() const
+{
+ return _pImpl->pointToPoint();
+}
+
+
+bool NetworkInterface::isRunning() const
+{
+ return _pImpl->running();
+}
+
+
+bool NetworkInterface::isUp() const
+{
+ return _pImpl->up();
+}
+
+
+NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6)
+{
+ if (requireIPv6)
+ return forName(name, IPv6_ONLY);
+ else
+ return forName(name, IPv4_OR_IPv6);
+}
+
+
+NetworkInterface NetworkInterface::forName(const std::string& name, IPVersion ipVersion)
+{
+ Map map = NetworkInterface::map(false, false);
+ Map::const_iterator it = map.begin();
+ Map::const_iterator end = map.end();
+
+ for (; it != end; ++it)
+ {
+ if (it->second.name() == name)
+ {
+ if (ipVersion == IPv4_ONLY && it->second.supportsIPv4())
+ return it->second;
+ else if (ipVersion == IPv6_ONLY && it->second.supportsIPv6())
+ return it->second;
+ else if (ipVersion == IPv4_OR_IPv6)
+ return it->second;
+ }
+ }
+ throw InterfaceNotFoundException(name);
+}
+
+
+NetworkInterface NetworkInterface::forAddress(const IPAddress& addr)
+{
+ Map map = NetworkInterface::map(true, false);
+ Map::const_iterator it = map.begin();
+ Map::const_iterator end = map.end();
+
+ for (; it != end; ++it)
+ {
+ const std::size_t count = it->second.addressList().size();
+ for (int i = 0; i < count; ++i)
+ {
+ if (it->second.address(i) == addr)
+ return it->second;
+ }
+ }
+ throw InterfaceNotFoundException(addr.toString());
+}
+
+
+NetworkInterface NetworkInterface::forIndex(unsigned i)
+{
+ if (i != NetworkInterface::NO_INDEX)
+ {
+ Map map = NetworkInterface::map(false, false);
+ Map::const_iterator it = map.find(i);
+ if (it != map.end())
+ return it->second;
+ else
+ throw InterfaceNotFoundException("#" + NumberFormatter::format(i));
+ }
+ throw InterfaceNotFoundException("#" + NumberFormatter::format(i));
+}
+
+
+NetworkInterface::List NetworkInterface::list(bool ipOnly, bool upOnly)
+{
+ List list;
+ Map m = map(ipOnly, upOnly);
+ NetworkInterface::Map::const_iterator it = m.begin();
+ NetworkInterface::Map::const_iterator end = m.end();
+ for (; it != end; ++it)
+ {
+ int index = it->second.index();
+ std::string name = it->second.name();
+ std::string displayName = it->second.displayName();
+ std::string adapterName = it->second.adapterName();
+ NetworkInterface::MACAddress mac = it->second.macAddress();
+
+ typedef NetworkInterface::AddressList AddrList;
+ const AddrList& ipList = it->second.addressList();
+ if (ipList.size() > 0)
+ {
+ AddrList::const_iterator ipIt = ipList.begin();
+ AddrList::const_iterator ipEnd = ipList.end();
+ for(; ipIt != ipEnd; ++ipIt)
+ {
+ IPAddress addr = ipIt->get<NetworkInterface::IP_ADDRESS>();
+ IPAddress mask = ipIt->get<NetworkInterface::SUBNET_MASK>();
+ NetworkInterface ni;
+ if(mask.isWildcard())
+ {
+ ni = NetworkInterface(name, displayName, adapterName, addr, index, &mac);
+ }
+ else
+ {
+ IPAddress broadcast = ipIt->get<NetworkInterface::BROADCAST_ADDRESS>();
+ ni = NetworkInterface(name, displayName, adapterName, addr, mask, broadcast, index, &mac);
+ }
+
+ ni._pImpl->_broadcast = it->second._pImpl->_broadcast;
+ ni._pImpl->_loopback = it->second._pImpl->_loopback;
+ ni._pImpl->_multicast = it->second._pImpl->_multicast;
+ ni._pImpl->_pointToPoint = it->second._pImpl->_pointToPoint;
+ ni._pImpl->_up = it->second._pImpl->_up;
+ ni._pImpl->_running = it->second._pImpl->_running;
+ ni._pImpl->_mtu = it->second._pImpl->_mtu;
+ ni._pImpl->_type = it->second._pImpl->_type;
+
+ list.push_back(ni);
+ }
+ }
+ else
+ {
+ list.push_back(NetworkInterface(name, displayName, adapterName, index, &mac));
+ }
+ }
+
+ return list;
+}
+
+
+} } // namespace Poco::Net
+
+
+//
+// platform-specific code below
+//
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+//
+// Windows
+//
+
+
+#include "Poco/Buffer.h"
+#include <iterator>
+
+
+namespace Poco {
+namespace Net {
+
+
+namespace {
+
+
+IPAddress getBroadcastAddress(PIP_ADAPTER_PREFIX pPrefix, const IPAddress& addr, ULONG* pprefix = 0)
+ /// This function relies on (1) subnet prefix being at the position
+ /// immediately preceding and (2) broadcast address being at the position
+ /// immediately succeeding the IPv4 unicast address.
+ ///
+ /// Since there is no explicit guarantee on order, to ensure correctness,
+ /// the above constraints are checked prior to returning the result.
+ /// Additionally, on pre-Vista versions on Windows, the main structure does
+ /// not contain prefix length; for those platforms, this function
+ /// returns prefix through pprefix argument.
+{
+ PIP_ADAPTER_PREFIX pPrev = 0;
+ for (int i = 0; pPrefix; pPrefix = pPrefix->Next, ++i)
+ {
+ ADDRESS_FAMILY family = pPrefix->Address.lpSockaddr->sa_family;
+ if ((family == AF_INET) && (addr == IPAddress(pPrefix->Address)))
+ break;
+ pPrev = pPrefix;
+ }
+
+ if (pPrefix && pPrefix->Next && pPrev)
+ {
+ IPAddress ipPrefix(pPrev->PrefixLength, IPAddress::IPv4);
+ IPAddress mask(pPrefix->Next->Address);
+ if ((ipPrefix & mask) == (ipPrefix & addr))
+ {
+ if (pprefix) *pprefix = pPrefix->PrefixLength;
+ return IPAddress(pPrefix->Next->Address);
+ }
+ }
+
+ return IPAddress(IPAddress::IPv4);
+}
+
+
+NetworkInterface::Type fromNative(DWORD type)
+{
+ switch (type)
+ {
+ case IF_TYPE_ETHERNET_CSMACD: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD;
+ case IF_TYPE_ISO88025_TOKENRING: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING;
+ case IF_TYPE_FRAMERELAY: return NetworkInterface::NI_TYPE_FRAMERELAY;
+ case IF_TYPE_PPP: return NetworkInterface::NI_TYPE_PPP;
+ case IF_TYPE_SOFTWARE_LOOPBACK: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK;
+ case IF_TYPE_ATM: return NetworkInterface::NI_TYPE_ATM;
+ case IF_TYPE_IEEE80211: return NetworkInterface::NI_TYPE_IEEE80211;
+ case IF_TYPE_TUNNEL: return NetworkInterface::NI_TYPE_TUNNEL;
+ case IF_TYPE_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394;
+ default: return NetworkInterface::NI_TYPE_OTHER;
+ }
+}
+
+
+IPAddress subnetMaskForInterface(const std::string& name, bool isLoopback)
+{
+ if (isLoopback)
+ {
+ return IPAddress::parse("255.0.0.0");
+ }
+ else
+ {
+#if !defined(_WIN32_WCE)
+ std::string subKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\");
+ subKey += name;
+ std::string netmask;
+ HKEY hKey;
+#if defined(POCO_WIN32_UTF8) && !defined(POCO_NO_WSTRING)
+ std::wstring usubKey;
+ Poco::UnicodeConverter::toUTF16(subKey, usubKey);
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, usubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
+ return IPAddress();
+ wchar_t unetmask[16];
+ DWORD size = sizeof(unetmask);
+ if (RegQueryValueExW(hKey, L"DhcpSubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
+ {
+ if (RegQueryValueExW(hKey, L"SubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return IPAddress();
+ }
+ }
+ Poco::UnicodeConverter::toUTF8(unetmask, netmask);
+#else
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
+ return IPAddress();
+ char unetmask[16];
+ DWORD size = sizeof(unetmask);
+ if (RegQueryValueExA(hKey, "DhcpSubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
+ {
+ if (RegQueryValueExA(hKey, "SubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return IPAddress();
+ }
+ }
+ netmask = unetmask;
+#endif
+ RegCloseKey(hKey);
+ return IPAddress::parse(netmask);
+#else
+ return IPAddress();
+#endif // !defined(_WIN32_WCE)
+ }
+}
+
+
+} /// namespace
+
+
+NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
+{
+ OSVERSIONINFO osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&osvi);
+
+ FastMutex::ScopedLock lock(_mutex);
+ Map result;
+ ULONG outBufLen = 16384;
+ Poco::Buffer<UCHAR> memory(outBufLen);
+ ULONG flags = (GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX);
+#ifdef GAA_FLAG_INCLUDE_ALL_INTERFACES
+ flags |= GAA_FLAG_INCLUDE_ALL_INTERFACES;
+#endif
+#if defined(POCO_HAVE_IPv6)
+ const unsigned family = AF_UNSPEC; //IPv4 and IPv6
+#else
+ const unsigned family = AF_INET; //IPv4 only
+#endif
+ DWORD dwRetVal = 0;
+ ULONG iterations = 0;
+ PIP_ADAPTER_ADDRESSES pAddress = 0;
+ do
+ {
+ pAddress = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(memory.begin()); // leave in the loop, begin may change after resize
+ poco_assert (memory.capacity() >= outBufLen);
+ if (ERROR_BUFFER_OVERFLOW == (dwRetVal = GetAdaptersAddresses(family, flags, 0, pAddress, &outBufLen)))
+ memory.resize(outBufLen, false); // adjust size and try again
+ else if (ERROR_NO_DATA == dwRetVal) // no network interfaces found
+ return result;
+ else if (NO_ERROR != dwRetVal) // error occurred
+ throw SystemException(format("An error occurred while trying to obtain list of network interfaces: [%s]", Error::getMessage(dwRetVal)));
+ else
+ break;
+ }
+ while ((ERROR_BUFFER_OVERFLOW == dwRetVal) && (++iterations <= 2));
+
+ poco_assert (NO_ERROR == dwRetVal);
+ for (; pAddress; pAddress = pAddress->Next)
+ {
+ IPAddress address;
+ IPAddress subnetMask;
+ IPAddress broadcastAddress;
+ unsigned ifIndex = 0;
+
+#if defined(POCO_HAVE_IPv6)
+ #if defined(_WIN32_WCE)
+ ifIndex = pAddress->Ipv6IfIndex;
+ #elif (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1
+ #if defined (IP_ADAPTER_IPV6_ENABLED) // Vista
+ if(osvi.dwMajorVersion>=6)//vista
+ {
+ if ((pAddress->Flags & IP_ADAPTER_IPV6_ENABLED) &&
+ (osvi.dwMajorVersion >= 5) &&
+ (osvi.dwMinorVersion >= 1) &&
+ (osvi.dwBuildNumber >=1))
+ {
+ ifIndex = pAddress->Ipv6IfIndex;
+ }
+ }
+ else
+ {
+ if ((osvi.dwMajorVersion >= 5) &&
+ (osvi.dwMinorVersion >= 1) &&
+ (osvi.dwBuildNumber >= 1))
+ {
+ ifIndex = pAddress->Ipv6IfIndex;
+ }
+ }
+ #else // !defined(IP_ADAPTER_IPV6_ENABLED)
+ if ((osvi.dwMajorVersion >= 5) &&
+ (osvi.dwMinorVersion >= 1) &&
+ (osvi.dwBuildNumber >= 1))
+ {
+ ifIndex = pAddress->Ipv6IfIndex;
+ }
+ #endif // defined(IP_ADAPTER_IPV6_ENABLED)
+ #endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100)
+#endif // POCO_HAVE_IPv6
+
+#if defined (IP_ADAPTER_IPV4_ENABLED)
+ if(osvi.dwMajorVersion>=6)
+ {//vista
+ if (pAddress->Flags & IP_ADAPTER_IPV4_ENABLED)
+ {
+ ifIndex = pAddress->IfIndex;
+ }
+ }
+ else
+ {
+ ifIndex = pAddress->IfIndex;
+ }
+#else // !IP_ADAPTER_IPV4_ENABLED
+ ifIndex = pAddress->IfIndex;
+#endif
+ if (ifIndex == 0) continue;
+
+ std::string name;
+ std::string displayName;
+ std::string adapterName(pAddress->AdapterName);
+#ifdef POCO_WIN32_UTF8
+ Poco::UnicodeConverter::toUTF8(pAddress->FriendlyName, name);
+ Poco::UnicodeConverter::toUTF8(pAddress->Description, displayName);
+#else
+ char nameBuffer[1024];
+ int rc = WideCharToMultiByte(CP_ACP, 0, pAddress->FriendlyName, -1, nameBuffer, sizeof(nameBuffer), NULL, NULL);
+ if (rc) name = nameBuffer;
+ char displayNameBuffer[1024];
+ rc = WideCharToMultiByte(CP_ACP, 0, pAddress->Description, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL);
+ if (rc) displayName = displayNameBuffer;
+#endif
+
+ bool isUp = (pAddress->OperStatus == IfOperStatusUp);
+ bool isIP = (0 != pAddress->FirstUnicastAddress);
+ if (((ipOnly && isIP) || !ipOnly) && ((upOnly && isUp) || !upOnly))
+ {
+ NetworkInterface ni(name, displayName, adapterName, ifIndex);
+ // Create interface even if it has an empty list of addresses; also, set
+ // physical attributes which are protocol independent (name, media type,
+ // MAC address, MTU, operational status, etc).
+ Map::iterator ifIt = result.find(ifIndex);
+ if (ifIt == result.end())
+ ifIt = result.insert(Map::value_type(ifIndex, ni)).first;
+
+ ifIt->second.impl().setFlags(pAddress->Flags, pAddress->IfType);
+ ifIt->second.impl().setMTU(pAddress->Mtu);
+ ifIt->second.impl().setUp(pAddress->OperStatus == IfOperStatusUp);
+#if (_WIN32_WINNT >= 0x0600) // Vista and newer only
+ if ((osvi.dwMajorVersion >= 6) &&
+ (osvi.dwMinorVersion >= 0) &&
+ (osvi.dwBuildNumber >= 0))
+ {
+ ifIt->second.impl().setRunning(pAddress->ReceiveLinkSpeed > 0 || pAddress->TransmitLinkSpeed > 0);
+ }
+#endif
+ ifIt->second.impl().setType(fromNative(pAddress->IfType));
+ if (pAddress->PhysicalAddressLength)
+ ifIt->second.impl().setMACAddress(pAddress->PhysicalAddress, pAddress->PhysicalAddressLength);
+
+ for (PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress;
+ pUniAddr;
+ pUniAddr = pUniAddr->Next)
+ {
+ address = IPAddress(pUniAddr->Address);
+ ADDRESS_FAMILY family2 = pUniAddr->Address.lpSockaddr->sa_family;
+ switch (family2)
+ {
+ case AF_INET:
+ {
+ // Windows lists broadcast address on localhost
+ bool hasBroadcast = (pAddress->IfType == IF_TYPE_ETHERNET_CSMACD) || (pAddress->IfType == IF_TYPE_SOFTWARE_LOOPBACK) || (pAddress->IfType == IF_TYPE_IEEE80211);
+ if (hasBroadcast)
+ {
+ // On Windows, a valid broadcast address will be all 1's (== address | ~subnetMask); additionaly, on pre-Vista versions of
+ // OS, master address structure does not contain member for prefix length; we go an extra mile here in order to make sure
+ // we reflect the actual values held by system and protect against misconfiguration (e.g. bad DHCP config entry)
+ ULONG prefixLength = 0;
+#if defined(_WIN32_WCE)
+ #if _WIN32_WCE >= 0x0800
+ prefixLength = pUniAddr->OnLinkPrefixLength;
+ broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address);
+ #else
+ broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength);
+ #endif
+ // if previous call did not do it, make last-ditch attempt for prefix and broadcast
+ if (prefixLength == 0 && pAddress->FirstPrefix)
+ prefixLength = pAddress->FirstPrefix->PrefixLength;
+ poco_assert (prefixLength <= 32);
+ if (broadcastAddress.isWildcard())
+ {
+ IPAddress mask(static_cast<unsigned>(prefixLength), IPAddress::IPv4);
+ IPAddress host(mask & address);
+ broadcastAddress = host | ~mask;
+ }
+#elif (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1
+ #if (_WIN32_WINNT >= 0x0600) // Vista and newer
+ if (osvi.dwMajorVersion >= 6)
+ {
+ prefixLength = pUniAddr->OnLinkPrefixLength;
+ broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address);
+ }
+ else
+ {
+ broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength);
+ }
+ #else
+ broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength);
+ #endif
+ poco_assert (prefixLength <= 32);
+ if (broadcastAddress.isWildcard())
+ {
+ IPAddress mask(static_cast<unsigned>(prefixLength), IPAddress::IPv4);
+ IPAddress host(mask & address);
+ broadcastAddress = host | ~mask;
+ }
+#endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100)
+ if (prefixLength)
+ {
+ subnetMask = IPAddress(static_cast<unsigned>(prefixLength), IPAddress::IPv4);
+ }
+ else // if all of the above fails, look up the subnet mask in the registry
+ {
+ address = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pUniAddr->Address.lpSockaddr)->sin_addr, sizeof(in_addr));
+ subnetMask = subnetMaskForInterface(name, address.isLoopback());
+ if (!address.isLoopback())
+ {
+ broadcastAddress = address;
+ broadcastAddress.mask(subnetMask, IPAddress::broadcast());
+ }
+ }
+ ifIt->second.addAddress(address, subnetMask, broadcastAddress);
+ }
+ else
+ {
+ ifIt->second.addAddress(address);
+ }
+ }
+ break;
+#if defined(POCO_HAVE_IPv6)
+ case AF_INET6:
+ ifIt->second.addAddress(address);
+ break;
+#endif
+ } // switch family
+ } // for addresses
+ } // if ipOnly/upOnly
+ } // for adapters
+ return result;
+}
+
+
+} } // namespace Poco::Net
+
+
+#elif defined(POCO_VXWORKS)
+//
+// VxWorks
+//
+
+#error TODO
+
+/*
+namespace Poco {
+namespace Net {
+
+
+NetworkInterface::NetworkInterfaceList NetworkInterface::list()
+{
+ FastMutex::ScopedLock lock(_mutex);
+ NetworkInterfaceList result;
+
+ int ifIndex = 1;
+ char ifName[32];
+ char ifAddr[INET_ADDR_LEN];
+
+ for (;;)
+ {
+ if (ifIndexToIfName(ifIndex, ifName) == OK)
+ {
+ std::string name(ifName);
+ IPAddress addr;
+ IPAddress mask;
+ IPAddress bcst;
+ if (ifAddrGet(ifName, ifAddr) == OK)
+ {
+ addr = IPAddress(std::string(ifAddr));
+ }
+ int ifMask;
+ if (ifMaskGet(ifName, &ifMask) == OK)
+ {
+ mask = IPAddress(&ifMask, sizeof(ifMask));
+ }
+ if (ifBroadcastGet(ifName, ifAddr) == OK)
+ {
+ bcst = IPAddress(std::string(ifAddr));
+ }
+ result.push_back(NetworkInterface(name, name, name, addr, mask, bcst));
+ ifIndex++;
+ }
+ else break;
+ }
+
+ return result;
+}
+
+
+} } // namespace Poco::Net
+*/
+
+#elif defined(POCO_OS_FAMILY_BSD) || (POCO_OS == POCO_OS_QNX) || (POCO_OS == POCO_OS_SOLARIS)
+//
+// BSD variants, QNX(?) and Solaris
+//
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#ifndef POCO_NO_NET_IFTYPES
+#include <net/if_types.h>
+#endif
+
+
+namespace Poco {
+namespace Net {
+
+
+namespace {
+
+
+NetworkInterface::Type fromNative(u_char nativeType)
+{
+ switch (nativeType)
+ {
+#ifndef POCO_NO_NET_IFTYPES
+ case IFT_ETHER: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD;
+ case IFT_ISO88025: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING;
+ case IFT_FRELAY: return NetworkInterface::NI_TYPE_FRAMERELAY;
+ case IFT_PPP: return NetworkInterface::NI_TYPE_PPP;
+ case IFT_LOOP: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK;
+ case IFT_ATM: return NetworkInterface::NI_TYPE_ATM;
+#if (POCO_OS != POCO_OS_SOLARIS)
+ case IFT_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394;
+#endif
+#endif
+ default: return NetworkInterface::NI_TYPE_OTHER;
+
+ }
+}
+
+
+void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl)
+{
+ struct sockaddr_dl* sdl = (struct sockaddr_dl*) iface->ifa_addr;
+ impl.setName(iface->ifa_name);
+ impl.setDisplayName(iface->ifa_name);
+ impl.setAdapterName(iface->ifa_name);
+ impl.setPhyParams();
+
+ impl.setMACAddress(LLADDR(sdl), sdl->sdl_alen);
+ impl.setType(fromNative(sdl->sdl_type));
+}
+
+
+} // namespace
+
+
+NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
+{
+ FastMutex::ScopedLock lock(_mutex);
+ Map result;
+ unsigned ifIndex = 0;
+ NetworkInterface intf;
+ Map::iterator ifIt;
+
+ struct ifaddrs* ifaces = 0;
+ struct ifaddrs* currIface = 0;
+
+ if (getifaddrs(&ifaces) < 0)
+ throw NetException("cannot get network adapter list");
+
+ try
+ {
+ for (currIface = ifaces; currIface != 0; currIface = currIface->ifa_next)
+ {
+ if (!currIface->ifa_addr) continue;
+
+ IPAddress address, subnetMask, broadcastAddress;
+ unsigned family = currIface->ifa_addr->sa_family;
+ switch (family)
+ {
+#if defined(POCO_OS_FAMILY_BSD)
+ case AF_LINK:
+ {
+ struct sockaddr_dl* sdl = (struct sockaddr_dl*) currIface->ifa_addr;
+ ifIndex = sdl->sdl_index;
+ intf = NetworkInterface(ifIndex);
+ setInterfaceParams(currIface, intf.impl());
+ if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
+ ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
+ break;
+ }
+#endif
+ case AF_INET:
+ ifIndex = if_nametoindex(currIface->ifa_name);
+ ifIt = result.find(ifIndex);
+ intf = NetworkInterface(ifIndex);
+ setInterfaceParams(currIface, intf.impl());
+ if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
+ ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
+
+ address = IPAddress(*(currIface->ifa_addr));
+
+ if (( currIface->ifa_flags & IFF_LOOPBACK ) == 0 && currIface->ifa_netmask)
+ subnetMask = IPAddress(*(currIface->ifa_netmask));
+
+ if (currIface->ifa_flags & IFF_BROADCAST && currIface->ifa_broadaddr)
+ broadcastAddress = IPAddress(*(currIface->ifa_broadaddr));
+ else if (currIface->ifa_flags & IFF_POINTOPOINT && currIface->ifa_dstaddr)
+ broadcastAddress = IPAddress(*(currIface->ifa_dstaddr));
+ else
+ broadcastAddress = IPAddress();
+ break;
+#if defined(POCO_HAVE_IPv6)
+ case AF_INET6:
+ ifIndex = if_nametoindex(currIface->ifa_name);
+ ifIt = result.find(ifIndex);
+ intf = NetworkInterface(ifIndex);
+ setInterfaceParams(currIface, intf.impl());
+ if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
+ ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
+
+ address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(currIface->ifa_addr)->sin6_addr,
+ sizeof(struct in6_addr), ifIndex);
+ subnetMask = IPAddress(*(currIface->ifa_netmask));
+ broadcastAddress = IPAddress();
+ break;
+#endif
+ default:
+ continue;
+ }
+
+ if (family == AF_INET
+#ifdef POCO_HAVE_IPv6
+ || family == AF_INET6
+#endif
+ )
+ {
+ if ((upOnly && intf.isUp()) || !upOnly)
+ {
+ if ((ifIt = result.find(ifIndex)) != result.end())
+ ifIt->second.addAddress(address, subnetMask, broadcastAddress);
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ }
+ if (ifaces) freeifaddrs(ifaces);
+
+ if (ipOnly)
+ {
+ Map::iterator it = result.begin();
+ Map::iterator end = result.end();
+ for (; it != end;)
+ {
+ if (!it->second.supportsIPv4() && !it->second.supportsIPv6())
+ result.erase(it++);
+ else ++it;
+ }
+ }
+
+ return result;
+}
+
+
+} } // namespace Poco::Net
+
+
+#elif POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_ANDROID
+//
+// Linux
+//
+
+
+#include <sys/types.h>
+#if POCO_OS != POCO_OS_ANDROID // Android doesn't have <ifaddrs.h>
+#include <ifaddrs.h>
+#endif
+#include <net/if.h>
+#ifndef POCO_NO_LINUX_IF_PACKET_H
+#include <linux/if_packet.h>
+#endif
+#include <net/if_arp.h>
+#include <iostream>
+
+namespace Poco {
+namespace Net {
+
+
+namespace {
+
+
+static NetworkInterface::Type fromNative(unsigned arphrd)
+{
+ switch (arphrd)
+ {
+ case ARPHRD_ETHER: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD;
+ case ARPHRD_IEEE802: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING;
+ case ARPHRD_DLCI: return NetworkInterface::NI_TYPE_FRAMERELAY;
+ case ARPHRD_PPP: return NetworkInterface::NI_TYPE_PPP;
+ case ARPHRD_LOOPBACK: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK;
+ case ARPHRD_ATM: return NetworkInterface::NI_TYPE_ATM;
+ case ARPHRD_IEEE80211: return NetworkInterface::NI_TYPE_IEEE80211;
+ case ARPHRD_TUNNEL:
+ case ARPHRD_TUNNEL6: return NetworkInterface::NI_TYPE_TUNNEL;
+ case ARPHRD_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394;
+ default: return NetworkInterface::NI_TYPE_OTHER;
+ }
+}
+
+#if POCO_OS != POCO_OS_ANDROID
+
+void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl)
+{
+ impl.setName(iface->ifa_name);
+ impl.setDisplayName(iface->ifa_name);
+ impl.setAdapterName(iface->ifa_name);
+ impl.setPhyParams();
+
+#ifndef POCO_NO_LINUX_IF_PACKET_H
+ struct sockaddr_ll* sdl = (struct sockaddr_ll*) iface->ifa_addr;
+ impl.setMACAddress(sdl->sll_addr, sdl->sll_halen);
+ impl.setType(fromNative(sdl->sll_hatype));
+#else
+ std::string ifPath("/sys/class/net/");
+ ifPath += iface->ifa_name;
+
+ std::string addrPath(ifPath);
+ addrPath += "/address";
+
+ std::ifstream addrStream(addrPath.c_str());
+ if (addrStream.good())
+ {
+ std::string addr;
+ std::getline(addrStream, addr);
+ Poco::StringTokenizer tok(addr, ":");
+ std::vector<unsigned char> mac;
+ for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it)
+ {
+ mac.push_back(static_cast<unsigned char>(Poco::NumberParser::parseHex(*it)));
+ }
+ impl.setMACAddress(&mac[0], mac.size());
+ addrStream.close();
+ }
+
+ std::string typePath(ifPath);
+ typePath += "/type";
+ std::ifstream typeStream(typePath.c_str());
+ if (typeStream.good())
+ {
+ int type;
+ typeStream >> type;
+ impl.setType(fromNative(type));
+ typeStream.close();
+ }
+#endif // POCO_NO_LINUX_IF_PACKET_H
+}
+
+#endif
+
+
+}
+
+
+NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
+{
+#if POCO_OS != POCO_OS_ANDROID
+ FastMutex::ScopedLock lock(_mutex);
+ Map result;
+ unsigned ifIndex = 0;
+ NetworkInterface intf;
+ Map::iterator ifIt;
+
+ struct ifaddrs* ifaces = 0;
+ struct ifaddrs* iface = 0;
+
+ if (getifaddrs(&ifaces) < 0)
+ throw NetException("cannot get network adapter list");
+
+ try
+ {
+ for (iface = ifaces; iface; iface = iface->ifa_next)
+ {
+ if (!iface->ifa_addr) continue;
+
+ IPAddress address, subnetMask, broadcastAddress;
+ unsigned family = iface->ifa_addr->sa_family;
+ switch (family)
+ {
+#ifndef POCO_NO_LINUX_IF_PACKET_H
+ case AF_PACKET:
+ {
+ struct sockaddr_ll* sll = (struct sockaddr_ll*)iface->ifa_addr;
+ ifIndex = sll->sll_ifindex;
+ intf = NetworkInterface(ifIndex);
+ setInterfaceParams(iface, intf.impl());
+
+ if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
+ ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
+
+ break;
+ }
+#endif // POCO_NO_LINUX_IF_PACKET_H
+ case AF_INET:
+ ifIndex = if_nametoindex(iface->ifa_name);
+ ifIt = result.find(ifIndex);
+ intf = NetworkInterface(ifIndex);
+ setInterfaceParams(iface, intf.impl());
+
+ if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
+ ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
+
+ address = IPAddress(*(iface->ifa_addr));
+ subnetMask = IPAddress(*(iface->ifa_netmask));
+
+ if (iface->ifa_flags & IFF_BROADCAST && iface->ifa_broadaddr)
+ broadcastAddress = IPAddress(*(iface->ifa_broadaddr));
+ else if (iface->ifa_flags & IFF_POINTOPOINT && iface->ifa_dstaddr)
+ broadcastAddress = IPAddress(*(iface->ifa_dstaddr));
+ else
+ broadcastAddress = IPAddress();
+
+ break;
+#if defined(POCO_HAVE_IPv6)
+ case AF_INET6:
+ ifIndex = if_nametoindex(iface->ifa_name);
+ ifIt = result.find(ifIndex);
+ intf = NetworkInterface(ifIndex);
+ setInterfaceParams(iface, intf.impl());
+
+ if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
+ result.insert(Map::value_type(ifIndex, intf));
+
+ address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(iface->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
+ subnetMask = IPAddress(*(iface->ifa_netmask));
+ broadcastAddress = IPAddress();
+
+ break;
+#endif
+ default:
+ continue;
+ }
+
+ if (family == AF_INET
+#ifdef POCO_HAVE_IPv6
+ || family == AF_INET6
+#endif
+ )
+ {
+ intf = NetworkInterface(std::string(iface->ifa_name), address, subnetMask, broadcastAddress, ifIndex);
+ if ((upOnly && intf.isUp()) || !upOnly)
+ {
+ if ((ifIt = result.find(ifIndex)) != result.end())
+ ifIt->second.addAddress(address, subnetMask, broadcastAddress);
+ }
+ }
+ } // for interface
+ }
+ catch (...)
+ {
+ if (ifaces) freeifaddrs(ifaces);
+ throw;
+ }
+
+ if (ifaces) freeifaddrs(ifaces);
+
+ if (ipOnly)
+ {
+ Map::iterator it = result.begin();
+ Map::iterator end = result.end();
+ for (; it != end;)
+ {
+ if (!it->second.supportsIPv4() && !it->second.supportsIPv6())
+ result.erase(it++);
+ else ++it;
+ }
+ }
+
+ return result;
+#else
+ throw Poco::NotImplementedException("Not implemented in Android");
+#endif
+}
+
+
+} } // namespace Poco::Net
+
+
+#else
+//
+// Non-BSD Unix variants
+//
+#error TODO
+/*
+NetworkInterface::NetworkInterfaceList NetworkInterface::list()
+{
+ FastMutex::ScopedLock lock(_mutex);
+ NetworkInterfaceList result;
+ DatagramSocket socket;
+ // the following code is loosely based
+ // on W. Richard Stevens, UNIX Network Programming, pp 434ff.
+ int lastlen = 0;
+ int len = 100*sizeof(struct ifreq);
+ char* buf = 0;
+ try
+ {
+ struct ifconf ifc;
+ for (;;)
+ {
+ buf = new char[len];
+ ifc.ifc_len = len;
+ ifc.ifc_buf = buf;
+ if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0)
+ {
+ if (errno != EINVAL || lastlen != 0)
+ throw NetException("cannot get network adapter list");
+ }
+ else
+ {
+ if (ifc.ifc_len == lastlen)
+ break;
+ lastlen = ifc.ifc_len;
+ }
+ len += 10*sizeof(struct ifreq);
+ delete [] buf;
+ }
+ for (const char* ptr = buf; ptr < buf + ifc.ifc_len;)
+ {
+ const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
+#if defined(POCO_HAVE_SALEN)
+ len = ifr->ifr_addr.sa_len;
+ if (sizeof(struct sockaddr) > len) len = sizeof(struct sockaddr);
+#else
+ len = sizeof(struct sockaddr);
+#endif
+ IPAddress addr;
+ bool haveAddr = false;
+ int ifIndex(-1);
+ switch (ifr->ifr_addr.sa_family)
+ {
+#if defined(POCO_HAVE_IPv6)
+ case AF_INET6:
+ ifIndex = if_nametoindex(ifr->ifr_name);
+ if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6);
+ addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
+ haveAddr = true;
+ break;
+#endif
+ case AF_INET:
+ if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in);
+ addr = IPAddress(ifr->ifr_addr);
+ haveAddr = true;
+ break;
+ default:
+ break;
+ }
+ if (haveAddr)
+ {
+ std::string name(ifr->ifr_name);
+ result.push_back(NetworkInterface(name, name, name, addr, ifIndex));
+ }
+ len += sizeof(ifr->ifr_name);
+ ptr += len;
+ }
+ }
+ catch (...)
+ {
+ delete [] buf;
+ throw;
+ }
+ delete [] buf;
+ return result;
+}
+*/
+
+} } // namespace Poco::Net
+
+
+#endif
+
+
+#endif // POCO_NET_HAS_INTERFACE