2015-02-22 04:51:16 -05:00
|
|
|
|
|
|
|
// NetworkInterfaceEnum.cpp
|
|
|
|
|
|
|
|
// Implements the cNetwork::EnumLocalIPAddresses() interface enumeration function
|
|
|
|
|
|
|
|
#include "Globals.h"
|
|
|
|
#include "Network.h"
|
|
|
|
#include "event2/util.h"
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <IPHlpApi.h>
|
|
|
|
#pragma comment(lib, "IPHLPAPI.lib")
|
|
|
|
#else // _WIN32
|
2015-03-08 12:54:44 -04:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <ifaddrs.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
2015-02-22 04:51:16 -05:00
|
|
|
#endif // else _WIN32
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SELF_TEST
|
|
|
|
|
|
|
|
static class cEnumIPAddressTest
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
cEnumIPAddressTest(void)
|
|
|
|
{
|
|
|
|
printf("Enumerating all IP addresses...\n");
|
|
|
|
auto IPs = cNetwork::EnumLocalIPAddresses();
|
|
|
|
for (auto & ip: IPs)
|
|
|
|
{
|
|
|
|
printf(" %s\n", ip.c_str());
|
|
|
|
}
|
2015-03-08 12:54:44 -04:00
|
|
|
printf("Done.\n");
|
2015-02-22 04:51:16 -05:00
|
|
|
}
|
|
|
|
} g_EnumIPAddressTest;
|
|
|
|
|
|
|
|
#endif // SELF_TEST
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
|
|
/** Converts the SOCKET_ADDRESS structure received from the OS into an IP address string. */
|
|
|
|
static AString PrintAddress(SOCKET_ADDRESS & a_Addr)
|
|
|
|
{
|
|
|
|
char IP[128];
|
|
|
|
switch (a_Addr.lpSockaddr->sa_family)
|
|
|
|
{
|
|
|
|
case AF_INET:
|
|
|
|
{
|
|
|
|
auto sin = reinterpret_cast<const sockaddr_in *>(a_Addr.lpSockaddr);
|
|
|
|
evutil_inet_ntop(a_Addr.lpSockaddr->sa_family, &(sin->sin_addr), IP, sizeof(IP));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case AF_INET6:
|
|
|
|
{
|
|
|
|
auto sin = reinterpret_cast<const sockaddr_in6 *>(a_Addr.lpSockaddr);
|
|
|
|
evutil_inet_ntop(a_Addr.lpSockaddr->sa_family, &(sin->sin6_addr), IP, sizeof(IP));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
IP[0] = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-03-08 12:54:44 -04:00
|
|
|
return IP;
|
2015-02-22 04:51:16 -05:00
|
|
|
}
|
|
|
|
|
2015-03-08 12:54:44 -04:00
|
|
|
#else // _WIN32
|
|
|
|
|
|
|
|
static AString PrintAddress(ifaddrs * InterfaceAddress)
|
|
|
|
{
|
|
|
|
switch (InterfaceAddress->ifa_addr->sa_family)
|
|
|
|
{
|
|
|
|
case AF_INET:
|
|
|
|
{ // IPv4
|
|
|
|
char AddressBuffer[INET_ADDRSTRLEN];
|
2015-03-10 18:25:53 -04:00
|
|
|
sockaddr_in InternetSocket;
|
|
|
|
|
|
|
|
std::memcpy(&InternetSocket, InterfaceAddress->ifa_addr, sizeof(InternetSocket));
|
|
|
|
inet_ntop(AF_INET, &InternetSocket.sin_addr, AddressBuffer, INET_ADDRSTRLEN);
|
2015-03-08 12:54:44 -04:00
|
|
|
return AddressBuffer;
|
|
|
|
}
|
|
|
|
case AF_INET6:
|
|
|
|
{ // IPv6
|
|
|
|
char AddressBuffer[INET6_ADDRSTRLEN];
|
2015-03-10 18:25:53 -04:00
|
|
|
sockaddr_in6 InternetSocket;
|
|
|
|
|
|
|
|
std::memcpy(&InternetSocket, InterfaceAddress->ifa_addr, sizeof(InternetSocket));
|
|
|
|
inet_ntop(AF_INET6, &InternetSocket.sin6_addr, AddressBuffer, INET6_ADDRSTRLEN);
|
2015-03-08 12:54:44 -04:00
|
|
|
return AddressBuffer;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
LOG("Unknown address family: %i", InterfaceAddress->ifa_addr->sa_family);
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // else _WIN32
|
2015-02-22 04:51:16 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AStringVector cNetwork::EnumLocalIPAddresses(void)
|
|
|
|
{
|
|
|
|
AStringVector res;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
|
|
// Query the OS for all adapters' addresses:
|
|
|
|
char buffer[64 KiB]; // A buffer backing the address list
|
|
|
|
PIP_ADAPTER_ADDRESSES pAddresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer);
|
|
|
|
ULONG outBufLen = sizeof(buffer);
|
|
|
|
DWORD dwRetVal = GetAdaptersAddresses(
|
|
|
|
AF_UNSPEC,
|
|
|
|
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, nullptr,
|
|
|
|
pAddresses, &outBufLen
|
|
|
|
);
|
|
|
|
if (dwRetVal != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
LOG("GetAdaptersAddresses() failed: %u", dwRetVal);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enumerate all active adapters
|
|
|
|
for (auto pCurrAddresses = pAddresses; pCurrAddresses != nullptr; pCurrAddresses = pCurrAddresses->Next)
|
|
|
|
{
|
2015-02-22 12:52:49 -05:00
|
|
|
if (pCurrAddresses->OperStatus != IfOperStatusUp)
|
2015-02-22 04:51:16 -05:00
|
|
|
{
|
|
|
|
// Adapter not active, skip it:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Collect all IP addresses on this adapter:
|
|
|
|
for (auto pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast != nullptr; pUnicast = pUnicast->Next)
|
|
|
|
{
|
|
|
|
auto Address = PrintAddress(pUnicast->Address);
|
|
|
|
if (!Address.empty())
|
|
|
|
{
|
|
|
|
res.push_back(Address);
|
|
|
|
}
|
|
|
|
} // for pUnicast
|
|
|
|
} // for pCurrAddresses
|
|
|
|
|
|
|
|
#else // _WIN32
|
|
|
|
|
2015-03-08 12:54:44 -04:00
|
|
|
struct ifaddrs * ifAddrStruct = nullptr;
|
|
|
|
getifaddrs(&ifAddrStruct);
|
|
|
|
|
|
|
|
for (auto ifa = ifAddrStruct; ifa != nullptr; ifa = ifa->ifa_next)
|
|
|
|
{
|
|
|
|
if (ifa->ifa_addr == nullptr)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Address = PrintAddress(ifa);
|
|
|
|
if (!Address.empty())
|
|
|
|
{
|
|
|
|
res.emplace_back(Address);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ifAddrStruct != nullptr)
|
|
|
|
{
|
|
|
|
freeifaddrs(ifAddrStruct);
|
|
|
|
}
|
2015-02-22 04:51:16 -05:00
|
|
|
|
|
|
|
#endif // else _WIN32
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|