diff options
Diffstat (limited to 'src/core/hle/service/nwm/uds_data.cpp')
-rw-r--r-- | src/core/hle/service/nwm/uds_data.cpp | 103 |
1 files changed, 99 insertions, 4 deletions
diff --git a/src/core/hle/service/nwm/uds_data.cpp b/src/core/hle/service/nwm/uds_data.cpp index 8c6742dba..4b389710f 100644 --- a/src/core/hle/service/nwm/uds_data.cpp +++ b/src/core/hle/service/nwm/uds_data.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> #include <cstring> #include <cryptopp/aes.h> #include <cryptopp/ccm.h> @@ -197,7 +198,7 @@ static std::vector<u8> DecryptDataFrame(const std::vector<u8>& encrypted_payload df.ChannelMessageEnd(CryptoPP::DEFAULT_CHANNEL); df.SetRetrievalChannel(CryptoPP::DEFAULT_CHANNEL); - int size = df.MaxRetrievable(); + size_t size = df.MaxRetrievable(); std::vector<u8> pdata(size); df.Get(pdata.data(), size); @@ -251,7 +252,7 @@ static std::vector<u8> EncryptDataFrame(const std::vector<u8>& payload, df.SetRetrievalChannel(CryptoPP::DEFAULT_CHANNEL); - int size = df.MaxRetrievable(); + size_t size = df.MaxRetrievable(); std::vector<u8> cipher(size); df.Get(cipher.data(), size); @@ -266,13 +267,107 @@ static std::vector<u8> EncryptDataFrame(const std::vector<u8>& payload, std::vector<u8> GenerateDataPayload(const std::vector<u8>& data, u8 channel, u16 dest_node, u16 src_node, u16 sequence_number) { std::vector<u8> buffer = GenerateLLCHeader(EtherType::SecureData); - std::vector<u8> securedata_header = - GenerateSecureDataHeader(data.size(), channel, dest_node, src_node, sequence_number); + std::vector<u8> securedata_header = GenerateSecureDataHeader( + static_cast<u16>(data.size()), channel, dest_node, src_node, sequence_number); buffer.insert(buffer.end(), securedata_header.begin(), securedata_header.end()); buffer.insert(buffer.end(), data.begin(), data.end()); return buffer; } +std::vector<u8> GenerateEAPoLStartFrame(u16 association_id, const NodeInfo& node_info) { + EAPoLStartPacket eapol_start{}; + eapol_start.association_id = association_id; + eapol_start.node.friend_code_seed = node_info.friend_code_seed; + + std::copy(node_info.username.begin(), node_info.username.end(), + eapol_start.node.username.begin()); + + // Note: The network_node_id and unknown bytes seem to be uninitialized in the NWM module. + // TODO(B3N30): The last 8 bytes seem to have a fixed value of 07 88 15 00 04 e9 13 00 in + // EAPoL-Start packets from different 3DSs to the same host during a Super Smash Bros. 4 game. + // Find out what that means. + + std::vector<u8> eapol_buffer(sizeof(EAPoLStartPacket)); + std::memcpy(eapol_buffer.data(), &eapol_start, sizeof(eapol_start)); + + std::vector<u8> buffer = GenerateLLCHeader(EtherType::EAPoL); + buffer.insert(buffer.end(), eapol_buffer.begin(), eapol_buffer.end()); + return buffer; +} + +EtherType GetFrameEtherType(const std::vector<u8>& frame) { + LLCHeader header; + std::memcpy(&header, frame.data(), sizeof(header)); + + u16 ethertype = header.protocol; + return static_cast<EtherType>(ethertype); +} + +u16 GetEAPoLFrameType(const std::vector<u8>& frame) { + // Ignore the LLC header + u16_be eapol_type; + std::memcpy(&eapol_type, frame.data() + sizeof(LLCHeader), sizeof(eapol_type)); + return eapol_type; +} + +NodeInfo DeserializeNodeInfoFromFrame(const std::vector<u8>& frame) { + EAPoLStartPacket eapol_start; + + // Skip the LLC header + std::memcpy(&eapol_start, frame.data() + sizeof(LLCHeader), sizeof(eapol_start)); + + NodeInfo node{}; + node.friend_code_seed = eapol_start.node.friend_code_seed; + + std::copy(eapol_start.node.username.begin(), eapol_start.node.username.end(), + node.username.begin()); + + return node; +} + +NodeInfo DeserializeNodeInfo(const EAPoLNodeInfo& node) { + NodeInfo node_info{}; + node_info.friend_code_seed = node.friend_code_seed; + node_info.network_node_id = node.network_node_id; + + std::copy(node.username.begin(), node.username.end(), node_info.username.begin()); + + return node_info; +} + +std::vector<u8> GenerateEAPoLLogoffFrame(const MacAddress& mac_address, u16 network_node_id, + const NodeList& nodes, u8 max_nodes, u8 total_nodes) { + EAPoLLogoffPacket eapol_logoff{}; + eapol_logoff.assigned_node_id = network_node_id; + eapol_logoff.connected_nodes = total_nodes; + eapol_logoff.max_nodes = max_nodes; + + for (size_t index = 0; index < total_nodes; ++index) { + const auto& node_info = nodes[index]; + auto& node = eapol_logoff.nodes[index]; + + node.friend_code_seed = node_info.friend_code_seed; + node.network_node_id = node_info.network_node_id; + + std::copy(node_info.username.begin(), node_info.username.end(), node.username.begin()); + } + + std::vector<u8> eapol_buffer(sizeof(EAPoLLogoffPacket)); + std::memcpy(eapol_buffer.data(), &eapol_logoff, sizeof(eapol_logoff)); + + std::vector<u8> buffer = GenerateLLCHeader(EtherType::EAPoL); + buffer.insert(buffer.end(), eapol_buffer.begin(), eapol_buffer.end()); + return buffer; +} + +EAPoLLogoffPacket ParseEAPoLLogoffFrame(const std::vector<u8>& frame) { + EAPoLLogoffPacket eapol_logoff; + + // Skip the LLC header + std::memcpy(&eapol_logoff, frame.data() + sizeof(LLCHeader), sizeof(eapol_logoff)); + return eapol_logoff; +} + } // namespace NWM } // namespace Service |