mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 00:35:47 +00:00
fix(libSceNet): read an option of a libkernel socket through sceNetGetsockopt
Human Fall Flat (PPSA02429) opens its sockets with libkernel's socket() and reads options of them with sceNetGetsockopt. libSceNet only looked in its own socket table, so each call failed with SCE_NET_ERROR_EBADF. On the console both calls work on the same kernel sockets, the position sceNetSetsockopt already takes for MXGP 26 (PPSA30839). A descriptor libSceNet does not own but libkernel has open as a socket now goes to libkernel's getsockopt(), which answers the options it models. Anything else still fails with EBADF. The fallback runs after g_mutex is released. guest_sce_net reads SO_SNDBUF and TCP_NODELAY of a libkernel TCP socket through sceNetGetsockopt, checks that an unknown level fails with EINVAL, and that the call fails with EBADF once the socket is closed.
This commit is contained in:
1 parent
b90d009d9f
commit
6cbb4ff7fd
2 files changed
+31
-2
No files matched your search
@@ -1464,11 +1464,18 @@ int APS5_VABI sceNetSetsockopt(int s, int level, int optname, const void* optval
|
||||
|
||||
int APS5_VABI sceNetGetsockopt(int s, int level, int optname, void* optval, uint32_t* optlen) {
|
||||
Sock socket;
|
||||
bool found = false;
|
||||
{
|
||||
std::lock_guard lk(g_mutex);
|
||||
auto it = g_socks.find(s);
|
||||
if (it == g_socks.end()) return fail(NET_EBADF);
|
||||
socket = it->second;
|
||||
if (it != g_socks.end()) {
|
||||
socket = it->second;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (!GuestSocketIsOpen_nid_no_patch(s)) return fail(NET_EBADF);
|
||||
return getsockopt_nid_postfix(s, level, optname, optval, optlen) == 0 ? 0 : fail(*__error_nid_postfix());
|
||||
}
|
||||
if (optval == nullptr || optlen == nullptr) return fail(NET_EINVAL);
|
||||
if (level == NET_SOL_SOCKET && optname == NET_SO_PROTOCOL) {
|
||||
|
||||
@@ -1508,6 +1508,27 @@ static void CheckCloseKernelSocket() {
|
||||
Require(Failed(sceNetSocketClose(kernel), 9));
|
||||
}
|
||||
|
||||
static void CheckKernelSocketGetOption() {
|
||||
const int kernel = socket_nid_postfix(2, 1, 0);
|
||||
Require(kernel >= 0);
|
||||
const int requested = 65536;
|
||||
Require(sceNetSetsockopt(kernel, 0xffff, 0x1001, &requested, sizeof(requested)) == 0);
|
||||
int value = 0;
|
||||
std::uint32_t size = sizeof(value);
|
||||
Require(sceNetGetsockopt(kernel, 0xffff, 0x1001, &value, &size) == 0 && size == sizeof(value) && value > 0);
|
||||
int expected = 0;
|
||||
std::uint32_t expectedSize = sizeof(expected);
|
||||
Require(getsockopt_nid_postfix(kernel, 0xffff, 0x1001, &expected, &expectedSize) == 0 && value == expected);
|
||||
const int one = 1;
|
||||
Require(sceNetSetsockopt(kernel, 6, 1, &one, sizeof(one)) == 0);
|
||||
value = 0;
|
||||
size = sizeof(value);
|
||||
Require(sceNetGetsockopt(kernel, 6, 1, &value, &size) == 0 && value != 0);
|
||||
Require(Failed(sceNetGetsockopt(kernel, 1234, 1, &value, &size), 22));
|
||||
Require(close_nid_postfix(kernel) == 0);
|
||||
Require(Failed(sceNetGetsockopt(kernel, 0xffff, 0x1001, &value, &size), 9));
|
||||
}
|
||||
|
||||
static std::array<std::uint8_t, 0xa0> RequireSockInfo(int socket, int type, int flags, const std::array<std::uint8_t, 16>& local,
|
||||
const std::array<std::uint8_t, 16>& remote) {
|
||||
std::array<std::uint8_t, 0x140> records;
|
||||
@@ -1897,6 +1918,7 @@ int main() {
|
||||
}
|
||||
CheckDatagramDisconnect();
|
||||
CheckCloseKernelSocket();
|
||||
CheckKernelSocketGetOption();
|
||||
CheckSockInfo();
|
||||
CheckSockInfo6();
|
||||
|
||||
|
||||
Reference in new issue
Block a user