60 lines
1.8 KiB
C++
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;
|
|
}
|
|
|
|
|
|
}
|