From 2f701311f23051a03e6e91bf80b3bb7ac831cf0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Wed, 6 Aug 2025 07:00:29 +0200 Subject: [PATCH] Sockets fixes (#3392) * Print errnos as decimal * SetSocketOptions: prevent setting SO_TYPE * Extract net error handler * Change the local IP retrieval method * Fix windows --- src/core/libraries/network/net.cpp | 690 ++----------------- src/core/libraries/network/net_error.h | 1 + src/core/libraries/network/net_util.cpp | 45 ++ src/core/libraries/network/net_util.h | 3 + src/core/libraries/network/netctl.cpp | 28 +- src/core/libraries/network/posix_sockets.cpp | 2 +- src/core/libraries/network/sys_net.cpp | 20 +- 7 files changed, 131 insertions(+), 658 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index e51861d60..d57cc7bb6 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -40,6 +40,45 @@ static int ConvertFamilies(int family) { } } +auto NetErrorHandler(auto f) -> decltype(f()) { + auto result = 0; + int err; + int positiveErr; + + do { + result = f(); + + if (result >= 0) { + return result; // Success + } + + err = *Libraries::Kernel::__Error(); // Standard errno + + // Convert to positive error for comparison + positiveErr = (err < 0) ? -err : err; + + if ((positiveErr & 0xfff0000) != 0) { + // Unknown/fatal error range + *sceNetErrnoLoc() = ORBIS_NET_ERETURN; + return -positiveErr; + } + + // Retry if interrupted + } while (positiveErr == ORBIS_NET_EINTR); + + if (positiveErr == ORBIS_NET_ENOTSOCK) { + result = -ORBIS_NET_EBADF; + } else if (positiveErr == ORBIS_NET_ENETINTR) { + result = -ORBIS_NET_EINTR; + } else { + result = -positiveErr; + } + + *sceNetErrnoLoc() = -result; + + return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code +} + int PS4_SYSV_ABI in6addr_any() { LOG_ERROR(Lib_Net, "(STUBBED) called"); return ORBIS_OK; @@ -84,42 +123,8 @@ OrbisNetId PS4_SYSV_ABI sceNetAccept(OrbisNetId s, OrbisNetSockaddr* addr, u32* if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_accept(s, addr, paddrlen); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_accept(s, addr, paddrlen); }); } int PS4_SYSV_ABI sceNetAddrConfig6GetInfo() { @@ -181,42 +186,8 @@ int PS4_SYSV_ABI sceNetBind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addr if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_bind(s, addr, addrlen); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_bind(s, addr, addrlen); }); } int PS4_SYSV_ABI sceNetClearDnsCache() { @@ -563,42 +534,8 @@ int PS4_SYSV_ABI sceNetConnect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 a if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_connect(s, addr, addrlen); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_connect(s, addr, addrlen); }); } int PS4_SYSV_ABI sceNetControl() { @@ -797,42 +734,8 @@ int PS4_SYSV_ABI sceNetGetpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* pa if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_getpeername(s, addr, paddrlen); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_getpeername(s, addr, paddrlen); }); } int PS4_SYSV_ABI sceNetGetRandom() { @@ -859,42 +762,8 @@ int PS4_SYSV_ABI sceNetGetsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* pa if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_getsockname(s, addr, paddrlen); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_getsockname(s, addr, paddrlen); }); } int PS4_SYSV_ABI sceNetGetsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) { @@ -902,42 +771,8 @@ int PS4_SYSV_ABI sceNetGetsockopt(OrbisNetId s, int level, int optname, void* op if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_getsockopt(s, level, optname, optval, optlen); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_getsockopt(s, level, optname, optval, optlen); }); } int PS4_SYSV_ABI sceNetGetStatisticsInfo() { @@ -1167,42 +1002,8 @@ int PS4_SYSV_ABI sceNetListen(OrbisNetId s, int backlog) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_listen(s, backlog); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_listen(s, backlog); }); } int PS4_SYSV_ABI sceNetMemoryAllocate() { @@ -1252,42 +1053,9 @@ int PS4_SYSV_ABI sceNetRecv(OrbisNetId s, void* buf, u64 len, int flags) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_recvfrom(s, buf, len, flags | 0x40000000, nullptr, 0); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler( + [&] { return sys_recvfrom(s, buf, len, flags | 0x40000000, nullptr, 0); }); } int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr, @@ -1295,84 +1063,17 @@ int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, u64 len, int flags, Orb if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_recvfrom(s, buf, len, flags | 0x40000000, addr, paddrlen); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler( + [&] { return sys_recvfrom(s, buf, len, flags | 0x40000000, addr, paddrlen); }); } int PS4_SYSV_ABI sceNetRecvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_recvmsg(s, msg, flags | 0x40000000); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_recvmsg(s, msg, flags | 0x40000000); }); } int PS4_SYSV_ABI sceNetResolverAbort() { @@ -1496,84 +1197,16 @@ int PS4_SYSV_ABI sceNetSend(OrbisNetId s, const void* buf, u64 len, int flags) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_sendto(s, buf, len, flags | 0x40020000, nullptr, 0); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_sendto(s, buf, len, flags | 0x40020000, nullptr, 0); }); } int PS4_SYSV_ABI sceNetSendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_sendmsg(s, msg, flags | 0x40020000); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_sendmsg(s, msg, flags | 0x40020000); }); } int PS4_SYSV_ABI sceNetSendto(OrbisNetId s, const void* buf, u64 len, int flags, @@ -1581,42 +1214,9 @@ int PS4_SYSV_ABI sceNetSendto(OrbisNetId s, const void* buf, u64 len, int flags, if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_sendto(s, buf, len, flags | 0x40020000, addr, addrlen); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler( + [&] { return sys_sendto(s, buf, len, flags | 0x40020000, addr, addrlen); }); } int PS4_SYSV_ABI sceNetSetDns6Info() { @@ -1645,42 +1245,8 @@ int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const vo if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_setsockopt(s, level, optname, optval, optlen); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_setsockopt(s, level, optname, optval, optlen); }); } int PS4_SYSV_ABI sceNetShowIfconfig() { @@ -1767,168 +1333,32 @@ int PS4_SYSV_ABI sceNetShutdown(OrbisNetId s, int how) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_shutdown(s, how); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_shutdown(s, how); }); } OrbisNetId PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_socketex(name, family, type, protocol); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_socketex(name, family, type, protocol); }); } int PS4_SYSV_ABI sceNetSocketAbort(OrbisNetId s, int flags) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_netabort(s, flags); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_netabort(s, flags); }); } int PS4_SYSV_ABI sceNetSocketClose(OrbisNetId s) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } - int result; - int err; - int positiveErr; - do { - result = sys_socketclose(s); - - if (result >= 0) { - return result; // Success - } - - err = *Libraries::Kernel::__Error(); // Standard errno - - // Convert to positive error for comparison - int positiveErr = (err < 0) ? -err : err; - - if ((positiveErr & 0xfff0000) != 0) { - // Unknown/fatal error range - *sceNetErrnoLoc() = ORBIS_NET_ERETURN; - return -positiveErr; - } - - // Retry if interrupted - } while (positiveErr == ORBIS_NET_EINTR); - - if (positiveErr == ORBIS_NET_EADDRINUSE) { - result = -ORBIS_NET_EBADF; - } else if (positiveErr == ORBIS_NET_EALREADY) { - result = -ORBIS_NET_EINTR; - } else { - result = -positiveErr; - } - - *sceNetErrnoLoc() = -result; - - return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code + return NetErrorHandler([&] { return sys_socketclose(s); }); } int PS4_SYSV_ABI sceNetSyncCreate() { diff --git a/src/core/libraries/network/net_error.h b/src/core/libraries/network/net_error.h index 93ff3b6cb..d6eb61627 100644 --- a/src/core/libraries/network/net_error.h +++ b/src/core/libraries/network/net_error.h @@ -58,6 +58,7 @@ constexpr int ORBIS_NET_EINACTIVEDISABLED = 163; constexpr int ORBIS_NET_ENODATA = 164; constexpr int ORBIS_NET_EDESC = 165; constexpr int ORBIS_NET_EDESCTIMEDOUT = 166; +constexpr int ORBIS_NET_ENETINTR = 167; constexpr int ORBIS_NET_ENOTINIT = 200; constexpr int ORBIS_NET_ENOLIBMEM = 201; constexpr int ORBIS_NET_ECALLBACK = 203; diff --git a/src/core/libraries/network/net_util.cpp b/src/core/libraries/network/net_util.cpp index aa840cf3e..fe3c1f540 100644 --- a/src/core/libraries/network/net_util.cpp +++ b/src/core/libraries/network/net_util.cpp @@ -322,4 +322,49 @@ bool NetUtilInternal::RetrieveNetmask() { return success; } +const std::string& NetUtilInternal::GetIp() const { + return ip; +} + +bool NetUtilInternal::RetrieveIp() { + std::scoped_lock lock{m_mutex}; + + auto sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) { + return false; + } + + sockaddr_in sa{}; + socklen_t sa_len{sizeof(sa)}; + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = inet_addr("1.1.1.1"); + sa.sin_port = htons(80); + +#ifdef _WIN32 +#define close closesocket +#endif + + if (connect(sockfd, (sockaddr*)&sa, sa_len) == -1) { + close(sockfd); + return false; + } + + if (getsockname(sockfd, (struct sockaddr*)&sa, &sa_len) == -1) { + close(sockfd); + return false; + } + + char netmaskStr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &sa.sin_addr, netmaskStr, INET_ADDRSTRLEN); + ip = netmaskStr; + + close(sockfd); + +#ifdef _WIN32 +#undef close +#endif + + return true; +} + } // namespace NetUtil \ No newline at end of file diff --git a/src/core/libraries/network/net_util.h b/src/core/libraries/network/net_util.h index fce55c2ff..955e08f29 100644 --- a/src/core/libraries/network/net_util.h +++ b/src/core/libraries/network/net_util.h @@ -17,14 +17,17 @@ private: std::array ether_address{}; std::string default_gateway{}; std::string netmask{}; + std::string ip{}; std::mutex m_mutex; public: const std::array& GetEthernetAddr() const; const std::string& GetDefaultGateway() const; const std::string& GetNetmask() const; + const std::string& GetIp() const; bool RetrieveEthernetAddr(); bool RetrieveDefaultGateway(); bool RetrieveNetmask(); + bool RetrieveIp(); }; } // namespace NetUtil \ No newline at end of file diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index 4a293f4de..c0cb0d1d5 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -185,19 +185,12 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { break; case ORBIS_NET_CTL_INFO_IP_ADDRESS: { strcpy(info->ip_address, - "127.0.0.1"); // placeholder in case gethostbyname can't find another ip - char devname[80]; - gethostname(devname, 80); - if (struct hostent* resolved = gethostbyname(devname)) { - for (int i = 0; resolved->h_addr_list[i] != nullptr; ++i) { - struct in_addr addrIn; - memcpy(&addrIn, resolved->h_addr_list[i], sizeof(u32)); - char* addr = inet_ntoa(addrIn); - if (strcmp(addr, "127.0.0.1") != 0) { - strcpy(info->ip_address, addr); - break; - } - } + "127.0.0.1"); // placeholder in case ip retrieval failed + auto success = netinfo->RetrieveIp(); + if (success) { + strncpy(info->ip_address, netinfo->GetIp().data(), sizeof(info->ip_address)); + } else { + LOG_WARNING(Lib_NetCtl, "local ip: failed to retrieve"); } break; } @@ -214,8 +207,9 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { case ORBIS_NET_CTL_INFO_DEFAULT_ROUTE: { auto success = netinfo->RetrieveDefaultGateway(); if (success) { - strncpy(info->netmask, netinfo->GetDefaultGateway().data(), sizeof(info->netmask)); - LOG_DEBUG(Lib_NetCtl, "default gateway: {}", info->netmask); + strncpy(info->default_route, netinfo->GetDefaultGateway().data(), + sizeof(info->default_route)); + LOG_DEBUG(Lib_NetCtl, "default gateway: {}", info->default_route); } else { LOG_WARNING(Lib_NetCtl, "default gateway: failed to retrieve"); } @@ -234,8 +228,8 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { LOG_DEBUG(Lib_NetCtl, "http secondary dns: {}", info->secondary_dns); break; case ORBIS_NET_CTL_INFO_HTTP_PROXY_SERVER: - strcpy(info->http_proxy_server, "0.0.0.0"); - LOG_DEBUG(Lib_NetCtl, "http proxy server: {}", info->http_proxy_server); + info->http_proxy_server[0] = '\0'; + LOG_DEBUG(Lib_NetCtl, "http proxy server: none"); break; case ORBIS_NET_CTL_INFO_HTTP_PROXY_PORT: info->http_proxy_port = 0; diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp index 2f83bcb06..a2b63d5e4 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -286,12 +286,12 @@ int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u3 CASE_SETSOCKOPT(SO_RCVBUF); CASE_SETSOCKOPT(SO_SNDTIMEO); CASE_SETSOCKOPT(SO_RCVTIMEO); - CASE_SETSOCKOPT(SO_TYPE); CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_CONNECTTIMEO, &sockopt_so_connecttimeo); CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_REUSEPORT, &sockopt_so_reuseport); CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_ONESBCAST, &sockopt_so_onesbcast); CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USECRYPTO, &sockopt_so_usecrypto); CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USESIGNATURE, &sockopt_so_usesignature); + case ORBIS_NET_SO_TYPE: case ORBIS_NET_SO_ERROR: { *Libraries::Kernel::__Error() = ORBIS_NET_ENOPROTOOPT; return -1; diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index 4a3876d09..0fd1bc4c2 100644 --- a/src/core/libraries/network/sys_net.cpp +++ b/src/core/libraries/network/sys_net.cpp @@ -26,7 +26,7 @@ int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 add if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; } @@ -41,7 +41,7 @@ int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrle if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; } @@ -79,7 +79,7 @@ int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* padd if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; } @@ -94,7 +94,7 @@ int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* padd if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; } @@ -109,7 +109,7 @@ int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optv if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; } @@ -124,7 +124,7 @@ int PS4_SYSV_ABI sys_listen(OrbisNetId s, int backlog) { if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; } @@ -140,7 +140,7 @@ int PS4_SYSV_ABI sys_setsockopt(OrbisNetId s, int level, int optname, const void if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; } @@ -204,7 +204,7 @@ int PS4_SYSV_ABI sys_socketclose(OrbisNetId s) { if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; } @@ -220,7 +220,7 @@ int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags, if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; } @@ -241,7 +241,7 @@ s64 PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, Orbis if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); return -1; }