initial import

This commit is contained in:
Guenter Obiltschnig
2006-07-11 16:33:40 +00:00
commit f476bd6b32
1463 changed files with 242402 additions and 0 deletions

View File

@@ -0,0 +1,497 @@
//
// NetworkInterface.cpp
//
// $Id: //poco/1.1.0/Net/src/NetworkInterface.cpp#3 $
//
// Library: Net
// Package: Sockets
// Module: NetworkInterface
//
// 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 "Net/NetworkInterface.h"
#include "Net/DatagramSocket.h"
#include "Net/NetException.h"
#include "Foundation/NumberFormatter.h"
#include <string.h>
using Foundation::NumberFormatter;
using Foundation::FastMutex;
Net_BEGIN
FastMutex NetworkInterface::_mutex;
NetworkInterface::NetworkInterface():
_index(0)
{
}
NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, int index):
_name(name),
_address(address),
_index(index)
{
}
NetworkInterface::NetworkInterface(const NetworkInterface& interface):
_index(interface._index),
_name(interface._name),
_address(interface._address)
{
}
NetworkInterface::~NetworkInterface()
{
}
NetworkInterface& NetworkInterface::operator = (const NetworkInterface& interface)
{
if (&interface != this)
{
_index = interface._index;
_name = interface._name;
_address = interface._address;
}
return *this;
}
NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6)
{
#if defined(_WIN32)
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->name() == name && it->supportsIPv6() == requireIPv6)
return *it;
}
throw InterfaceNotFoundException(name);
#else
FastMutex::ScopedLock lock(_mutex);
struct ifreq ifr;
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ);
DatagramSocket ds(requireIPv6 ? IPAddress::IPv6 : IPAddress::IPv4);
ds.impl()->ioctl(SIOCGIFADDR, &ifr);
IPAddress addr;
#if defined(POCO_HAVE_IPv6)
if (ifr.ifr_addr.sa_family == AF_INET)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
else if (ifr.ifr_addr.sa_family == AF_INET6)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr.ifr_addr)->sin6_addr, sizeof(struct in6_addr));
else throw InterfaceNotFoundException(addr.toString(), "interface has no IP address");
int index = if_nametoindex(name.c_str());
#else
if (ifr.ifr_addr.sa_family == AF_INET)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
else throw InterfaceNotFoundException(addr.toString(), "interface has no IP address");
int index = 0;
#endif
return NetworkInterface(name, addr, index);
#endif
}
NetworkInterface NetworkInterface::forAddress(const IPAddress& addr)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->address() == addr)
return *it;
}
throw InterfaceNotFoundException(addr.toString());
}
NetworkInterface NetworkInterface::forIndex(int i)
{
if (i != 0)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->index() == i)
return *it;
}
throw InterfaceNotFoundException("#" + NumberFormatter::format(i));
}
else return NetworkInterface();
}
Foundation_END
//
// platform-specific code below
//
#if defined(POCO_OS_FAMILY_WINDOWS)
//
// Windows
//
#include <iphlpapi.h>
Net_BEGIN
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
#if defined(POCO_HAVE_IPv6)
// On Windows XP/Server 2003 and later we use GetAdaptersAddresses.
PIP_ADAPTER_ADDRESSES pAdapterAddresses;
PIP_ADAPTER_ADDRESSES pAdapter = 0;
ULONG len = sizeof(IP_ADAPTER_ADDRESSES);
pAdapterAddresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(new char[len]);
// Make an initial call to GetAdaptersAddresses to get
// the necessary size into len
DWORD rc = GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &len);
if (rc == ERROR_BUFFER_OVERFLOW)
{
delete [] reinterpret_cast<char*>(pAdapterAddresses);
pAdapterAddresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(new char[len]);
}
else if (rc != ERROR_SUCCESS)
{
throw NetException("cannot get network adapter list");
}
try
{
if (GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &len) == NO_ERROR)
{
pAdapter = pAdapterAddresses;
while (pAdapter)
{
if (pAdapter->FirstUnicastAddress)
{
IPAddress addr(pAdapter->FirstUnicastAddress->Address.lpSockaddr, pAdapter->FirstUnicastAddress->Address.iSockaddrLength);
result.push_back(NetworkInterface(std::string(pAdapter->AdapterName), addr, pAdapter->Ipv6IfIndex));
pAdapter = pAdapter->Next;
}
}
}
else throw NetException("cannot get network adapter list");
}
catch (Foundation::Exception&)
{
delete [] reinterpret_cast<char*>(pAdapterAddresses);
throw;
}
delete [] reinterpret_cast<char*>(pAdapterAddresses);
#else
// On Windows 2000 we use GetAdaptersInfo.
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = 0;
ULONG len = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[len]);
// Make an initial call to GetAdaptersInfo to get
// the necessary size into len
DWORD rc = GetAdaptersInfo(pAdapterInfo, &len);
if (rc == ERROR_BUFFER_OVERFLOW)
{
delete [] reinterpret_cast<char*>(pAdapterInfo);
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[len]);
}
else if (rc != ERROR_SUCCESS)
{
throw NetException("cannot get network adapter list");
}
try
{
if (GetAdaptersInfo(pAdapterInfo, &len) == NO_ERROR)
{
pAdapter = pAdapterInfo;
while (pAdapter)
{
IPAddress addr(std::string(pAdapter->IpAddressList.IpAddress.String));
result.push_back(NetworkInterface(std::string(pAdapter->AdapterName), addr));
pAdapter = pAdapter->Next;
}
}
else throw NetException("cannot get network adapter list");
}
catch (Foundation::Exception&)
{
delete [] reinterpret_cast<char*>(pAdapterInfo);
throw;
}
delete [] reinterpret_cast<char*>(pAdapterInfo);
#endif
return result;
}
Net_END
#elif defined(POCO_OS_FAMILY_BSD) || POCO_OS == POCO_OS_QNX
//
// BSD variants
//
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if_dl.h>
Net_BEGIN
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
struct ifaddrs* ifaphead;
int rc = getifaddrs(&ifaphead);
if (rc) throw NetException("cannot get network adapter list");
for (struct ifaddrs* ifap = ifaphead; ifap; ifap = ifap->ifa_next)
{
if (ifap->ifa_addr)
{
if (ifap->ifa_addr->sa_family == AF_INET)
{
IPAddress addr(&reinterpret_cast<struct sockaddr_in*>(ifap->ifa_addr)->sin_addr, sizeof(struct in_addr));
result.push_back(NetworkInterface(std::string(ifap->ifa_name), addr));
}
#if defined(POCO_HAVE_IPv6)
else if (ifap->ifa_addr->sa_family == AF_INET6)
{
IPAddress addr(&reinterpret_cast<struct sockaddr_in6*>(ifap->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
result.push_back(NetworkInterface(std::string(ifap->ifa_name), addr, if_nametoindex(ifap->ifa_name)));
}
#endif
}
}
freeifaddrs(ifaphead);
return result;
}
Net_END
#elif POCO_OS == POCO_OS_LINUX
//
// Linux
//
Net_BEGIN
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);
IPAddress addr;
bool haveAddr = false;
switch (ifr->ifr_addr.sa_family)
{
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr));
haveAddr = true;
break;
#endif
case AF_INET:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
#if defined(POCO_HAVE_IPv6)
int index = if_nametoindex(ifr->ifr_name);
#else
int index = -1;
#endif
result.push_back(NetworkInterface(std::string(ifr->ifr_name), addr, index));
}
ptr += sizeof(struct ifreq);
}
}
catch (...)
{
delete [] buf;
throw;
}
delete [] buf;
return result;
}
Net_END
#else
//
// Non-BSD Unix variants
//
Net_BEGIN
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;
switch (ifr->ifr_addr.sa_family)
{
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
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));
haveAddr = true;
break;
#endif
case AF_INET:
if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
#if defined(POCO_HAVE_IPv6)
int index = if_nametoindex(ifr->ifr_name);
#else
int index = -1;
#endif
result.push_back(NetworkInterface(std::string(ifr->ifr_name), addr, index));
}
len += sizeof(ifr->ifr_name);
ptr += len;
}
}
catch (...)
{
delete [] buf;
throw;
}
delete [] buf;
return result;
}
Net_END
#endif