summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/nwm/uds_data.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/nwm/uds_data.cpp')
-rw-r--r--src/core/hle/service/nwm/uds_data.cpp103
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