diff --git a/pcsx2/DEV9/AdapterUtils.cpp b/pcsx2/DEV9/AdapterUtils.cpp index 3d9ac709da..1dff8e35b7 100644 --- a/pcsx2/DEV9/AdapterUtils.cpp +++ b/pcsx2/DEV9/AdapterUtils.cpp @@ -56,6 +56,21 @@ using namespace PacketReader::IP; * Where they plan to sweep the issue under the rug. */ +/* + * We assume that a sockaddr_* object is given to us pre-aliased via a sockaddr pointer, we need to read sa_family for the actual type. + * Use std::memcpy to cast, but only copy enough to read the common initial layout, in case we somehow have a sockaddr_* smaller than sockaddr. + * In practice, any smaller stucts are probably padded up, but that padding is not noted in current spec afaik. + */ +u16 AdapterUtils::ReadAddressFamily(const sockaddr* unknownAddr) +{ + sockaddr addr; + // Structures are pointer-interconvertible with the first non-static field. + // However, On FreeBSD & Mac, sa_family is not the first member, sa_len is. + static_assert(std::is_standard_layout_v); + std::memcpy(&addr, unknownAddr, offsetof(sockaddr, sa_family) + sizeof(addr.sa_family)); + return addr.sa_family; +} + #ifdef _WIN32 AdapterUtils::Adapter* AdapterUtils::GetAllAdapters(AdapterBuffer* buffer, bool includeHidden) { @@ -187,7 +202,7 @@ bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, Adapter do { if (pAdapter->ifa_addr != nullptr && - pAdapter->ifa_addr->sa_family == AF_INET && + ReadAddressFamily(pAdapter->ifa_addr) == AF_INET && strcmp(pAdapter->ifa_name, name.c_str()) == 0) break; @@ -278,7 +293,7 @@ std::optional AdapterUtils::GetAdapterMAC(Adapter* adapter) if (strcmp(po->ifa_name, adapter->ifa_name)) continue; - if (po->ifa_addr->sa_family != AF_LINK) + if (ReadAddressFamily(po->ifa_addr) != AF_LINK) continue; // We have a valid MAC address. @@ -329,7 +344,7 @@ std::optional AdapterUtils::GetAdapterIP(Adapter* adapter) if (adapter != nullptr) { address = adapter->FirstUnicastAddress; - while (address != nullptr && address->Address.lpSockaddr->sa_family != AF_INET) + while (address != nullptr && ReadAddressFamily(address->Address.lpSockaddr) != AF_INET) address = address->Next; } @@ -346,7 +361,7 @@ std::optional AdapterUtils::GetAdapterIP(Adapter* adapter) sockaddr_in* address = nullptr; if (adapter != nullptr) { - if (adapter->ifa_addr != nullptr && adapter->ifa_addr->sa_family == AF_INET) + if (adapter->ifa_addr != nullptr && ReadAddressFamily(adapter->ifa_addr) == AF_INET) address = reinterpret_cast(adapter->ifa_addr); } @@ -369,7 +384,7 @@ std::vector AdapterUtils::GetGateways(Adapter* adapter) PIP_ADAPTER_GATEWAY_ADDRESS address = adapter->FirstGatewayAddress; while (address != nullptr) { - if (address->Address.lpSockaddr->sa_family == AF_INET) + if (ReadAddressFamily(address->Address.lpSockaddr) == AF_INET) { sockaddr_in* sockaddr = reinterpret_cast(address->Address.lpSockaddr); collection.push_back(std::bit_cast(sockaddr->sin_addr)); @@ -525,7 +540,7 @@ std::vector AdapterUtils::GetDNS(Adapter* adapter) PIP_ADAPTER_DNS_SERVER_ADDRESS address = adapter->FirstDnsServerAddress; while (address != nullptr) { - if (address->Address.lpSockaddr->sa_family == AF_INET) + if (ReadAddressFamily(address->Address.lpSockaddr) == AF_INET) { sockaddr_in* sockaddr = reinterpret_cast(address->Address.lpSockaddr); collection.push_back(std::bit_cast(sockaddr->sin_addr)); diff --git a/pcsx2/DEV9/AdapterUtils.h b/pcsx2/DEV9/AdapterUtils.h index af54d8e2a9..9c66a37d4d 100644 --- a/pcsx2/DEV9/AdapterUtils.h +++ b/pcsx2/DEV9/AdapterUtils.h @@ -32,6 +32,9 @@ namespace AdapterUtils }; typedef std::unique_ptr AdapterBuffer; #endif + + u16 ReadAddressFamily(const sockaddr* unknownAddr); + // 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. diff --git a/pcsx2/DEV9/sockets.cpp b/pcsx2/DEV9/sockets.cpp index 43f772b159..d791bef3dc 100644 --- a/pcsx2/DEV9/sockets.cpp +++ b/pcsx2/DEV9/sockets.cpp @@ -82,7 +82,7 @@ std::vector SocketAdapter::GetAdapters() if ((pAdapter->ifa_flags & IFF_LOOPBACK) == 0 && (pAdapter->ifa_flags & IFF_UP) != 0 && pAdapter->ifa_addr != nullptr && - pAdapter->ifa_addr->sa_family == AF_INET) + AdapterUtils::ReadAddressFamily(pAdapter->ifa_addr) == AF_INET) { AdapterEntry entry; entry.type = Pcsx2Config::DEV9Options::NetApi::Sockets;