M2-PT-DRP/source/utils/network.cpp

60 lines
1.8 KiB
C++

#include "network.hpp"
#include <cstring>
#include <ifaddrs.h>
#include <stdexcept>
#include <netinet/in.h>
namespace drp::util::network {
bool is_localhost(const sockaddr_storage& address, const socklen_t addressLength) {
// iterate through all the interfaces
ifaddrs* interfaces;
if (getifaddrs(&interfaces) == -1)
throw std::runtime_error("Could not get network interfaces.");
bool result = false;
for (const ifaddrs *interface = interfaces; interface; interface = interface->ifa_next) {
// if the interface family does not correspond to the server candidate, ignore it
if (interface->ifa_addr->sa_family != address.ss_family)
continue;
switch (address.ss_family) {
case AF_INET: {
const auto interfaceIpv4 = reinterpret_cast<const sockaddr_in*>(interface->ifa_addr);
const auto addressIpv4 = reinterpret_cast<const sockaddr_in*>(&address);
// the family have already been checked.
if (std::memcmp(&interfaceIpv4->sin_addr, &addressIpv4->sin_addr, sizeof(in_addr)) == 0)
result = true;
break;
}
case AF_INET6: {
const auto interfaceIpv6 = reinterpret_cast<const sockaddr_in6*>(interface->ifa_addr);
const auto addressIpv6 = reinterpret_cast<const sockaddr_in6*>(&address);
// the interface and the family have already been checked.
if (std::memcmp(&interfaceIpv6->sin6_addr, &addressIpv6->sin6_addr, sizeof(in6_addr)) == 0)
result = true;
break;
}
default:
throw std::runtime_error("Unknown address family.");
}
if (result == true)
break;
}
freeifaddrs(interfaces);
return result;
}
}