From 8b1b0fa0dc8dfefc312e89e21cab22ef35ad6b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 25 Jul 2025 18:05:28 +0200 Subject: [PATCH] Implement simple DNS name resolution (#3318) * Implement simple DNS name resolution * Remove conversion of getaddrinfo errors to string --------- Co-authored-by: georgemoralis --- src/core/libraries/network/net.cpp | 68 +++++++++++++++++++++++++----- src/core/libraries/network/net.h | 40 ++++++++++++++++-- 2 files changed, 94 insertions(+), 14 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index c422a0009..8a8a1b1ee 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -20,6 +20,7 @@ #include "net_error.h" #include "net_util.h" #include "netctl.h" +#include "sockets.h" #include "sys_net.h" namespace Libraries::Net { @@ -1399,12 +1400,13 @@ int PS4_SYSV_ABI sceNetResolverConnectDestroy() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetResolverCreate() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetResolverCreate(const char* name, int poolid, int flags) { + LOG_ERROR(Lib_Net, "(STUBBED) called, name = {}, poolid = {}, flags = {}", name, poolid, flags); + static int id = 1; + return id++; } -int PS4_SYSV_ABI sceNetResolverDestroy() { +int PS4_SYSV_ABI sceNetResolverDestroy(OrbisNetId resolverid) { LOG_ERROR(Lib_Net, "(STUBBED) called"); return ORBIS_OK; } @@ -1424,9 +1426,43 @@ int PS4_SYSV_ABI sceNetResolverStartAton6() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetResolverStartNtoa() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetResolverStartNtoa(OrbisNetId resolverid, const char* hostname, + OrbisNetInAddr* addr, int timeout, int retry, int flags) { + LOG_INFO(Lib_Net, + "called, resolverid = {}, hostname = {}, timeout = {}, retry = {}, flags = {}", + resolverid, hostname, timeout, retry, flags); + + if ((flags & ORBIS_NET_RESOLVER_ASYNC) != 0) { + // moves processing to EpollWait + LOG_ERROR(Lib_Net, "async resolution is not implemented"); + *sceNetErrnoLoc() = ORBIS_NET_RESOLVER_EINTERNAL; + auto ret = -ORBIS_NET_RESOLVER_EINTERNAL | ORBIS_NET_ERROR_BASE; + return ret; + } + + const addrinfo hints = { + .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG, + .ai_family = AF_INET, + }; + + addrinfo* info = nullptr; + auto gai_result = getaddrinfo(hostname, nullptr, &hints, &info); + + auto ret = ORBIS_OK; + if (gai_result != 0) { + // handle more errors + LOG_ERROR(Lib_Net, "address resolution for {} failed: {}", hostname, gai_result); + *sceNetErrnoLoc() = ORBIS_NET_ERETURN; + ret = -ORBIS_NET_ERETURN | ORBIS_NET_ERROR_BASE; + } else { + ASSERT(info && info->ai_addr); + in_addr resolved_addr = ((sockaddr_in*)info->ai_addr)->sin_addr; + LOG_DEBUG(Lib_Net, "resolved address for {}: {}", hostname, inet_ntoa(resolved_addr)); + addr->inaddr_addr = resolved_addr.s_addr; + } + + freeaddrinfo(info); + return ret; } int PS4_SYSV_ABI sceNetResolverStartNtoa6() { @@ -1434,9 +1470,21 @@ int PS4_SYSV_ABI sceNetResolverStartNtoa6() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(OrbisNetId resolverid, const char* hostname, + OrbisNetResolverInfo* info, int timeout, + int retry, int flags) { + LOG_WARNING(Lib_Net, "redirected to sceNetResolverStartNtoa"); + + OrbisNetInAddr addr{}; + auto result = sceNetResolverStartNtoa(resolverid, hostname, &addr, timeout, retry, flags); + + if (result == ORBIS_OK) { + info->addrs[0] = {.u = {.addr = addr}, .af = ORBIS_NET_AF_INET}; + info->records = 1; + info->recordsv4 = 1; + } + + return result; } int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecordsEx() { diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index 25dfaf4a7..9bbe51041 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -95,6 +95,11 @@ enum OrbisNetEpollEvents : u32 { ORBIS_NET_EPOLLDESCID = 0x10000, }; +enum OrbisNetResolverFlag : u32 { + ORBIS_NET_RESOLVER_ASYNC = 0x1, + ORBIS_NET_RESOLVER_START_NTOA_DISABLE_IPADDRESS = 0x10000, +}; + using OrbisNetId = s32; struct OrbisNetSockaddr { @@ -112,6 +117,12 @@ struct OrbisNetSockaddrIn { char sin_zero[6]; }; +using OrbisNetInAddr_t = u32; + +struct OrbisNetInAddr { + OrbisNetInAddr_t inaddr_addr; +}; + struct OrbisNetIovec { void* iov_base; u64 iov_len; @@ -141,6 +152,24 @@ struct OrbisNetEpollEvent { OrbisNetEpollData data; }; +union OrbisNetAddrUnion { + OrbisNetInAddr addr; + u8 addr6[16]; +}; + +struct OrbisNetResolverAddr { + OrbisNetAddrUnion u; + u32 af; + u32 pad[3]; +}; + +struct OrbisNetResolverInfo { + OrbisNetResolverAddr addrs[10]; + u32 records; + u32 recordsv4; + u32 pad[14]; +}; + int PS4_SYSV_ABI in6addr_any(); int PS4_SYSV_ABI in6addr_loopback(); int PS4_SYSV_ABI sce_net_dummy(); @@ -310,14 +339,17 @@ int PS4_SYSV_ABI sceNetResolverConnect(); int PS4_SYSV_ABI sceNetResolverConnectAbort(); int PS4_SYSV_ABI sceNetResolverConnectCreate(); int PS4_SYSV_ABI sceNetResolverConnectDestroy(); -int PS4_SYSV_ABI sceNetResolverCreate(); -int PS4_SYSV_ABI sceNetResolverDestroy(); +int PS4_SYSV_ABI sceNetResolverCreate(const char* name, int poolid, int flags); +int PS4_SYSV_ABI sceNetResolverDestroy(OrbisNetId resolverid); int PS4_SYSV_ABI sceNetResolverGetError(); int PS4_SYSV_ABI sceNetResolverStartAton(); int PS4_SYSV_ABI sceNetResolverStartAton6(); -int PS4_SYSV_ABI sceNetResolverStartNtoa(); +int PS4_SYSV_ABI sceNetResolverStartNtoa(OrbisNetId resolverid, const char* hostname, + OrbisNetInAddr* addr, int timeout, int retry, int flags); int PS4_SYSV_ABI sceNetResolverStartNtoa6(); -int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(); +int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(OrbisNetId resolverid, const char* hostname, + OrbisNetResolverInfo* info, int timeout, + int retry, int flags); int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecordsEx(); int PS4_SYSV_ABI sceNetSend(OrbisNetId s, const void* buf, u64 len, int flags); int PS4_SYSV_ABI sceNetSendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags);