mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-10-11 21:49:59 +00:00
* p2p crypto schema * adding p2p keyring * p2p framing and testing * fixups * test fix * missing definations * implementation of host functions * tcp/transport of p2p packets * improvements in binding * guest_net ,improvements and test cases * all mighty clang * fixing macOS tests failures * misc * net_rewrite : net_errors , types and translation schemas * updated fixed chunks transfer on windows * bye bye old net * small updates for the new net * settings and tests * net lib first draft * allow more than 1 P2P instances on from same pc * improved shadnet replies * possible fix for jojo * cleanup * move net files to libaries/net * fixed macOS tests * mighty clang * fixed cmakelists * don't cosume inviation event on client (test code) * fix macOS tests * Large multi-file rework for Signaling and Matching2 network handling / optimization. Consolidates Matching2-signaling and signaling to one process (signaling_handler) General cleanup and consolidation of matching2 context management > nphandler Removal of a lot SIgnaling overall structure cleanup. Matching2: added get and set roommemberdatainternal and the proper type / shadnet call / request / reply. Consolidated signaling/matching2 typedefs to np_types2 Utilized Codex as a reviewer and for general cleanup. * all mighty clang * fixed member attributes * fixed MAPPED address for matching signaling * Fixed sceNpMatching2SignalingGetLocalNetInfo * fixups on net core/library based on fw * improved errno * spilt p2p to net_p2p * some cleanups * fix for localinfo * clang * fix up * cleanups * cleanups * added KernelFstat * fixed fstat * one more fix for fstat... * cleanup old deprecated code * cleanup * General logging cleanup across NP changes. Thanks Stephen! * cleanup based on stephen's suggestions * fixup * fixing tests * blah * fixup * improve memory pools * cleaunp * force https disable option * clang * @stephen's fixes * added network field in settings and ported old network ones --------- Co-authored-by: Metr1k <[email protected]>
166 lines
6.5 KiB
C++
166 lines
6.5 KiB
C++
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
// The P2P key ioctl (sceNetIoctl on P2P sockets): how the NP libraries install keys and the
|
|
// communication ID. Tested on a Keyring directly, without sockets.
|
|
|
|
#include <array>
|
|
#include <cstring>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "core/libraries/net/net_error.h"
|
|
#include "core/libraries/net/net_p2p_ioctl.h"
|
|
#include "core/libraries/net/net_types.h"
|
|
#include "core/net/p2p_codec.h"
|
|
|
|
using namespace Libraries::Net;
|
|
namespace P2P = Core::Net::P2P;
|
|
|
|
namespace {
|
|
|
|
constexpr u16 NpPort = 0x4a0e; // 3658 in network byte order
|
|
|
|
// ioctl numbers: group 'P' (0x50), 36-byte argument written by the caller (IOC_IN).
|
|
constexpr u64 SetDefault = 0x802450c9;
|
|
constexpr u64 GetDefault = 0xc02450ca;
|
|
constexpr u64 AddKey = 0x802450cb;
|
|
constexpr u64 ReleaseKey = 0x802450cc;
|
|
constexpr u64 SetWildcard = 0x802450cd;
|
|
constexpr u64 GetWildcard = 0xc02450ce;
|
|
constexpr u64 GetNpPort = 0xc00250cf;
|
|
constexpr u64 RemoveById = 0x802450c8;
|
|
constexpr u64 SetCommunicationIdCmd = 0x801050d8;
|
|
constexpr u64 ClearCommunicationId = 0x200050d9;
|
|
|
|
/// The 36-byte argument: IPv4 P2P sockaddr, key value, local port, flags, id.
|
|
struct Record {
|
|
std::array<u8, 36> bytes{};
|
|
|
|
Record(const char* ip, u16 port, u8 key_fill, u8 id, u16 local_port = 0) {
|
|
OrbisNetSockaddrIn in{};
|
|
in.sin_len = sizeof(in);
|
|
in.sin_family = ORBIS_NET_AF_INET;
|
|
in.sin_port = htons(port);
|
|
inet_pton(AF_INET, ip, &in.sin_addr);
|
|
std::memcpy(bytes.data(), &in, sizeof(in));
|
|
std::memset(bytes.data() + 16, key_fill, 16);
|
|
std::memcpy(bytes.data() + 32, &local_port, 2);
|
|
bytes[34] = 0x01; // flags
|
|
bytes[35] = id;
|
|
}
|
|
void* data() {
|
|
return bytes.data();
|
|
}
|
|
};
|
|
|
|
P2P::P2PKey Key(u8 fill) {
|
|
P2P::P2PKey key;
|
|
key.value.fill(fill);
|
|
return key;
|
|
}
|
|
|
|
const P2P::Endpoint Peer = P2P::Endpoint::IPv4("198.51.100.4", 3658);
|
|
|
|
TEST(NetLibP2PIoctl, CommunicationIdIsDerived) {
|
|
P2P::Keyring keys;
|
|
std::array<u8, 16> value;
|
|
for (u8 i = 0; i < 16; ++i) {
|
|
value[i] = i;
|
|
}
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, SetCommunicationIdCmd, value.data()), 0);
|
|
// HMAC-SHA1(key = value, message = "")[0..4], from an independent implementation (Python).
|
|
EXPECT_EQ(keys.GetCommunicationId(), (P2P::CommunicationId{0x54, 0x33, 0x12, 0x2f}));
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, ClearCommunicationId, nullptr), 0);
|
|
EXPECT_FALSE(keys.GetCommunicationId());
|
|
}
|
|
|
|
TEST(NetLibP2PIoctl, PeerKeysAreReferenceCounted) {
|
|
P2P::Keyring keys;
|
|
Record record("198.51.100.4", 3658, 0x11, 7);
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, AddKey, record.data()), 0);
|
|
const auto entry = keys.FindPeerEntry(Peer);
|
|
ASSERT_TRUE(entry);
|
|
EXPECT_EQ(entry->key, Key(0x11));
|
|
EXPECT_EQ(entry->id, 7);
|
|
EXPECT_EQ(entry->flags, 1);
|
|
EXPECT_EQ(entry->local_port, NpPort); // 0 in the record means the NP port
|
|
|
|
// Installed twice, so it takes two releases to go away.
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, AddKey, record.data()), 0);
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, ReleaseKey, record.data()), 0);
|
|
EXPECT_TRUE(keys.FindPeerEntry(Peer));
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, ReleaseKey, record.data()), 0);
|
|
EXPECT_FALSE(keys.FindPeerEntry(Peer));
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, ReleaseKey, record.data()), ORBIS_NET_ENOENT);
|
|
|
|
// A release must name the same key value and id.
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, AddKey, record.data()), 0);
|
|
Record wrong_id("198.51.100.4", 3658, 0x11, 8);
|
|
Record wrong_key("198.51.100.4", 3658, 0x22, 7);
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, ReleaseKey, wrong_id.data()), ORBIS_NET_ENOENT);
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, ReleaseKey, wrong_key.data()), ORBIS_NET_ENOENT);
|
|
|
|
// A different value replaces the key; an explicit local port is kept.
|
|
Record other("198.51.100.4", 3658, 0x33, 7, 0x1234);
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, AddKey, other.data()), 0);
|
|
EXPECT_EQ(keys.FindPeerEntry(Peer)->key, Key(0x33));
|
|
EXPECT_EQ(keys.FindPeerEntry(Peer)->local_port, 0x1234);
|
|
}
|
|
|
|
TEST(NetLibP2PIoctl, RemoveKeysById) {
|
|
P2P::Keyring keys;
|
|
Record a("198.51.100.4", 3658, 0x11, 5);
|
|
Record b("198.51.100.5", 3658, 0x22, 5);
|
|
Record c("198.51.100.6", 3658, 0x33, 6);
|
|
for (auto* r : {&a, &b, &c}) {
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, AddKey, r->data()), 0);
|
|
}
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, RemoveById, a.data()), 0); // id 5
|
|
EXPECT_FALSE(keys.FindPeerEntry(P2P::Endpoint::IPv4("198.51.100.4", 3658)));
|
|
EXPECT_FALSE(keys.FindPeerEntry(P2P::Endpoint::IPv4("198.51.100.5", 3658)));
|
|
EXPECT_TRUE(keys.FindPeerEntry(P2P::Endpoint::IPv4("198.51.100.6", 3658)));
|
|
}
|
|
|
|
TEST(NetLibP2PIoctl, DefaultAndWildcardKeys) {
|
|
P2P::Keyring keys;
|
|
Record default_key("0.0.0.0", 0, 0x44, 1);
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, SetDefault, default_key.data()), 0);
|
|
EXPECT_EQ(keys.Find(Peer), Key(0x44)); // falls back to the default key
|
|
EXPECT_EQ(keys.FindPeerEntry(P2P::Endpoint::IPv4("127.0.0.1", 3658))->key, Key(0x44));
|
|
|
|
Record out("0.0.0.0", 0, 0x00, 0);
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, GetDefault, out.data()), 0);
|
|
EXPECT_EQ(out.bytes[16], 0x44);
|
|
EXPECT_EQ(out.bytes[31], 0x44);
|
|
|
|
// The wildcard key wins over the default key; reading it back works too.
|
|
Record out_wild("0.0.0.0", 0, 0xee, 0);
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, GetWildcard, out_wild.data()), 0);
|
|
EXPECT_EQ(out_wild.bytes[16], 0x00); // none yet: zeros
|
|
Record wildcard("0.0.0.0", 0, 0x55, 1);
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, SetWildcard, wildcard.data()), 0);
|
|
EXPECT_EQ(keys.Find(Peer), Key(0x55));
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, GetWildcard, out_wild.data()), 0);
|
|
EXPECT_EQ(out_wild.bytes[16], 0x55);
|
|
}
|
|
|
|
TEST(NetLibP2PIoctl, NpPortAndErrors) {
|
|
P2P::Keyring keys;
|
|
u16 port = 0;
|
|
ASSERT_EQ(P2PKeyIoctl(keys, NpPort, GetNpPort, &port), 0);
|
|
EXPECT_EQ(port, NpPort);
|
|
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, 0x8004667e /* FIONBIO */, &port), ORBIS_NET_EINVAL);
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, AddKey, nullptr), ORBIS_NET_EFAULT);
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, 0x200050c8, nullptr), 0); // the no-op command
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, 0x802450ff, &port), ORBIS_NET_EINVAL);
|
|
|
|
// Adding a key needs an IPv4 P2P sockaddr.
|
|
Record bad_family("198.51.100.4", 3658, 0x11, 7);
|
|
bad_family.bytes[1] = ORBIS_NET_AF_INET6;
|
|
EXPECT_EQ(P2PKeyIoctl(keys, NpPort, AddKey, bad_family.data()), ORBIS_NET_EINVAL);
|
|
}
|
|
|
|
} // namespace
|