From 8bb29695edbe9b944052d7a2464d49860e00e8b2 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Fri, 27 Feb 2026 16:50:41 -0600 Subject: [PATCH] Lib.Net: Proper resolver errors when isConnectedToNetwork is disabled (#4081) * Force resolver errors when not connected to network Error values are based on real hardware testing. sceNetResolverGetError is based on libSceNet decompilation. * Update net_resolver.h --- src/core/libraries/network/net.cpp | 28 +++++++++++++++++++-- src/core/libraries/network/net_resolver.cpp | 10 ++++++-- src/core/libraries/network/net_resolver.h | 3 ++- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 102447952..ca75ad394 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -887,6 +887,10 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events, } file->resolver->Resolve(); + if (file->resolver->resolution_error != ORBIS_OK) { + // Resolution failed, shouldn't appear. + continue; + } const auto it = std::ranges::find_if(epoll->events, [&](auto& el) { return el.first == rid; }); @@ -1402,8 +1406,21 @@ int PS4_SYSV_ABI sceNetResolverDestroy(OrbisNetId resolverid) { } int PS4_SYSV_ABI sceNetResolverGetError(OrbisNetId resolverid, s32* status) { - LOG_ERROR(Lib_Net, "(STUBBED) called rid = {}", resolverid); - *status = 0; + if (!status) { + LOG_ERROR(Lib_Net, "status == nullptr"); + *sceNetErrnoLoc() = ORBIS_NET_EINVAL; + return ORBIS_NET_ERROR_EINVAL; + } + + auto file = FDTable::Instance()->GetResolver(resolverid); + if (!file) { + LOG_ERROR(Lib_Net, "invalid resolverid {}", resolverid); + *sceNetErrnoLoc() = ORBIS_NET_EBADF; + return ORBIS_NET_ERROR_EBADF; + } + + *status = file->resolver->resolution_error; + LOG_INFO(Lib_Net, "called rid = {}, error = {:#x}", resolverid, static_cast(*status)); return ORBIS_OK; } @@ -1425,10 +1442,17 @@ int PS4_SYSV_ABI sceNetResolverStartNtoa(OrbisNetId resolverid, const char* host auto file = FDTable::Instance()->GetResolver(resolverid); if (!file) { + LOG_ERROR(Lib_Net, "invalid resolverid {}", resolverid); *sceNetErrnoLoc() = ORBIS_NET_EBADF; return ORBIS_NET_ERROR_EBADF; } + if (!Config::getIsConnectedToNetwork()) { + *sceNetErrnoLoc() = ORBIS_NET_RESOLVER_ENODNS; + file->resolver->resolution_error = ORBIS_NET_ERROR_RESOLVER_ENODNS; + return ORBIS_NET_ERROR_RESOLVER_ENODNS; + } + if ((flags & ORBIS_NET_RESOLVER_ASYNC) != 0) { return file->resolver->ResolveAsync(hostname, addr, timeout, retry, flags); } diff --git a/src/core/libraries/network/net_resolver.cpp b/src/core/libraries/network/net_resolver.cpp index 6571176df..a334cd8a4 100644 --- a/src/core/libraries/network/net_resolver.cpp +++ b/src/core/libraries/network/net_resolver.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" +#include "common/config.h" #include "common/singleton.h" #include "common/types.h" #include "core/libraries/error_codes.h" @@ -26,11 +27,16 @@ int Resolver::ResolveAsync(const char* hostname, OrbisNetInAddr* addr, int timeo } void Resolver::Resolve() { + if (!Config::getIsConnectedToNetwork()) { + resolution_error = ORBIS_NET_ERROR_RESOLVER_ENODNS; + return; + } + if (async_resolution) { auto* netinfo = Common::Singleton::Instance(); auto ret = netinfo->ResolveHostname(async_resolution->hostname, async_resolution->addr); - - resolution_error = ret; + // Resolver errors are stored as ORBIS_NET_ERROR values. + resolution_error = -ret | ORBIS_NET_ERROR_BASE; } else { LOG_ERROR(Lib_Net, "async resolution has not been set-up"); } diff --git a/src/core/libraries/network/net_resolver.h b/src/core/libraries/network/net_resolver.h index 34d7dc591..4c5c2ece8 100644 --- a/src/core/libraries/network/net_resolver.h +++ b/src/core/libraries/network/net_resolver.h @@ -18,6 +18,8 @@ public: int ResolveAsync(const char* hostname, OrbisNetInAddr* addr, int timeout, int retry, int flags); void Resolve(); + int resolution_error = ORBIS_OK; + private: struct AsyncResolution { const char* hostname; @@ -31,7 +33,6 @@ private: int poolid; int flags; std::optional async_resolution{}; - int resolution_error = ORBIS_OK; std::mutex m_mutex; };