From f2665262f794a80c4eddb76503d9eb0c02ff4b09 Mon Sep 17 00:00:00 2001 From: Yuriy Grishin Date: Sun, 15 Mar 2015 08:51:07 -0700 Subject: [PATCH 1/2] Added MTU detection code for Windows --- util.cpp | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 179 insertions(+), 5 deletions(-) diff --git a/util.cpp b/util.cpp index 42541a75..6f6b2fc8 100644 --- a/util.cpp +++ b/util.cpp @@ -19,11 +19,45 @@ #if defined(__linux__) || defined(__FreeBSD_kernel__) #include #include -#endif - -#ifdef WIN32 -#include +#elif defined(WIN32) +#include +#include +#include +#include +#include +#include #include + +#pragma comment(lib, "IPHLPAPI.lib") + +#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) +#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) + +int inet_pton(int af, const char *src, void *dst) +{ /* This function was written by Petar Korponai?. See +http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found */ + struct sockaddr_storage ss; + int size = sizeof (ss); + char src_copy[INET6_ADDRSTRLEN + 1]; + + ZeroMemory (&ss, sizeof (ss)); + strncpy_s (src_copy, src, INET6_ADDRSTRLEN + 1); + src_copy[INET6_ADDRSTRLEN] = 0; + + if (WSAStringToAddress (src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0) + { + switch (af) + { + case AF_INET: + *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr; + return 1; + case AF_INET6: + *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr; + return 1; + } + } + return 0; +} #endif namespace i2p @@ -514,8 +548,148 @@ namespace net freeifaddrs (ifaddr); return mtu; +#elif defined(WIN32) + + int result = 576; // fallback MTU + + DWORD dwRetVal = 0; + ULONG outBufLen = 0; + PIP_ADAPTER_ADDRESSES pAddresses = nullptr; + PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr; + PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; + +#ifdef UNICODE + string localAddress_temporary = localAddress.to_string(); + wstring localAddressUniversal (localAddress_temporary.begin(), localAddress_temporary.end()); #else - return 0; + std::string localAddressUniversal = localAddress.to_string(); +#endif + + if (localAddress.is_v4()) + { + struct sockaddr_in inputAddress; + inet_pton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); + + if (GetAdaptersAddresses (AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) + == ERROR_BUFFER_OVERFLOW) + { + FREE (pAddresses); + pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC (outBufLen); + } + + dwRetVal = GetAdaptersAddresses (AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen); + if (dwRetVal == NO_ERROR) + { + pCurrAddresses = pAddresses; + while (pCurrAddresses) + { + PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress; + + pUnicast = pCurrAddresses->FirstUnicastAddress; + if (pUnicast != nullptr) + { + for (int i = 0; pUnicast != nullptr; ++i) + { + LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; + struct sockaddr_in *localInterfaceAddress = (struct sockaddr_in*) lpAddr; + if (localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr) + { + result = pAddresses->Mtu; + FREE (pAddresses); + pAddresses = nullptr; + return result; + } + pUnicast = pUnicast->Next; + } + } + else + { + LogPrint (eLogError, "GetMTU() has failed: not a unicast ipv4 address, this is not supported"); + } + + pCurrAddresses = pCurrAddresses->Next; + } + + } + else + { + LogPrint (eLogError, "GetMTU() has failed: enclosed GetAdaptersAddresses() call has failed"); + } + + } + else if (localAddress.is_v6()) + { + struct sockaddr_in6 inputAddress; + inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); + + if (GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) + == ERROR_BUFFER_OVERFLOW) + { + FREE (pAddresses); + pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen); + } + + dwRetVal = GetAdaptersAddresses (AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen); + if (dwRetVal == NO_ERROR) + { + bool found_address = false; + pCurrAddresses = pAddresses; + while (pCurrAddresses) + { + PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress; + + pUnicast = pCurrAddresses->FirstUnicastAddress; + if (pUnicast != nullptr) + { + for (int i = 0; pUnicast != nullptr; ++i) + { + LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; + struct sockaddr_in6 *localInterfaceAddress = (struct sockaddr_in6*) lpAddr; + + for (int j = 0; j != 8; ++j) + { + if (localInterfaceAddress->sin6_addr.u.Word[j] != inputAddress.sin6_addr.u.Word[j]) + { + break; + } + else + { + found_address = true; + } + } + if (found_address) + { + result = pAddresses->Mtu; + FREE (pAddresses); + pAddresses = nullptr; + return result; + } + pUnicast = pUnicast->Next; + } + } + else + { + LogPrint (eLogError, "GetMTU() has failed: not a unicast ipv6 address, this is not supported"); + } + + pCurrAddresses = pCurrAddresses->Next; + } + + } + else + { + LogPrint (eLogError, "GetMTU() has failed: enclosed GetAdaptersAddresses() call has failed"); + } + } + else + { + LogPrint (eLogError, "GetMTU() has failed: address family is not supported"); + } + + FREE (pAddresses); + pAddresses = nullptr; + LogPrint(eLogError, "GetMTU() error: control flow should never reach this line"); + return result; #endif } } From f32399454cf0a91d0579ef7ed8cac71024c0cf07 Mon Sep 17 00:00:00 2001 From: Yuriy Grishin Date: Sun, 15 Mar 2015 10:07:39 -0700 Subject: [PATCH 2/2] Whitespace to follow coding style convention --- util.cpp | 138 +++++++++++++++++++++++++++---------------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/util.cpp b/util.cpp index 6f6b2fc8..fbaf2dbf 100644 --- a/util.cpp +++ b/util.cpp @@ -550,115 +550,115 @@ namespace net return mtu; #elif defined(WIN32) - int result = 576; // fallback MTU + int result = 576; // fallback MTU - DWORD dwRetVal = 0; - ULONG outBufLen = 0; - PIP_ADAPTER_ADDRESSES pAddresses = nullptr; - PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr; - PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; + DWORD dwRetVal = 0; + ULONG outBufLen = 0; + PIP_ADAPTER_ADDRESSES pAddresses = nullptr; + PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr; + PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; #ifdef UNICODE - string localAddress_temporary = localAddress.to_string(); - wstring localAddressUniversal (localAddress_temporary.begin(), localAddress_temporary.end()); + string localAddress_temporary = localAddress.to_string(); + wstring localAddressUniversal (localAddress_temporary.begin(), localAddress_temporary.end()); #else - std::string localAddressUniversal = localAddress.to_string(); + std::string localAddressUniversal = localAddress.to_string(); #endif - if (localAddress.is_v4()) - { - struct sockaddr_in inputAddress; + if (localAddress.is_v4()) + { + struct sockaddr_in inputAddress; inet_pton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); - if (GetAdaptersAddresses (AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) - == ERROR_BUFFER_OVERFLOW) - { - FREE (pAddresses); - pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC (outBufLen); - } - - dwRetVal = GetAdaptersAddresses (AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen); - if (dwRetVal == NO_ERROR) - { - pCurrAddresses = pAddresses; - while (pCurrAddresses) - { - PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress; - - pUnicast = pCurrAddresses->FirstUnicastAddress; - if (pUnicast != nullptr) - { - for (int i = 0; pUnicast != nullptr; ++i) - { - LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; - struct sockaddr_in *localInterfaceAddress = (struct sockaddr_in*) lpAddr; - if (localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr) - { - result = pAddresses->Mtu; - FREE (pAddresses); - pAddresses = nullptr; - return result; - } - pUnicast = pUnicast->Next; - } - } - else - { - LogPrint (eLogError, "GetMTU() has failed: not a unicast ipv4 address, this is not supported"); - } - - pCurrAddresses = pCurrAddresses->Next; + if (GetAdaptersAddresses (AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) + == ERROR_BUFFER_OVERFLOW) + { + FREE (pAddresses); + pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC (outBufLen); } + dwRetVal = GetAdaptersAddresses (AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen); + if (dwRetVal == NO_ERROR) + { + pCurrAddresses = pAddresses; + while (pCurrAddresses) + { + PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress; + + pUnicast = pCurrAddresses->FirstUnicastAddress; + if (pUnicast != nullptr) + { + for (int i = 0; pUnicast != nullptr; ++i) + { + LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; + struct sockaddr_in *localInterfaceAddress = (struct sockaddr_in*) lpAddr; + if (localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr) + { + result = pAddresses->Mtu; + FREE (pAddresses); + pAddresses = nullptr; + return result; + } + pUnicast = pUnicast->Next; + } + } + else + { + LogPrint (eLogError, "GetMTU() has failed: not a unicast ipv4 address, this is not supported"); + } + + pCurrAddresses = pCurrAddresses->Next; + } + } else - { + { LogPrint (eLogError, "GetMTU() has failed: enclosed GetAdaptersAddresses() call has failed"); } } else if (localAddress.is_v6()) - { + { struct sockaddr_in6 inputAddress; inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); if (GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) - { + { FREE (pAddresses); - pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen); + pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC (outBufLen); } dwRetVal = GetAdaptersAddresses (AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen); if (dwRetVal == NO_ERROR) - { + { bool found_address = false; pCurrAddresses = pAddresses; while (pCurrAddresses) - { + { PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress; pUnicast = pCurrAddresses->FirstUnicastAddress; if (pUnicast != nullptr) - { + { for (int i = 0; pUnicast != nullptr; ++i) - { + { LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; struct sockaddr_in6 *localInterfaceAddress = (struct sockaddr_in6*) lpAddr; - + for (int j = 0; j != 8; ++j) - { + { if (localInterfaceAddress->sin6_addr.u.Word[j] != inputAddress.sin6_addr.u.Word[j]) - { + { break; } else - { + { found_address = true; } } if (found_address) - { + { result = pAddresses->Mtu; FREE (pAddresses); pAddresses = nullptr; @@ -668,7 +668,7 @@ namespace net } } else - { + { LogPrint (eLogError, "GetMTU() has failed: not a unicast ipv6 address, this is not supported"); } @@ -677,20 +677,20 @@ namespace net } else - { - LogPrint (eLogError, "GetMTU() has failed: enclosed GetAdaptersAddresses() call has failed"); + { + LogPrint (eLogError, "GetMTU() has failed: enclosed GetAdaptersAddresses() call has failed"); } } else - { - LogPrint (eLogError, "GetMTU() has failed: address family is not supported"); + { + LogPrint (eLogError, "GetMTU() has failed: address family is not supported"); } FREE (pAddresses); pAddresses = nullptr; LogPrint(eLogError, "GetMTU() error: control flow should never reach this line"); return result; -#endif +#endif } }