|
|
@ -75,7 +75,8 @@ const char *inet_ntop_xp(int af, const void *src, char *dst, socklen_t size) |
|
|
|
ZeroMemory(&ss, sizeof(ss)); |
|
|
|
ZeroMemory(&ss, sizeof(ss)); |
|
|
|
ss.ss_family = af; |
|
|
|
ss.ss_family = af; |
|
|
|
|
|
|
|
|
|
|
|
switch(af) { |
|
|
|
switch (af) |
|
|
|
|
|
|
|
{ |
|
|
|
case AF_INET: |
|
|
|
case AF_INET: |
|
|
|
((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src; |
|
|
|
((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src; |
|
|
|
break; |
|
|
|
break; |
|
|
@ -179,7 +180,7 @@ namespace net |
|
|
|
PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr; |
|
|
|
PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr; |
|
|
|
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; |
|
|
|
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
if(GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) |
|
|
|
if (GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) |
|
|
|
== ERROR_BUFFER_OVERFLOW) |
|
|
|
== ERROR_BUFFER_OVERFLOW) |
|
|
|
{ |
|
|
|
{ |
|
|
|
FREE(pAddresses); |
|
|
|
FREE(pAddresses); |
|
|
@ -190,7 +191,7 @@ namespace net |
|
|
|
AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen |
|
|
|
AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if(dwRetVal != NO_ERROR) |
|
|
|
if (dwRetVal != NO_ERROR) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LogPrint(eLogError, "NetIface: GetMTU: Enclosed GetAdaptersAddresses() call has failed"); |
|
|
|
LogPrint(eLogError, "NetIface: GetMTU: Enclosed GetAdaptersAddresses() call has failed"); |
|
|
|
FREE(pAddresses); |
|
|
|
FREE(pAddresses); |
|
|
@ -198,17 +199,17 @@ namespace net |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pCurrAddresses = pAddresses; |
|
|
|
pCurrAddresses = pAddresses; |
|
|
|
while(pCurrAddresses) |
|
|
|
while (pCurrAddresses) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pUnicast = pCurrAddresses->FirstUnicastAddress; |
|
|
|
pUnicast = pCurrAddresses->FirstUnicastAddress; |
|
|
|
if(pUnicast == nullptr) |
|
|
|
if (pUnicast == nullptr) |
|
|
|
LogPrint(eLogError, "NetIface: GetMTU: Not a unicast IPv4 address, this is not supported"); |
|
|
|
LogPrint(eLogError, "NetIface: GetMTU: Not a unicast IPv4 address, this is not supported"); |
|
|
|
|
|
|
|
|
|
|
|
while(pUnicast != nullptr) |
|
|
|
while (pUnicast != nullptr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; |
|
|
|
LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; |
|
|
|
sockaddr_in* localInterfaceAddress = (sockaddr_in*) lpAddr; |
|
|
|
sockaddr_in* localInterfaceAddress = (sockaddr_in*) lpAddr; |
|
|
|
if(localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr) |
|
|
|
if (localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char addr[INET_ADDRSTRLEN]; |
|
|
|
char addr[INET_ADDRSTRLEN]; |
|
|
|
inetntop(AF_INET, &(((struct sockaddr_in *)localInterfaceAddress)->sin_addr), addr, INET_ADDRSTRLEN); |
|
|
|
inetntop(AF_INET, &(((struct sockaddr_in *)localInterfaceAddress)->sin_addr), addr, INET_ADDRSTRLEN); |
|
|
@ -314,13 +315,13 @@ namespace net |
|
|
|
IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton"); |
|
|
|
IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton"); |
|
|
|
if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found
|
|
|
|
if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found
|
|
|
|
|
|
|
|
|
|
|
|
if(localAddress.is_v4()) |
|
|
|
if (localAddress.is_v4()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
sockaddr_in inputAddress; |
|
|
|
sockaddr_in inputAddress; |
|
|
|
inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); |
|
|
|
inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); |
|
|
|
return GetMTUWindowsIpv4(inputAddress, fallback); |
|
|
|
return GetMTUWindowsIpv4(inputAddress, fallback); |
|
|
|
} |
|
|
|
} |
|
|
|
else if(localAddress.is_v6()) |
|
|
|
else if (localAddress.is_v6()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
sockaddr_in6 inputAddress; |
|
|
|
sockaddr_in6 inputAddress; |
|
|
|
inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); |
|
|
|
inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); |
|
|
@ -336,7 +337,7 @@ namespace net |
|
|
|
int GetMTUUnix (const boost::asio::ip::address& localAddress, int fallback) |
|
|
|
int GetMTUUnix (const boost::asio::ip::address& localAddress, int fallback) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ifaddrs* ifaddr, *ifa = nullptr; |
|
|
|
ifaddrs* ifaddr, *ifa = nullptr; |
|
|
|
if(getifaddrs(&ifaddr) == -1) |
|
|
|
if (getifaddrs(&ifaddr) == -1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LogPrint(eLogError, "NetIface: Can't call getifaddrs(): ", strerror(errno)); |
|
|
|
LogPrint(eLogError, "NetIface: Can't call getifaddrs(): ", strerror(errno)); |
|
|
|
return fallback; |
|
|
|
return fallback; |
|
|
@ -344,34 +345,34 @@ namespace net |
|
|
|
|
|
|
|
|
|
|
|
int family = 0; |
|
|
|
int family = 0; |
|
|
|
// look for interface matching local address
|
|
|
|
// look for interface matching local address
|
|
|
|
for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) |
|
|
|
for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if(!ifa->ifa_addr) |
|
|
|
if (!ifa->ifa_addr) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
family = ifa->ifa_addr->sa_family; |
|
|
|
family = ifa->ifa_addr->sa_family; |
|
|
|
if(family == AF_INET && localAddress.is_v4()) |
|
|
|
if (family == AF_INET && localAddress.is_v4()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
sockaddr_in* sa = (sockaddr_in*) ifa->ifa_addr; |
|
|
|
sockaddr_in* sa = (sockaddr_in*) ifa->ifa_addr; |
|
|
|
if(!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4)) |
|
|
|
if (!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4)) |
|
|
|
break; // address matches
|
|
|
|
break; // address matches
|
|
|
|
} |
|
|
|
} |
|
|
|
else if(family == AF_INET6 && localAddress.is_v6()) |
|
|
|
else if (family == AF_INET6 && localAddress.is_v6()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
sockaddr_in6* sa = (sockaddr_in6*) ifa->ifa_addr; |
|
|
|
sockaddr_in6* sa = (sockaddr_in6*) ifa->ifa_addr; |
|
|
|
if(!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16)) |
|
|
|
if (!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16)) |
|
|
|
break; // address matches
|
|
|
|
break; // address matches
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
int mtu = fallback; |
|
|
|
int mtu = fallback; |
|
|
|
if(ifa && family) |
|
|
|
if (ifa && family) |
|
|
|
{ // interface found?
|
|
|
|
{ // interface found?
|
|
|
|
int fd = socket(family, SOCK_DGRAM, 0); |
|
|
|
int fd = socket(family, SOCK_DGRAM, 0); |
|
|
|
if(fd > 0) |
|
|
|
if (fd > 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ifreq ifr; |
|
|
|
ifreq ifr; |
|
|
|
strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ-1); // set interface for query
|
|
|
|
strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ-1); // set interface for query
|
|
|
|
if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0) |
|
|
|
if (ioctl(fd, SIOCGIFMTU, &ifr) >= 0) |
|
|
|
mtu = ifr.ifr_mtu; // MTU
|
|
|
|
mtu = ifr.ifr_mtu; // MTU
|
|
|
|
else |
|
|
|
else |
|
|
|
LogPrint (eLogError, "NetIface: Failed to run ioctl: ", strerror(errno)); |
|
|
|
LogPrint (eLogError, "NetIface: Failed to run ioctl: ", strerror(errno)); |
|
|
@ -404,7 +405,7 @@ namespace net |
|
|
|
{ |
|
|
|
{ |
|
|
|
#ifdef _WIN32 |
|
|
|
#ifdef _WIN32 |
|
|
|
LogPrint(eLogError, "NetIface: Cannot get address by interface name, not implemented on WIN32"); |
|
|
|
LogPrint(eLogError, "NetIface: Cannot get address by interface name, not implemented on WIN32"); |
|
|
|
if(ipv6) |
|
|
|
if (ipv6) |
|
|
|
return boost::asio::ip::address::from_string("::1"); |
|
|
|
return boost::asio::ip::address::from_string("::1"); |
|
|
|
else |
|
|
|
else |
|
|
|
return boost::asio::ip::address::from_string("127.0.0.1"); |
|
|
|
return boost::asio::ip::address::from_string("127.0.0.1"); |
|
|
@ -423,7 +424,7 @@ namespace net |
|
|
|
// match
|
|
|
|
// match
|
|
|
|
char addr[INET6_ADDRSTRLEN]; |
|
|
|
char addr[INET6_ADDRSTRLEN]; |
|
|
|
memset (addr, 0, INET6_ADDRSTRLEN); |
|
|
|
memset (addr, 0, INET6_ADDRSTRLEN); |
|
|
|
if(af == AF_INET) |
|
|
|
if (af == AF_INET) |
|
|
|
inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN); |
|
|
|
inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN); |
|
|
|
else |
|
|
|
else |
|
|
|
inet_ntop(af, &((sockaddr_in6 *)cur->ifa_addr)->sin6_addr, addr, INET6_ADDRSTRLEN); |
|
|
|
inet_ntop(af, &((sockaddr_in6 *)cur->ifa_addr)->sin6_addr, addr, INET6_ADDRSTRLEN); |
|
|
@ -439,9 +440,9 @@ namespace net |
|
|
|
LogPrint(eLogError, "NetIface: Exception while searching address using ifaddr: ", ex.what()); |
|
|
|
LogPrint(eLogError, "NetIface: Exception while searching address using ifaddr: ", ex.what()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(addrs) freeifaddrs(addrs); |
|
|
|
if (addrs) freeifaddrs(addrs); |
|
|
|
std::string fallback; |
|
|
|
std::string fallback; |
|
|
|
if(ipv6) |
|
|
|
if (ipv6) |
|
|
|
{ |
|
|
|
{ |
|
|
|
fallback = "::1"; |
|
|
|
fallback = "::1"; |
|
|
|
LogPrint(eLogWarning, "NetIface: Cannot find IPv6 address for interface ", ifname); |
|
|
|
LogPrint(eLogWarning, "NetIface: Cannot find IPv6 address for interface ", ifname); |
|
|
@ -509,7 +510,7 @@ namespace net |
|
|
|
PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr; |
|
|
|
PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr; |
|
|
|
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; |
|
|
|
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) |
|
|
|
if (GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) |
|
|
|
== ERROR_BUFFER_OVERFLOW) |
|
|
|
== ERROR_BUFFER_OVERFLOW) |
|
|
|
{ |
|
|
|
{ |
|
|
|
FREE(pAddresses); |
|
|
|
FREE(pAddresses); |
|
|
@ -520,7 +521,7 @@ namespace net |
|
|
|
AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen |
|
|
|
AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if(dwRetVal != NO_ERROR) |
|
|
|
if (dwRetVal != NO_ERROR) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LogPrint(eLogError, "NetIface: GetYggdrasilAddress(): enclosed GetAdaptersAddresses() call has failed"); |
|
|
|
LogPrint(eLogError, "NetIface: GetYggdrasilAddress(): enclosed GetAdaptersAddresses() call has failed"); |
|
|
|
FREE(pAddresses); |
|
|
|
FREE(pAddresses); |
|
|
@ -528,11 +529,11 @@ namespace net |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pCurrAddresses = pAddresses; |
|
|
|
pCurrAddresses = pAddresses; |
|
|
|
while(pCurrAddresses) |
|
|
|
while (pCurrAddresses) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pUnicast = pCurrAddresses->FirstUnicastAddress; |
|
|
|
pUnicast = pCurrAddresses->FirstUnicastAddress; |
|
|
|
|
|
|
|
|
|
|
|
while(pUnicast != nullptr) |
|
|
|
while (pUnicast != nullptr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; |
|
|
|
LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; |
|
|
|
sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr; |
|
|
|
sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr; |
|
|
@ -576,7 +577,7 @@ namespace net |
|
|
|
LogPrint(eLogError, "NetIface: Exception while searching Yggdrasill address using ifaddr: ", ex.what()); |
|
|
|
LogPrint(eLogError, "NetIface: Exception while searching Yggdrasill address using ifaddr: ", ex.what()); |
|
|
|
} |
|
|
|
} |
|
|
|
LogPrint(eLogWarning, "NetIface: Interface with Yggdrasil network address not found"); |
|
|
|
LogPrint(eLogWarning, "NetIface: Interface with Yggdrasil network address not found"); |
|
|
|
if(addrs) freeifaddrs(addrs); |
|
|
|
if (addrs) freeifaddrs(addrs); |
|
|
|
return boost::asio::ip::address_v6 (); |
|
|
|
return boost::asio::ip::address_v6 (); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
@ -596,7 +597,7 @@ namespace net |
|
|
|
{ |
|
|
|
{ |
|
|
|
// https://en.wikipedia.org/wiki/Reserved_IP_addresses
|
|
|
|
// https://en.wikipedia.org/wiki/Reserved_IP_addresses
|
|
|
|
if (host.is_unspecified ()) return false; |
|
|
|
if (host.is_unspecified ()) return false; |
|
|
|
if(host.is_v4()) |
|
|
|
if (host.is_v4()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
static const std::vector< std::pair<uint32_t, uint32_t> > reservedIPv4Ranges { |
|
|
|
static const std::vector< std::pair<uint32_t, uint32_t> > reservedIPv4Ranges { |
|
|
|
address_pair_v4("0.0.0.0", "0.255.255.255"), |
|
|
|
address_pair_v4("0.0.0.0", "0.255.255.255"), |
|
|
@ -616,12 +617,12 @@ namespace net |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
uint32_t ipv4_address = host.to_v4 ().to_ulong (); |
|
|
|
uint32_t ipv4_address = host.to_v4 ().to_ulong (); |
|
|
|
for(const auto& it : reservedIPv4Ranges) { |
|
|
|
for (const auto& it : reservedIPv4Ranges) { |
|
|
|
if (ipv4_address >= it.first && ipv4_address <= it.second) |
|
|
|
if (ipv4_address >= it.first && ipv4_address <= it.second) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if(host.is_v6()) |
|
|
|
if (host.is_v6()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
static const std::vector< std::pair<boost::asio::ip::address_v6::bytes_type, boost::asio::ip::address_v6::bytes_type> > reservedIPv6Ranges { |
|
|
|
static const std::vector< std::pair<boost::asio::ip::address_v6::bytes_type, boost::asio::ip::address_v6::bytes_type> > reservedIPv6Ranges { |
|
|
|
address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"), |
|
|
|
address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"), |
|
|
@ -633,7 +634,7 @@ namespace net |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
boost::asio::ip::address_v6::bytes_type ipv6_address = host.to_v6 ().to_bytes (); |
|
|
|
boost::asio::ip::address_v6::bytes_type ipv6_address = host.to_v6 ().to_bytes (); |
|
|
|
for(const auto& it : reservedIPv6Ranges) { |
|
|
|
for (const auto& it : reservedIPv6Ranges) { |
|
|
|
if (ipv6_address >= it.first && ipv6_address <= it.second) |
|
|
|
if (ipv6_address >= it.first && ipv6_address <= it.second) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|