DEV9: Unify GetAdapter code

This commit is contained in:
TheLastRar 2024-05-19 18:06:07 +01:00 committed by refractionpcsx2
parent 344cf6fffb
commit 3aff833b5c
4 changed files with 84 additions and 171 deletions

View File

@ -55,17 +55,15 @@ using namespace PacketReader::IP;
*/ */
#ifdef _WIN32 #ifdef _WIN32
bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, AdapterBuffer* buffer) AdapterUtils::Adapter* AdapterUtils::GetAllAdapters(AdapterBuffer* buffer, bool includeHidden)
{ {
int neededSize = 128; int neededSize = includeHidden ? 256 : 128;
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> adapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize); std::unique_ptr<IP_ADAPTER_ADDRESSES[]> adapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize);
ULONG dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize; ULONG dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize;
PIP_ADAPTER_ADDRESSES pAdapterInfo;
DWORD dwStatus = GetAdaptersAddresses( DWORD dwStatus = GetAdaptersAddresses(
AF_UNSPEC, AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | (includeHidden ? GAA_FLAG_INCLUDE_ALL_INTERFACES : 0),
NULL, NULL,
adapterInfo.get(), adapterInfo.get(),
&dwBufLen); &dwBufLen);
@ -80,66 +78,45 @@ bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, Adapter
dwStatus = GetAdaptersAddresses( dwStatus = GetAdaptersAddresses(
AF_UNSPEC, AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | (includeHidden ? GAA_FLAG_INCLUDE_ALL_INTERFACES : 0),
NULL, NULL,
adapterInfo.get(), adapterInfo.get(),
&dwBufLen); &dwBufLen);
} }
if (dwStatus != ERROR_SUCCESS) if (dwStatus != ERROR_SUCCESS)
return false; return nullptr;
pAdapterInfo = adapterInfo.get(); buffer->swap(adapterInfo);
return buffer->get();
}
bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, AdapterBuffer* buffer)
{
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> adapterInfo;
PIP_ADAPTER_ADDRESSES pAdapter = GetAllAdapters(&adapterInfo);
if (pAdapter == nullptr)
return false;
do do
{ {
if (strcmp(pAdapterInfo->AdapterName, name.c_str()) == 0) if (strcmp(pAdapter->AdapterName, name.c_str()) == 0)
{ {
*adapter = *pAdapterInfo; *adapter = *pAdapter;
buffer->swap(adapterInfo); buffer->swap(adapterInfo);
return true; return true;
} }
pAdapterInfo = pAdapterInfo->Next; pAdapter = pAdapter->Next;
} while (pAdapterInfo); } while (pAdapter);
return false; return false;
} }
bool AdapterUtils::GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer) bool AdapterUtils::GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer)
{ {
int neededSize = 128; std::unique_ptr<IP_ADAPTER_ADDRESSES[]> adapterInfo;
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> adapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize); PIP_ADAPTER_ADDRESSES pAdapter = GetAllAdapters(&adapterInfo);
ULONG dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize; if (pAdapter == nullptr)
return false;
PIP_ADAPTER_ADDRESSES pAdapter;
DWORD dwStatus = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS,
NULL,
adapterInfo.get(),
&dwBufLen);
if (dwStatus == ERROR_BUFFER_OVERFLOW)
{
DevCon.WriteLn("DEV9: PCAPGetWin32Adapter() buffer too small, resizing");
//
neededSize = dwBufLen / sizeof(IP_ADAPTER_ADDRESSES) + 1;
adapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize);
dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize;
DevCon.WriteLn("DEV9: New size %i", neededSize);
dwStatus = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS,
NULL,
adapterInfo.get(),
&dwBufLen);
}
if (dwStatus != ERROR_SUCCESS)
return 0;
pAdapter = adapterInfo.get();
do do
{ {
@ -181,19 +158,25 @@ bool AdapterUtils::GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer)
return false; return false;
} }
#elif defined(__POSIX__) #elif defined(__POSIX__)
bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, AdapterBuffer* buffer) AdapterUtils::Adapter* AdapterUtils::GetAllAdapters(AdapterBuffer* buffer)
{ {
ifaddrs* ifa; ifaddrs* ifa;
ifaddrs* pAdapter;
int error = getifaddrs(&ifa); int error = getifaddrs(&ifa);
if (error) if (error)
return nullptr;
buffer->reset(ifa);
return buffer->get();
}
bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, AdapterBuffer* buffer)
{
std::unique_ptr<ifaddrs, IfAdaptersDeleter> adapterInfo;
ifaddrs* pAdapter = GetAllAdapters(&adapterInfo);
if (pAdapter == nullptr)
return false; return false;
std::unique_ptr<ifaddrs, IfAdaptersDeleter> adapterInfo(ifa, IfAdaptersDeleter());
pAdapter = adapterInfo.get();
do do
{ {
if (pAdapter->ifa_addr != nullptr && if (pAdapter->ifa_addr != nullptr &&
@ -215,17 +198,11 @@ bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, Adapter
} }
bool AdapterUtils::GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer) bool AdapterUtils::GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer)
{ {
ifaddrs* ifa; std::unique_ptr<ifaddrs, IfAdaptersDeleter> adapterInfo;
ifaddrs* pAdapter; ifaddrs* pAdapter = GetAllAdapters(&adapterInfo);
if (pAdapter == nullptr)
int error = getifaddrs(&ifa);
if (error)
return false; return false;
std::unique_ptr<ifaddrs, IfAdaptersDeleter> adapterInfo(ifa, IfAdaptersDeleter());
pAdapter = adapterInfo.get();
do do
{ {
if ((pAdapter->ifa_flags & IFF_LOOPBACK) == 0 && if ((pAdapter->ifa_flags & IFF_LOOPBACK) == 0 &&

View File

@ -31,6 +31,15 @@ namespace AdapterUtils
void operator()(ifaddrs* buffer) const { freeifaddrs(buffer); } void operator()(ifaddrs* buffer) const { freeifaddrs(buffer); }
}; };
typedef std::unique_ptr<ifaddrs, IfAdaptersDeleter> AdapterBuffer; typedef std::unique_ptr<ifaddrs, IfAdaptersDeleter> AdapterBuffer;
#endif
// Adapter is a structure that contains ptrs to data stored within AdapterBuffer.
// We need to return this buffer the caller can free it after it's finished with Adapter.
// AdapterBuffer is a unique_ptr, so will be freed when it leaves scope.
#ifdef _WIN32
// includeHidden sets GAA_FLAG_INCLUDE_ALL_INTERFACES, used by TAPAdapter
Adapter* GetAllAdapters(AdapterBuffer* buffer, bool includeHidden = false);
#elif defined(__POSIX__)
Adapter* GetAllAdapters(AdapterBuffer* buffer);
#endif #endif
bool GetAdapter(const std::string& name, Adapter* adapter, AdapterBuffer* buffer); bool GetAdapter(const std::string& name, Adapter* adapter, AdapterBuffer* buffer);
bool GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer); bool GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer);

View File

@ -24,6 +24,7 @@
#include <wil/resource.h> #include <wil/resource.h>
#include "DEV9/PacketReader/MAC_Address.h" #include "DEV9/PacketReader/MAC_Address.h"
#include "DEV9/AdapterUtils.h"
//============= //=============
// TAP IOCTLs // TAP IOCTLs
@ -272,80 +273,41 @@ PIP_ADAPTER_ADDRESSES FindAdapterViaIndex(PIP_ADAPTER_ADDRESSES adapterList, int
//IP_ADAPTER_ADDRESSES is a structure that contains ptrs to data in other regions //IP_ADAPTER_ADDRESSES is a structure that contains ptrs to data in other regions
//of the buffer, se we need to return both so the caller can free the buffer //of the buffer, se we need to return both so the caller can free the buffer
//after it's finished reading the needed data from IP_ADAPTER_ADDRESSES //after it's finished reading the needed data from IP_ADAPTER_ADDRESSES
bool TAPGetWin32Adapter(const std::string& name, PIP_ADAPTER_ADDRESSES adapter, std::unique_ptr<IP_ADAPTER_ADDRESSES[]>* buffer) bool TAPGetWin32Adapter(const std::string& name, PIP_ADAPTER_ADDRESSES adapter, AdapterUtils::AdapterBuffer* buffer)
{ {
int neededSize = 256;
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> AdapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize);
ULONG dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize;
PIP_ADAPTER_ADDRESSES pAdapterInfo;
//GAA_FLAG_INCLUDE_ALL_INTERFACES needed to get Tap when bridged //GAA_FLAG_INCLUDE_ALL_INTERFACES needed to get Tap when bridged
DWORD dwStatus = GetAdaptersAddresses( AdapterUtils::AdapterBuffer adapterInfo;
AF_UNSPEC, PIP_ADAPTER_ADDRESSES pAdapterFirst = AdapterUtils::GetAllAdapters(&adapterInfo, true);
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | GAA_FLAG_INCLUDE_ALL_INTERFACES, if (pAdapterFirst == nullptr)
NULL, return false;
AdapterInfo.get(),
&dwBufLen);
if (dwStatus == ERROR_BUFFER_OVERFLOW)
{
DevCon.WriteLn("DEV9: GetWin32Adapter() buffer too small, resizing");
//
neededSize = dwBufLen / sizeof(IP_ADAPTER_ADDRESSES) + 1;
AdapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize);
dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize;
DevCon.WriteLn("DEV9: New size %i", neededSize);
dwStatus = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | GAA_FLAG_INCLUDE_ALL_INTERFACES,
NULL,
AdapterInfo.get(),
&dwBufLen);
}
if (dwStatus != ERROR_SUCCESS)
return 0;
pAdapterInfo = AdapterInfo.get();
PIP_ADAPTER_ADDRESSES pAdapter = pAdapterFirst;
do do
{ {
if (0 == strcmp(pAdapterInfo->AdapterName, name.c_str())) if (0 == strcmp(pAdapter->AdapterName, name.c_str()))
break; break;
pAdapterInfo = pAdapterInfo->Next; pAdapter = pAdapter->Next;
} while (pAdapterInfo); } while (pAdapter);
if (pAdapterInfo == nullptr) if (pAdapter == nullptr)
return false; return false;
//If we are bridged, then we won't show up without GAA_FLAG_INCLUDE_ALL_INTERFACES //If we are bridged, then we won't show up without GAA_FLAG_INCLUDE_ALL_INTERFACES
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> AdapterInfoReduced = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize); AdapterUtils::AdapterBuffer adapterInfoReduced;
dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize; PIP_ADAPTER_ADDRESSES pAdapterReducedFirst = AdapterUtils::GetAllAdapters(&adapterInfoReduced, false);
dwStatus = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS,
NULL,
AdapterInfoReduced.get(),
&dwBufLen);
if (dwStatus != ERROR_SUCCESS)
return 0;
//If we find our adapter in the reduced list, we are not bridged //If we find our adapter in the reduced list, we are not bridged
if (FindAdapterViaIndex(AdapterInfoReduced.get(), pAdapterInfo->IfIndex) != nullptr) if (FindAdapterViaIndex(pAdapterReducedFirst, pAdapter->IfIndex) != nullptr)
{ {
*adapter = *pAdapterInfo; *adapter = *pAdapter;
buffer->swap(AdapterInfo); buffer->swap(adapterInfo);
return true; return true;
} }
//We must be bridged //We must be bridged
Console.WriteLn("DEV9: Current adapter is probably bridged"); Console.WriteLn("DEV9: Current adapter is probably bridged");
Console.WriteLn(fmt::format("DEV9: Adapter Display name: {}", StringUtil::WideStringToUTF8String(pAdapterInfo->FriendlyName))); Console.WriteLn(fmt::format("DEV9: Adapter Display name: {}", StringUtil::WideStringToUTF8String(pAdapter->FriendlyName)));
//We will need to find the bridge adapter that out adapter is //We will need to find the bridge adapter that out adapter is
//as the IP information of the tap adapter is null //as the IP information of the tap adapter is null
@ -379,7 +341,7 @@ bool TAPGetWin32Adapter(const std::string& name, PIP_ADAPTER_ADDRESSES adapter,
//If multiple rows have our adapter, we check all of them //If multiple rows have our adapter, we check all of them
std::vector<NET_IFINDEX> potentialBridges; std::vector<NET_IFINDEX> potentialBridges;
std::vector<NET_IFINDEX> searchList; std::vector<NET_IFINDEX> searchList;
searchList.push_back(pAdapterInfo->IfIndex); searchList.push_back(pAdapter->IfIndex);
PMIB_IFSTACK_TABLE table; PMIB_IFSTACK_TABLE table;
GetIfStackTable(&table); GetIfStackTable(&table);
@ -392,7 +354,7 @@ bool TAPGetWin32Adapter(const std::string& name, PIP_ADAPTER_ADDRESSES adapter,
MIB_IFSTACK_ROW row = table->Table[i]; MIB_IFSTACK_ROW row = table->Table[i];
if (row.LowerLayerInterfaceIndex == targetIndex) if (row.LowerLayerInterfaceIndex == targetIndex)
{ {
const PIP_ADAPTER_ADDRESSES potentialAdapter = FindAdapterViaIndex(AdapterInfoReduced.get(), row.HigherLayerInterfaceIndex); const PIP_ADAPTER_ADDRESSES potentialAdapter = FindAdapterViaIndex(pAdapterReducedFirst, row.HigherLayerInterfaceIndex);
if (potentialAdapter != nullptr) if (potentialAdapter != nullptr)
{ {
Console.WriteLn(fmt::format("DEV9: {} is possible bridge (Check 1 passed)", StringUtil::WideStringToUTF8String(potentialAdapter->Description))); Console.WriteLn(fmt::format("DEV9: {} is possible bridge (Check 1 passed)", StringUtil::WideStringToUTF8String(potentialAdapter->Description)));
@ -406,7 +368,8 @@ bool TAPGetWin32Adapter(const std::string& name, PIP_ADAPTER_ADDRESSES adapter,
} }
//Cleanup //Cleanup
FreeMibTable(table); FreeMibTable(table);
AdapterInfoReduced = nullptr; pAdapterReducedFirst = nullptr;
adapterInfoReduced.reset();
//Step 2 //Step 2
//Init COM //Init COM
@ -442,7 +405,7 @@ bool TAPGetWin32Adapter(const std::string& name, PIP_ADAPTER_ADDRESSES adapter,
//We need to match the adapter index to an INetCfgComponent //We need to match the adapter index to an INetCfgComponent
//We do this by matching IP_ADAPTER_ADDRESSES.AdapterName //We do this by matching IP_ADAPTER_ADDRESSES.AdapterName
//with the INetCfgComponent Instance GUID //with the INetCfgComponent Instance GUID
PIP_ADAPTER_ADDRESSES cAdapterInfo = FindAdapterViaIndex(AdapterInfo.get(), index); PIP_ADAPTER_ADDRESSES cAdapterInfo = FindAdapterViaIndex(pAdapterFirst, index);
if (cAdapterInfo == nullptr || cAdapterInfo->AdapterName == nullptr) if (cAdapterInfo == nullptr || cAdapterInfo->AdapterName == nullptr)
continue; continue;
@ -514,7 +477,7 @@ bool TAPGetWin32Adapter(const std::string& name, PIP_ADAPTER_ADDRESSES adapter,
if (bridgeAdapter != nullptr) if (bridgeAdapter != nullptr)
{ {
*adapter = *bridgeAdapter; *adapter = *bridgeAdapter;
buffer->swap(AdapterInfo); buffer->swap(adapterInfo);
return true; return true;
} }
@ -551,7 +514,7 @@ TAPAdapter::TAPAdapter()
SetMACAddress(&newMAC); SetMACAddress(&newMAC);
IP_ADAPTER_ADDRESSES adapter; IP_ADAPTER_ADDRESSES adapter;
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> buffer; AdapterUtils::AdapterBuffer buffer;
if (TAPGetWin32Adapter(EmuConfig.DEV9.EthDevice, &adapter, &buffer)) if (TAPGetWin32Adapter(EmuConfig.DEV9.EthDevice, &adapter, &buffer))
InitInternalServer(&adapter); InitInternalServer(&adapter);
else else
@ -646,7 +609,7 @@ bool TAPAdapter::send(NetPacket* pkt)
void TAPAdapter::reloadSettings() void TAPAdapter::reloadSettings()
{ {
IP_ADAPTER_ADDRESSES adapter; IP_ADAPTER_ADDRESSES adapter;
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> buffer; AdapterUtils::AdapterBuffer buffer;
if (TAPGetWin32Adapter(EmuConfig.DEV9.EthDevice, &adapter, &buffer)) if (TAPGetWin32Adapter(EmuConfig.DEV9.EthDevice, &adapter, &buffer))
ReloadInternalServer(&adapter); ReloadInternalServer(&adapter);
else else

View File

@ -50,67 +50,33 @@ std::vector<AdapterEntry> SocketAdapter::GetAdapters()
nic.push_back(autoEntry); nic.push_back(autoEntry);
#ifdef _WIN32 #ifdef _WIN32
int neededSize = 128; AdapterUtils::AdapterBuffer adapterInfo;
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> AdapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize); PIP_ADAPTER_ADDRESSES pAdapter = AdapterUtils::GetAllAdapters(&adapterInfo);
ULONG dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize; if (pAdapter == nullptr)
PIP_ADAPTER_ADDRESSES pAdapterInfo;
DWORD dwStatus = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS,
NULL,
AdapterInfo.get(),
&dwBufLen);
if (dwStatus == ERROR_BUFFER_OVERFLOW)
{
DevCon.WriteLn("DEV9: PCAPGetWin32Adapter() buffer too small, resizing");
//
neededSize = dwBufLen / sizeof(IP_ADAPTER_ADDRESSES) + 1;
AdapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize);
dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize;
DevCon.WriteLn("DEV9: New size %i", neededSize);
dwStatus = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS,
NULL,
AdapterInfo.get(),
&dwBufLen);
}
if (dwStatus != ERROR_SUCCESS)
return nic; return nic;
pAdapterInfo = AdapterInfo.get();
do do
{ {
if (pAdapterInfo->IfType != IF_TYPE_SOFTWARE_LOOPBACK && if (pAdapter->IfType != IF_TYPE_SOFTWARE_LOOPBACK &&
pAdapterInfo->OperStatus == IfOperStatusUp) pAdapter->OperStatus == IfOperStatusUp)
{ {
AdapterEntry entry; AdapterEntry entry;
entry.type = Pcsx2Config::DEV9Options::NetApi::Sockets; entry.type = Pcsx2Config::DEV9Options::NetApi::Sockets;
entry.name = StringUtil::WideStringToUTF8String(pAdapterInfo->FriendlyName); entry.name = StringUtil::WideStringToUTF8String(pAdapter->FriendlyName);
entry.guid = pAdapterInfo->AdapterName; entry.guid = pAdapter->AdapterName;
nic.push_back(entry); nic.push_back(entry);
} }
pAdapterInfo = pAdapterInfo->Next; pAdapter = pAdapter->Next;
} while (pAdapterInfo); } while (pAdapter);
#elif defined(__POSIX__) #elif defined(__POSIX__)
ifaddrs* adapterInfo; AdapterUtils::AdapterBuffer adapterInfo;
ifaddrs* pAdapter; ifaddrs* pAdapter = GetAllAdapters(&adapterInfo);
if (pAdapter == nullptr)
int error = getifaddrs(&adapterInfo);
if (error)
return nic; return nic;
pAdapter = adapterInfo;
do do
{ {
if ((pAdapter->ifa_flags & IFF_LOOPBACK) == 0 && if ((pAdapter->ifa_flags & IFF_LOOPBACK) == 0 &&
@ -128,8 +94,6 @@ std::vector<AdapterEntry> SocketAdapter::GetAdapters()
pAdapter = pAdapter->ifa_next; pAdapter = pAdapter->ifa_next;
} while (pAdapter); } while (pAdapter);
freeifaddrs(adapterInfo);
#endif #endif
return nic; return nic;