commits
tags
#include "wj_lanip.h"
#include <cstring>
#include <cstdio>
#include <cstdint>
#if defined(__WINDOWS__) || defined(__NT__) || defined(_MSC_VER) || defined(_WIN32)
#ifndef __WIN32__
#define __WIN32__
#endif
#endif
static bool IsPrivateIPv4(uint32_t hostOrderAddr)
{
uint8_t a = uint8_t(hostOrderAddr >> 24);
uint8_t b = uint8_t(hostOrderAddr >> 16);
if (a == 10) return true; // 10.0.0.0/8
if (a == 172 && (b & 0xF0) == 16) return true; // 172.16.0.0/12
if (a == 192 && b == 168) return true; // 192.168.0.0/16
return false;
}
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
std::vector<std::string> WJ_GetLocalIPv4Addresses()
{
std::vector<std::string> result;
ULONG bufLen = 16384;
std::vector<uint8_t> buf(bufLen);
PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(buf.data());
ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
DWORD ret = GetAdaptersAddresses(AF_INET, flags, nullptr, addresses, &bufLen);
if (ret == ERROR_BUFFER_OVERFLOW)
{
buf.resize(bufLen);
addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(buf.data());
ret = GetAdaptersAddresses(AF_INET, flags, nullptr, addresses, &bufLen);
}
if (ret != NO_ERROR)
return result;
for (auto adapter = addresses; adapter != nullptr; adapter = adapter->Next)
{
if (adapter->OperStatus != IfOperStatusUp)
continue;
if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
continue;
for (auto ua = adapter->FirstUnicastAddress; ua != nullptr; ua = ua->Next)
{
sockaddr_in *sin = reinterpret_cast<sockaddr_in *>(ua->Address.lpSockaddr);
if (sin->sin_family != AF_INET)
continue;
uint32_t hostOrder = ntohl(sin->sin_addr.s_addr);
if (!IsPrivateIPv4(hostOrder))
continue;
char text[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &sin->sin_addr, text, sizeof(text)))
result.push_back(text);
}
}
return result;
}
#else // POSIX
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
std::vector<std::string> WJ_GetLocalIPv4Addresses()
{
std::vector<std::string> result;
ifaddrs *ifaddr = nullptr;
if (getifaddrs(&ifaddr) != 0)
return result;
for (ifaddrs *ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == nullptr || ifa->ifa_addr->sa_family != AF_INET)
continue;
if (!(ifa->ifa_flags & IFF_UP) || !(ifa->ifa_flags & IFF_RUNNING))
continue;
if (ifa->ifa_flags & IFF_LOOPBACK)
continue;
auto sin = reinterpret_cast<sockaddr_in *>(ifa->ifa_addr);
uint32_t hostOrder = ntohl(sin->sin_addr.s_addr);
if (!IsPrivateIPv4(hostOrder))
continue;
char text[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &sin->sin_addr, text, sizeof(text)))
result.push_back(text);
}
freeifaddrs(ifaddr);
return result;
}
#endif