mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-07 13:39:55 +00:00
fix(libSceNetCtl): read the STUN OTHER-ADDRESS attribute from 0x802c per RFC 5780
STUN_ATTR_OTHER_ADDRESS was 0x802b. RFC 5780 section 9.1 registers 0x802b as RESPONSE-ORIGIN and 0x802c as OTHER-ADDRESS (section 7.4 notes that OTHER-ADDRESS reuses the 0x0005 number of RFC 3489 CHANGED-ADDRESS, which stays accepted). ParseStunBindingResponse therefore ignored the alternate server a binding response advertised in OTHER-ADDRESS, and decoded a RESPONSE-ORIGIN (the address the response was sent from) as the alternate server. GuestNetCtl.cpp gains two cases: a response carrying OTHER-ADDRESS (0x802c) makes sceNetCtlGetNatInfo probe the advertised server, and a response carrying RESPONSE-ORIGIN (0x802b) makes it probe nothing.
This commit is contained in:
1 parent
ab213704ee
commit
6ddd82ff60
2 files changed
+44
-3
No files matched your search
@@ -70,7 +70,7 @@ static constexpr std::uint16_t STUN_ATTR_MAPPED_ADDRESS = 0x0001;
|
||||
static constexpr std::uint16_t STUN_ATTR_CHANGED_ADDRESS = 0x0005;
|
||||
static constexpr std::uint16_t STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020;
|
||||
static constexpr std::uint16_t STUN_ATTR_XOR_MAPPED_ADDRESS_LEGACY = 0x8020;
|
||||
static constexpr std::uint16_t STUN_ATTR_OTHER_ADDRESS = 0x802b;
|
||||
static constexpr std::uint16_t STUN_ATTR_OTHER_ADDRESS = 0x802c;
|
||||
static constexpr std::size_t STUN_HEADER_SIZE = 20;
|
||||
static constexpr std::size_t STUN_TRANSACTION_ID_SIZE = 12;
|
||||
static constexpr int STUN_DEFAULT_TIMEOUT_MS = 300;
|
||||
|
||||
@@ -418,7 +418,7 @@ StunTxId ReceiveStunBindingRequest(TestSocket serverSocket, sockaddr_in& client)
|
||||
return txId;
|
||||
}
|
||||
|
||||
void SendStunBindingResponse(TestSocket serverSocket, const sockaddr_in& client, const StunTxId& txId, std::uint32_t mappedAddr, std::uint16_t mappedHostPort, bool xorMapped, const sockaddr_in* otherServer = nullptr) {
|
||||
void SendStunBindingResponse(TestSocket serverSocket, const sockaddr_in& client, const StunTxId& txId, std::uint32_t mappedAddr, std::uint16_t mappedHostPort, bool xorMapped, const sockaddr_in* otherServer = nullptr, std::uint16_t otherAttr = 0x0005) {
|
||||
const std::uint16_t effectivePort = mappedHostPort != 0 ? mappedHostPort : ntohs(client.sin_port);
|
||||
const std::uint32_t effectiveAddr = mappedAddr != 0 ? mappedAddr : client.sin_addr.s_addr;
|
||||
std::vector<std::uint8_t> response(20, 0);
|
||||
@@ -429,7 +429,7 @@ void SendStunBindingResponse(TestSocket serverSocket, const sockaddr_in& client,
|
||||
std::memcpy(response.data() + 8, txId.data(), txId.size());
|
||||
AppendStunAddressAttribute(response, xorMapped ? 0x0020 : 0x0001, effectiveAddr, effectivePort, xorMapped);
|
||||
if (otherServer) {
|
||||
AppendStunAddressAttribute(response, 0x0005, otherServer->sin_addr.s_addr, ntohs(otherServer->sin_port), false);
|
||||
AppendStunAddressAttribute(response, otherAttr, otherServer->sin_addr.s_addr, ntohs(otherServer->sin_port), false);
|
||||
}
|
||||
const auto attrLen = static_cast<std::uint16_t>(response.size() - 20);
|
||||
response[2] = static_cast<std::uint8_t>(attrLen >> 8);
|
||||
@@ -578,6 +578,47 @@ void CheckNatDiscovery(in_addr address) {
|
||||
Require(natInfo.nat_type == 3);
|
||||
Require(natInfo.mapped_addr == externalIp);
|
||||
|
||||
constexpr std::uint16_t kStunResponseOrigin = 0x802b;
|
||||
constexpr std::uint16_t kStunOtherAddress = 0x802c;
|
||||
|
||||
NetCtlSetStunServers_nid_no_patch(&server1Addr, 1, 1000);
|
||||
StunTxId otherAddressTx1{};
|
||||
StunTxId otherAddressTx2{};
|
||||
bool otherAddressProbed = false;
|
||||
std::thread otherAddressWorker([&] {
|
||||
sockaddr_in firstClient{};
|
||||
otherAddressTx1 = ReceiveStunBindingRequest(server1, firstClient);
|
||||
SendStunBindingResponse(server1, firstClient, otherAddressTx1, externalIp, 54321, false, &server2Addr, kStunOtherAddress);
|
||||
if (WaitReadable(server2, 1500)) {
|
||||
otherAddressProbed = true;
|
||||
sockaddr_in secondClient{};
|
||||
otherAddressTx2 = ReceiveStunBindingRequest(server2, secondClient);
|
||||
SendStunBindingResponse(server2, secondClient, otherAddressTx2, externalIp, 54322, false);
|
||||
}
|
||||
});
|
||||
natInfo = {sizeof(natInfo), 99, 99, 0};
|
||||
Require(sceNetCtlGetNatInfo(&natInfo) == 0);
|
||||
otherAddressWorker.join();
|
||||
Require(otherAddressProbed);
|
||||
RecordUniqueTransactionId(seenIds, otherAddressTx1);
|
||||
RecordUniqueTransactionId(seenIds, otherAddressTx2);
|
||||
Require(natInfo.stun_status == 2);
|
||||
Require(natInfo.nat_type == 3);
|
||||
Require(natInfo.mapped_addr == externalIp);
|
||||
|
||||
NetCtlSetStunServers_nid_no_patch(&server1Addr, 1, 300);
|
||||
StunTxId responseOriginTx{};
|
||||
std::thread responseOriginWorker([&] {
|
||||
sockaddr_in client{};
|
||||
responseOriginTx = ReceiveStunBindingRequest(server1, client);
|
||||
SendStunBindingResponse(server1, client, responseOriginTx, externalIp, 54321, false, &server2Addr, kStunResponseOrigin);
|
||||
});
|
||||
natInfo = {sizeof(natInfo), 99, 99, 0};
|
||||
Require(sceNetCtlGetNatInfo(&natInfo) == 0);
|
||||
responseOriginWorker.join();
|
||||
RecordUniqueTransactionId(seenIds, responseOriginTx);
|
||||
Require(!WaitReadable(server2, 300));
|
||||
|
||||
NetCtlSetStunServers_nid_no_patch(nullptr, 0, 0);
|
||||
CloseTestSocket(server1);
|
||||
CloseTestSocket(server2);
|
||||
|
||||
Reference in new issue
Block a user