summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/nwm
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/nwm')
-rw-r--r--src/core/hle/service/nwm/nwm.cpp28
-rw-r--r--src/core/hle/service/nwm/nwm.h14
-rw-r--r--src/core/hle/service/nwm/nwm_cec.cpp19
-rw-r--r--src/core/hle/service/nwm/nwm_cec.h22
-rw-r--r--src/core/hle/service/nwm/nwm_ext.cpp19
-rw-r--r--src/core/hle/service/nwm/nwm_ext.h22
-rw-r--r--src/core/hle/service/nwm/nwm_inf.cpp21
-rw-r--r--src/core/hle/service/nwm/nwm_inf.h22
-rw-r--r--src/core/hle/service/nwm/nwm_sap.cpp20
-rw-r--r--src/core/hle/service/nwm/nwm_sap.h22
-rw-r--r--src/core/hle/service/nwm/nwm_soc.cpp20
-rw-r--r--src/core/hle/service/nwm/nwm_soc.h22
-rw-r--r--src/core/hle/service/nwm/nwm_tst.cpp20
-rw-r--r--src/core/hle/service/nwm/nwm_tst.h22
-rw-r--r--src/core/hle/service/nwm/nwm_uds.cpp1035
-rw-r--r--src/core/hle/service/nwm/nwm_uds.h111
-rw-r--r--src/core/hle/service/nwm/uds_beacon.cpp329
-rw-r--r--src/core/hle/service/nwm/uds_beacon.h140
-rw-r--r--src/core/hle/service/nwm/uds_connection.cpp88
-rw-r--r--src/core/hle/service/nwm/uds_connection.h56
-rw-r--r--src/core/hle/service/nwm/uds_data.cpp373
-rw-r--r--src/core/hle/service/nwm/uds_data.h164
22 files changed, 0 insertions, 2589 deletions
diff --git a/src/core/hle/service/nwm/nwm.cpp b/src/core/hle/service/nwm/nwm.cpp
deleted file mode 100644
index 9f1994dc3..000000000
--- a/src/core/hle/service/nwm/nwm.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/nwm/nwm.h"
-#include "core/hle/service/nwm/nwm_cec.h"
-#include "core/hle/service/nwm/nwm_ext.h"
-#include "core/hle/service/nwm/nwm_inf.h"
-#include "core/hle/service/nwm/nwm_sap.h"
-#include "core/hle/service/nwm/nwm_soc.h"
-#include "core/hle/service/nwm/nwm_tst.h"
-#include "core/hle/service/nwm/nwm_uds.h"
-
-namespace Service {
-namespace NWM {
-
-void Init() {
- AddService(new NWM_CEC);
- AddService(new NWM_EXT);
- AddService(new NWM_INF);
- AddService(new NWM_SAP);
- AddService(new NWM_SOC);
- AddService(new NWM_TST);
- AddService(new NWM_UDS);
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm.h b/src/core/hle/service/nwm/nwm.h
deleted file mode 100644
index 6926b29a6..000000000
--- a/src/core/hle/service/nwm/nwm.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-namespace Service {
-namespace NWM {
-
-/// Initialize all NWM services
-void Init();
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_cec.cpp b/src/core/hle/service/nwm/nwm_cec.cpp
deleted file mode 100644
index 7f03987df..000000000
--- a/src/core/hle/service/nwm/nwm_cec.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/nwm/nwm_cec.h"
-
-namespace Service {
-namespace NWM {
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x000D0082, nullptr, "SendProbeRequest"},
-};
-
-NWM_CEC::NWM_CEC() {
- Register(FunctionTable);
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_cec.h b/src/core/hle/service/nwm/nwm_cec.h
deleted file mode 100644
index 07b6addb5..000000000
--- a/src/core/hle/service/nwm/nwm_cec.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace NWM {
-
-class NWM_CEC final : public Interface {
-public:
- NWM_CEC();
-
- std::string GetPortName() const override {
- return "nwm::CEC";
- }
-};
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_ext.cpp b/src/core/hle/service/nwm/nwm_ext.cpp
deleted file mode 100644
index 605640a13..000000000
--- a/src/core/hle/service/nwm/nwm_ext.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/nwm/nwm_ext.h"
-
-namespace Service {
-namespace NWM {
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x00080040, nullptr, "ControlWirelessEnabled"},
-};
-
-NWM_EXT::NWM_EXT() {
- Register(FunctionTable);
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_ext.h b/src/core/hle/service/nwm/nwm_ext.h
deleted file mode 100644
index 51d39d9ea..000000000
--- a/src/core/hle/service/nwm/nwm_ext.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace NWM {
-
-class NWM_EXT final : public Interface {
-public:
- NWM_EXT();
-
- std::string GetPortName() const override {
- return "nwm::EXT";
- }
-};
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_inf.cpp b/src/core/hle/service/nwm/nwm_inf.cpp
deleted file mode 100644
index c8470589b..000000000
--- a/src/core/hle/service/nwm/nwm_inf.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/nwm/nwm_inf.h"
-
-namespace Service {
-namespace NWM {
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x000603C4, nullptr, "RecvBeaconBroadcastData"},
- {0x00070742, nullptr, "ConnectToEncryptedAP"},
- {0x00080302, nullptr, "ConnectToAP"},
-};
-
-NWM_INF::NWM_INF() {
- Register(FunctionTable);
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_inf.h b/src/core/hle/service/nwm/nwm_inf.h
deleted file mode 100644
index 0043d769c..000000000
--- a/src/core/hle/service/nwm/nwm_inf.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace NWM {
-
-class NWM_INF final : public Interface {
-public:
- NWM_INF();
-
- std::string GetPortName() const override {
- return "nwm::INF";
- }
-};
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_sap.cpp b/src/core/hle/service/nwm/nwm_sap.cpp
deleted file mode 100644
index fd29ed761..000000000
--- a/src/core/hle/service/nwm/nwm_sap.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/nwm/nwm_sap.h"
-
-namespace Service {
-namespace NWM {
-
-/*
-const Interface::FunctionInfo FunctionTable[] = {
-};
-*/
-
-NWM_SAP::NWM_SAP() {
- // Register(FunctionTable);
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_sap.h b/src/core/hle/service/nwm/nwm_sap.h
deleted file mode 100644
index f692e06d4..000000000
--- a/src/core/hle/service/nwm/nwm_sap.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace NWM {
-
-class NWM_SAP final : public Interface {
-public:
- NWM_SAP();
-
- std::string GetPortName() const override {
- return "nwm::SAP";
- }
-};
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_soc.cpp b/src/core/hle/service/nwm/nwm_soc.cpp
deleted file mode 100644
index fdffcb925..000000000
--- a/src/core/hle/service/nwm/nwm_soc.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/nwm/nwm_soc.h"
-
-namespace Service {
-namespace NWM {
-
-/*
-const Interface::FunctionInfo FunctionTable[] = {
-};
-*/
-
-NWM_SOC::NWM_SOC() {
- // Register(FunctionTable);
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_soc.h b/src/core/hle/service/nwm/nwm_soc.h
deleted file mode 100644
index 594941d7e..000000000
--- a/src/core/hle/service/nwm/nwm_soc.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace NWM {
-
-class NWM_SOC final : public Interface {
-public:
- NWM_SOC();
-
- std::string GetPortName() const override {
- return "nwm::SOC";
- }
-};
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_tst.cpp b/src/core/hle/service/nwm/nwm_tst.cpp
deleted file mode 100644
index 5f292e5db..000000000
--- a/src/core/hle/service/nwm/nwm_tst.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/nwm/nwm_tst.h"
-
-namespace Service {
-namespace NWM {
-
-/*
-const Interface::FunctionInfo FunctionTable[] = {
-};
-*/
-
-NWM_TST::NWM_TST() {
- // Register(FunctionTable);
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_tst.h b/src/core/hle/service/nwm/nwm_tst.h
deleted file mode 100644
index 8deca3216..000000000
--- a/src/core/hle/service/nwm/nwm_tst.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace NWM {
-
-class NWM_TST final : public Interface {
-public:
- NWM_TST();
-
- std::string GetPortName() const override {
- return "nwm::TST";
- }
-};
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp
deleted file mode 100644
index 87a6b0eca..000000000
--- a/src/core/hle/service/nwm/nwm_uds.cpp
+++ /dev/null
@@ -1,1035 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <array>
-#include <cstring>
-#include <list>
-#include <mutex>
-#include <unordered_map>
-#include <vector>
-#include "common/common_types.h"
-#include "common/logging/log.h"
-#include "core/core_timing.h"
-#include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/lock.h"
-#include "core/hle/result.h"
-#include "core/hle/service/nwm/nwm_uds.h"
-#include "core/hle/service/nwm/uds_beacon.h"
-#include "core/hle/service/nwm/uds_connection.h"
-#include "core/hle/service/nwm/uds_data.h"
-#include "core/memory.h"
-#include "network/network.h"
-
-namespace Service {
-namespace NWM {
-
-// Event that is signaled every time the connection status changes.
-static Kernel::SharedPtr<Kernel::Event> connection_status_event;
-
-// Shared memory provided by the application to store the receive buffer.
-// This is not currently used.
-static Kernel::SharedPtr<Kernel::SharedMemory> recv_buffer_memory;
-
-// Connection status of this 3DS.
-static ConnectionStatus connection_status{};
-
-/* Node information about the current network.
- * The amount of elements in this vector is always the maximum number
- * of nodes specified in the network configuration.
- * The first node is always the host.
- */
-static NodeList node_info;
-
-// Node information about our own system.
-static NodeInfo current_node;
-
-// Mapping of bind node ids to their respective events.
-static std::unordered_map<u32, Kernel::SharedPtr<Kernel::Event>> bind_node_events;
-
-// The WiFi network channel that the network is currently on.
-// Since we're not actually interacting with physical radio waves, this is just a dummy value.
-static u8 network_channel = DefaultNetworkChannel;
-
-// Information about the network that we're currently connected to.
-static NetworkInfo network_info;
-
-// Event that will generate and send the 802.11 beacon frames.
-static int beacon_broadcast_event;
-
-// Mutex to synchronize access to the connection status between the emulation thread and the
-// network thread.
-static std::mutex connection_status_mutex;
-
-// Mutex to synchronize access to the list of received beacons between the emulation thread and the
-// network thread.
-static std::mutex beacon_mutex;
-
-// Number of beacons to store before we start dropping the old ones.
-// TODO(Subv): Find a more accurate value for this limit.
-constexpr size_t MaxBeaconFrames = 15;
-
-// List of the last <MaxBeaconFrames> beacons received from the network.
-static std::list<Network::WifiPacket> received_beacons;
-
-/**
- * Returns a list of received 802.11 beacon frames from the specified sender since the last call.
- */
-std::list<Network::WifiPacket> GetReceivedBeacons(const MacAddress& sender) {
- std::lock_guard<std::mutex> lock(beacon_mutex);
- if (sender != Network::BroadcastMac) {
- std::list<Network::WifiPacket> filtered_list;
- const auto beacon = std::find_if(received_beacons.begin(), received_beacons.end(),
- [&sender](const Network::WifiPacket& packet) {
- return packet.transmitter_address == sender;
- });
- if (beacon != received_beacons.end()) {
- filtered_list.push_back(*beacon);
- // TODO(B3N30): Check if the complete deque is cleared or just the fetched entries
- received_beacons.erase(beacon);
- }
- return filtered_list;
- }
- return std::move(received_beacons);
-}
-
-/// Sends a WifiPacket to the room we're currently connected to.
-void SendPacket(Network::WifiPacket& packet) {
- // TODO(Subv): Implement.
-}
-
-/*
- * Returns an available index in the nodes array for the
- * currently-hosted UDS network.
- */
-static u16 GetNextAvailableNodeId() {
- for (u16 index = 0; index < connection_status.max_nodes; ++index) {
- if ((connection_status.node_bitmask & (1 << index)) == 0)
- return index;
- }
-
- // Any connection attempts to an already full network should have been refused.
- ASSERT_MSG(false, "No available connection slots in the network");
-}
-
-// Inserts the received beacon frame in the beacon queue and removes any older beacons if the size
-// limit is exceeded.
-void HandleBeaconFrame(const Network::WifiPacket& packet) {
- std::lock_guard<std::mutex> lock(beacon_mutex);
- const auto unique_beacon =
- std::find_if(received_beacons.begin(), received_beacons.end(),
- [&packet](const Network::WifiPacket& new_packet) {
- return new_packet.transmitter_address == packet.transmitter_address;
- });
- if (unique_beacon != received_beacons.end()) {
- // We already have a beacon from the same mac in the deque, remove the old one;
- received_beacons.erase(unique_beacon);
- }
-
- received_beacons.emplace_back(packet);
-
- // Discard old beacons if the buffer is full.
- if (received_beacons.size() > MaxBeaconFrames)
- received_beacons.pop_front();
-}
-
-void HandleAssociationResponseFrame(const Network::WifiPacket& packet) {
- auto assoc_result = GetAssociationResult(packet.data);
-
- ASSERT_MSG(std::get<AssocStatus>(assoc_result) == AssocStatus::Successful,
- "Could not join network");
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- ASSERT(connection_status.status == static_cast<u32>(NetworkStatus::Connecting));
- }
-
- // Send the EAPoL-Start packet to the server.
- using Network::WifiPacket;
- WifiPacket eapol_start;
- eapol_start.channel = network_channel;
- eapol_start.data = GenerateEAPoLStartFrame(std::get<u16>(assoc_result), current_node);
- // TODO(B3N30): Encrypt the packet.
- eapol_start.destination_address = packet.transmitter_address;
- eapol_start.type = WifiPacket::PacketType::Data;
-
- SendPacket(eapol_start);
-}
-
-static void HandleEAPoLPacket(const Network::WifiPacket& packet) {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
-
- if (GetEAPoLFrameType(packet.data) == EAPoLStartMagic) {
- if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
- LOG_DEBUG(Service_NWM, "Connection sequence aborted, because connection status is %u",
- connection_status.status);
- return;
- }
-
- auto node = DeserializeNodeInfoFromFrame(packet.data);
-
- if (connection_status.max_nodes == connection_status.total_nodes) {
- // Reject connection attempt
- LOG_ERROR(Service_NWM, "Reached maximum nodes, but reject packet wasn't sent.");
- // TODO(B3N30): Figure out what packet is sent here
- return;
- }
-
- // Get an unused network node id
- u16 node_id = GetNextAvailableNodeId();
- node.network_node_id = node_id + 1;
-
- connection_status.node_bitmask |= 1 << node_id;
- connection_status.changed_nodes |= 1 << node_id;
- connection_status.nodes[node_id] = node.network_node_id;
- connection_status.total_nodes++;
-
- u8 current_nodes = network_info.total_nodes;
- node_info[current_nodes] = node;
-
- network_info.total_nodes++;
-
- // Send the EAPoL-Logoff packet.
- using Network::WifiPacket;
- WifiPacket eapol_logoff;
- eapol_logoff.channel = network_channel;
- eapol_logoff.data =
- GenerateEAPoLLogoffFrame(packet.transmitter_address, node.network_node_id, node_info,
- network_info.max_nodes, network_info.total_nodes);
- // TODO(Subv): Encrypt the packet.
- eapol_logoff.destination_address = packet.transmitter_address;
- eapol_logoff.type = WifiPacket::PacketType::Data;
-
- SendPacket(eapol_logoff);
- // TODO(B3N30): Broadcast updated node list
- // The 3ds does this presumably to support spectators.
- std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
- connection_status_event->Signal();
- } else {
- if (connection_status.status != static_cast<u32>(NetworkStatus::NotConnected)) {
- LOG_DEBUG(Service_NWM, "Connection sequence aborted, because connection status is %u",
- connection_status.status);
- return;
- }
- auto logoff = ParseEAPoLLogoffFrame(packet.data);
-
- network_info.total_nodes = logoff.connected_nodes;
- network_info.max_nodes = logoff.max_nodes;
-
- connection_status.network_node_id = logoff.assigned_node_id;
- connection_status.total_nodes = logoff.connected_nodes;
- connection_status.max_nodes = logoff.max_nodes;
-
- node_info.clear();
- node_info.reserve(network_info.max_nodes);
- for (size_t index = 0; index < logoff.connected_nodes; ++index) {
- connection_status.node_bitmask |= 1 << index;
- connection_status.changed_nodes |= 1 << index;
- connection_status.nodes[index] = logoff.nodes[index].network_node_id;
-
- node_info.emplace_back(DeserializeNodeInfo(logoff.nodes[index]));
- }
-
- // We're now connected, signal the application
- connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsClient);
- // Some games require ConnectToNetwork to block, for now it doesn't
- // If blocking is implemented this lock needs to be changed,
- // otherwise it might cause deadlocks
- std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
- connection_status_event->Signal();
- }
-}
-
-/*
- * Start a connection sequence with an UDS server. The sequence starts by sending an 802.11
- * authentication frame with SEQ1.
- */
-void StartConnectionSequence(const MacAddress& server) {
- using Network::WifiPacket;
- WifiPacket auth_request;
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- ASSERT(connection_status.status == static_cast<u32>(NetworkStatus::NotConnected));
-
- // TODO(Subv): Handle timeout.
-
- // Send an authentication frame with SEQ1
- auth_request.channel = network_channel;
- auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ1);
- auth_request.destination_address = server;
- auth_request.type = WifiPacket::PacketType::Authentication;
- }
-
- SendPacket(auth_request);
-}
-
-/// Sends an Association Response frame to the specified mac address
-void SendAssociationResponseFrame(const MacAddress& address) {
- using Network::WifiPacket;
- WifiPacket assoc_response;
-
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
- LOG_ERROR(Service_NWM, "Connection sequence aborted, because connection status is %u",
- connection_status.status);
- return;
- }
-
- assoc_response.channel = network_channel;
- // TODO(Subv): This will cause multiple clients to end up with the same association id, but
- // we're not using that for anything.
- u16 association_id = 1;
- assoc_response.data = GenerateAssocResponseFrame(AssocStatus::Successful, association_id,
- network_info.network_id);
- assoc_response.destination_address = address;
- assoc_response.type = WifiPacket::PacketType::AssociationResponse;
- }
-
- SendPacket(assoc_response);
-}
-
-/*
- * Handles the authentication request frame and sends the authentication response and association
- * response frames. Once an Authentication frame with SEQ1 is received by the server, it responds
- * with an Authentication frame containing SEQ2, and immediately sends an Association response frame
- * containing the details of the access point and the assigned association id for the new client.
- */
-void HandleAuthenticationFrame(const Network::WifiPacket& packet) {
- // Only the SEQ1 auth frame is handled here, the SEQ2 frame doesn't need any special behavior
- if (GetAuthenticationSeqNumber(packet.data) == AuthenticationSeq::SEQ1) {
- using Network::WifiPacket;
- WifiPacket auth_request;
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
- LOG_ERROR(Service_NWM,
- "Connection sequence aborted, because connection status is %u",
- connection_status.status);
- return;
- }
-
- // Respond with an authentication response frame with SEQ2
- auth_request.channel = network_channel;
- auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ2);
- auth_request.destination_address = packet.transmitter_address;
- auth_request.type = WifiPacket::PacketType::Authentication;
- }
- SendPacket(auth_request);
-
- SendAssociationResponseFrame(packet.transmitter_address);
- }
-}
-
-static void HandleDataFrame(const Network::WifiPacket& packet) {
- switch (GetFrameEtherType(packet.data)) {
- case EtherType::EAPoL:
- HandleEAPoLPacket(packet);
- break;
- case EtherType::SecureData:
- // TODO(B3N30): Handle SecureData packets
- break;
- }
-}
-
-/// Callback to parse and handle a received wifi packet.
-void OnWifiPacketReceived(const Network::WifiPacket& packet) {
- switch (packet.type) {
- case Network::WifiPacket::PacketType::Beacon:
- HandleBeaconFrame(packet);
- break;
- case Network::WifiPacket::PacketType::Authentication:
- HandleAuthenticationFrame(packet);
- break;
- case Network::WifiPacket::PacketType::AssociationResponse:
- HandleAssociationResponseFrame(packet);
- break;
- case Network::WifiPacket::PacketType::Data:
- HandleDataFrame(packet);
- break;
- }
-}
-
-/**
- * NWM_UDS::Shutdown service function
- * Inputs:
- * 1 : None
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void Shutdown(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
-
- // TODO(purpasmart): Verify return header on HW
-
- cmd_buff[1] = RESULT_SUCCESS.raw;
-
- LOG_WARNING(Service_NWM, "(STUBBED) called");
-}
-
-/**
- * NWM_UDS::RecvBeaconBroadcastData service function
- * Returns the raw beacon data for nearby networks that match the supplied WlanCommId.
- * Inputs:
- * 1 : Output buffer max size
- * 2-3 : Unknown
- * 4-5 : Host MAC address.
- * 6-14 : Unused
- * 15 : WLan Comm Id
- * 16 : Id
- * 17 : Value 0
- * 18 : Input handle
- * 19 : (Size<<4) | 12
- * 20 : Output buffer ptr
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void RecvBeaconBroadcastData(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0F, 16, 4);
-
- u32 out_buffer_size = rp.Pop<u32>();
- u32 unk1 = rp.Pop<u32>();
- u32 unk2 = rp.Pop<u32>();
-
- MacAddress mac_address;
- rp.PopRaw(mac_address);
-
- rp.Skip(9, false);
-
- u32 wlan_comm_id = rp.Pop<u32>();
- u32 id = rp.Pop<u32>();
- Kernel::Handle input_handle = rp.PopHandle();
-
- size_t desc_size;
- const VAddr out_buffer_ptr = rp.PopMappedBuffer(&desc_size);
- ASSERT(desc_size == out_buffer_size);
-
- VAddr current_buffer_pos = out_buffer_ptr;
- u32 total_size = sizeof(BeaconDataReplyHeader);
-
- // Retrieve all beacon frames that were received from the desired mac address.
- auto beacons = GetReceivedBeacons(mac_address);
-
- BeaconDataReplyHeader data_reply_header{};
- data_reply_header.total_entries = static_cast<u32>(beacons.size());
- data_reply_header.max_output_size = out_buffer_size;
-
- Memory::WriteBlock(current_buffer_pos, &data_reply_header, sizeof(BeaconDataReplyHeader));
- current_buffer_pos += sizeof(BeaconDataReplyHeader);
-
- // Write each of the received beacons into the buffer
- for (const auto& beacon : beacons) {
- BeaconEntryHeader entry{};
- // TODO(Subv): Figure out what this size is used for.
- entry.unk_size = static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size());
- entry.total_size = static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size());
- entry.wifi_channel = beacon.channel;
- entry.header_size = sizeof(BeaconEntryHeader);
- entry.mac_address = beacon.transmitter_address;
-
- ASSERT(current_buffer_pos < out_buffer_ptr + out_buffer_size);
-
- Memory::WriteBlock(current_buffer_pos, &entry, sizeof(BeaconEntryHeader));
- current_buffer_pos += sizeof(BeaconEntryHeader);
-
- Memory::WriteBlock(current_buffer_pos, beacon.data.data(), beacon.data.size());
- current_buffer_pos += static_cast<VAddr>(beacon.data.size());
-
- total_size += static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size());
- }
-
- // Update the total size in the structure and write it to the buffer again.
- data_reply_header.total_size = total_size;
- Memory::WriteBlock(out_buffer_ptr, &data_reply_header, sizeof(BeaconDataReplyHeader));
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
- rb.Push(RESULT_SUCCESS);
-
- LOG_DEBUG(Service_NWM, "called out_buffer_size=0x%08X, wlan_comm_id=0x%08X, id=0x%08X,"
- "input_handle=0x%08X, out_buffer_ptr=0x%08X, unk1=0x%08X, unk2=0x%08X",
- out_buffer_size, wlan_comm_id, id, input_handle, out_buffer_ptr, unk1, unk2);
-}
-
-/**
- * NWM_UDS::Initialize service function
- * Inputs:
- * 1 : Shared memory size
- * 2-11 : Input NodeInfo Structure
- * 12 : 2-byte Version
- * 13 : Value 0
- * 14 : Shared memory handle
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : Value 0
- * 3 : Output event handle
- */
-static void InitializeWithVersion(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1B, 12, 2);
-
- u32 sharedmem_size = rp.Pop<u32>();
-
- // Update the node information with the data the game gave us.
- rp.PopRaw(current_node);
-
- u16 version = rp.Pop<u16>();
-
- Kernel::Handle sharedmem_handle = rp.PopHandle();
-
- recv_buffer_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(sharedmem_handle);
-
- ASSERT_MSG(recv_buffer_memory->size == sharedmem_size, "Invalid shared memory size.");
-
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
-
- // Reset the connection status, it contains all zeros after initialization,
- // except for the actual status value.
- connection_status = {};
- connection_status.status = static_cast<u32>(NetworkStatus::NotConnected);
- }
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
- rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(connection_status_event).Unwrap());
-
- // TODO(Subv): Connect the OnWifiPacketReceived function to the wifi packet received callback of
- // the room we're currently in.
-
- LOG_DEBUG(Service_NWM, "called sharedmem_size=0x%08X, version=0x%08X, sharedmem_handle=0x%08X",
- sharedmem_size, version, sharedmem_handle);
-}
-
-/**
- * NWM_UDS::GetConnectionStatus service function.
- * Returns the connection status structure for the currently open network connection.
- * This structure contains information about the connection,
- * like the number of connected nodes, etc.
- * Inputs:
- * 0 : Command header.
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- * 2-13 : Channel of the current WiFi network connection.
- */
-static void GetConnectionStatus(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xB, 0, 0);
- IPC::RequestBuilder rb = rp.MakeBuilder(13, 0);
-
- rb.Push(RESULT_SUCCESS);
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- rb.PushRaw(connection_status);
-
- // Reset the bitmask of changed nodes after each call to this
- // function to prevent falsely informing games of outstanding
- // changes in subsequent calls.
- // TODO(Subv): Find exactly where the NWM module resets this value.
- connection_status.changed_nodes = 0;
- }
-
- LOG_DEBUG(Service_NWM, "called");
-}
-
-/**
- * NWM_UDS::Bind service function.
- * Binds a BindNodeId to a data channel and retrieves a data event.
- * Inputs:
- * 1 : BindNodeId
- * 2 : Receive buffer size.
- * 3 : u8 Data channel to bind to.
- * 4 : Network node id.
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : Copy handle descriptor.
- * 3 : Data available event handle.
- */
-static void Bind(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x12, 4, 0);
-
- u32 bind_node_id = rp.Pop<u32>();
- u32 recv_buffer_size = rp.Pop<u32>();
- u8 data_channel = rp.Pop<u8>();
- u16 network_node_id = rp.Pop<u16>();
-
- // TODO(Subv): Store the data channel and verify it when receiving data frames.
-
- LOG_DEBUG(Service_NWM, "called");
-
- if (data_channel == 0) {
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
- rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
- ErrorSummary::WrongArgument, ErrorLevel::Usage));
- return;
- }
-
- // Create a new event for this bind node.
- // TODO(Subv): Signal this event when new data is received on this data channel.
- auto event = Kernel::Event::Create(Kernel::ResetType::OneShot,
- "NWM::BindNodeEvent" + std::to_string(bind_node_id));
- bind_node_events[bind_node_id] = event;
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
-
- rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(event).Unwrap());
-}
-
-/**
- * NWM_UDS::BeginHostingNetwork service function.
- * Creates a network and starts broadcasting its presence.
- * Inputs:
- * 1 : Passphrase buffer size.
- * 3 : VAddr of the NetworkInfo structure.
- * 5 : VAddr of the passphrase.
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void BeginHostingNetwork(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1D, 1, 4);
-
- const u32 passphrase_size = rp.Pop<u32>();
-
- size_t desc_size;
- const VAddr network_info_address = rp.PopStaticBuffer(&desc_size, false);
- ASSERT(desc_size == sizeof(NetworkInfo));
- const VAddr passphrase_address = rp.PopStaticBuffer(&desc_size, false);
- ASSERT(desc_size == passphrase_size);
-
- // TODO(Subv): Store the passphrase and verify it when attempting a connection.
-
- LOG_DEBUG(Service_NWM, "called");
-
- Memory::ReadBlock(network_info_address, &network_info, sizeof(NetworkInfo));
-
- // The real UDS module throws a fatal error if this assert fails.
- ASSERT_MSG(network_info.max_nodes > 1, "Trying to host a network of only one member.");
-
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsHost);
-
- // Ensure the application data size is less than the maximum value.
- ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize,
- "Data size is too big.");
-
- // Set up basic information for this network.
- network_info.oui_value = NintendoOUI;
- network_info.oui_type = static_cast<u8>(NintendoTagId::NetworkInfo);
-
- connection_status.max_nodes = network_info.max_nodes;
-
- // Resize the nodes list to hold max_nodes.
- node_info.resize(network_info.max_nodes);
-
- // There's currently only one node in the network (the host).
- connection_status.total_nodes = 1;
- network_info.total_nodes = 1;
- // The host is always the first node
- connection_status.network_node_id = 1;
- current_node.network_node_id = 1;
- connection_status.nodes[0] = connection_status.network_node_id;
- // Set the bit 0 in the nodes bitmask to indicate that node 1 is already taken.
- connection_status.node_bitmask |= 1;
- // Notify the application that the first node was set.
- connection_status.changed_nodes |= 1;
- node_info[0] = current_node;
- }
-
- // If the game has a preferred channel, use that instead.
- if (network_info.channel != 0)
- network_channel = network_info.channel;
-
- connection_status_event->Signal();
-
- // Start broadcasting the network, send a beacon frame every 102.4ms.
- CoreTiming::ScheduleEvent(msToCycles(DefaultBeaconInterval * MillisecondsPerTU),
- beacon_broadcast_event, 0);
-
- LOG_WARNING(Service_NWM,
- "An UDS network has been created, but broadcasting it is unimplemented.");
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
- rb.Push(RESULT_SUCCESS);
-}
-
-/**
- * NWM_UDS::DestroyNetwork service function.
- * Closes the network that we're currently hosting.
- * Inputs:
- * 0 : Command header.
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void DestroyNetwork(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x08, 0, 0);
-
- // TODO(Subv): Find out what happens if this is called while
- // no network is being hosted.
-
- // Unschedule the beacon broadcast event.
- CoreTiming::UnscheduleEvent(beacon_broadcast_event, 0);
-
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
-
- // TODO(Subv): Check if connection_status is indeed reset after this call.
- connection_status = {};
- connection_status.status = static_cast<u8>(NetworkStatus::NotConnected);
- }
- connection_status_event->Signal();
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
-
- rb.Push(RESULT_SUCCESS);
-
- LOG_WARNING(Service_NWM, "called");
-}
-
-/**
- * NWM_UDS::SendTo service function.
- * Sends a data frame to the UDS network we're connected to.
- * Inputs:
- * 0 : Command header.
- * 1 : Unknown.
- * 2 : u16 Destination network node id.
- * 3 : u8 Data channel.
- * 4 : Buffer size >> 2
- * 5 : Data size
- * 6 : Flags
- * 7 : Input buffer descriptor
- * 8 : Input buffer address
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void SendTo(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x17, 6, 2);
-
- rp.Skip(1, false);
- u16 dest_node_id = rp.Pop<u16>();
- u8 data_channel = rp.Pop<u8>();
- rp.Skip(1, false);
- u32 data_size = rp.Pop<u32>();
- u32 flags = rp.Pop<u32>();
-
- size_t desc_size;
- const VAddr input_address = rp.PopStaticBuffer(&desc_size, false);
- ASSERT(desc_size == data_size);
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
-
- u16 network_node_id;
-
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsClient) &&
- connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
- rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
- ErrorSummary::InvalidState, ErrorLevel::Status));
- return;
- }
-
- if (dest_node_id == connection_status.network_node_id) {
- rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::UDS,
- ErrorSummary::WrongArgument, ErrorLevel::Status));
- return;
- }
-
- network_node_id = connection_status.network_node_id;
- }
-
- // TODO(Subv): Do something with the flags.
-
- constexpr size_t MaxSize = 0x5C6;
- if (data_size > MaxSize) {
- rb.Push(ResultCode(ErrorDescription::TooLarge, ErrorModule::UDS,
- ErrorSummary::WrongArgument, ErrorLevel::Usage));
- return;
- }
-
- std::vector<u8> data(data_size);
- Memory::ReadBlock(input_address, data.data(), data.size());
-
- // TODO(Subv): Increment the sequence number after each sent packet.
- u16 sequence_number = 0;
- std::vector<u8> data_payload =
- GenerateDataPayload(data, data_channel, dest_node_id, network_node_id, sequence_number);
-
- // TODO(Subv): Retrieve the MAC address of the dest_node_id and our own to encrypt
- // and encapsulate the payload.
-
- // TODO(Subv): Send the frame.
-
- rb.Push(RESULT_SUCCESS);
-
- LOG_WARNING(Service_NWM, "(STUB) called dest_node_id=%u size=%u flags=%u channel=%u",
- static_cast<u32>(dest_node_id), data_size, flags, static_cast<u32>(data_channel));
-}
-
-/**
- * NWM_UDS::GetChannel service function.
- * Returns the WiFi channel in which the network we're connected to is transmitting.
- * Inputs:
- * 0 : Command header.
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : Channel of the current WiFi network connection.
- */
-static void GetChannel(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1A, 0, 0);
- IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
-
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- bool is_connected = connection_status.status != static_cast<u32>(NetworkStatus::NotConnected);
-
- u8 channel = is_connected ? network_channel : 0;
-
- rb.Push(RESULT_SUCCESS);
- rb.Push(channel);
-
- LOG_DEBUG(Service_NWM, "called");
-}
-
-/**
- * NWM_UDS::SetApplicationData service function.
- * Updates the application data that is being broadcast in the beacon frames
- * for the network that we're hosting.
- * Inputs:
- * 1 : Data size.
- * 3 : VAddr of the data.
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : Channel of the current WiFi network connection.
- */
-static void SetApplicationData(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1A, 1, 2);
-
- u32 size = rp.Pop<u32>();
-
- size_t desc_size;
- const VAddr address = rp.PopStaticBuffer(&desc_size, false);
- ASSERT(desc_size == size);
-
- LOG_DEBUG(Service_NWM, "called");
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
-
- if (size > ApplicationDataSize) {
- rb.Push(ResultCode(ErrorDescription::TooLarge, ErrorModule::UDS,
- ErrorSummary::WrongArgument, ErrorLevel::Usage));
- return;
- }
-
- network_info.application_data_size = size;
- Memory::ReadBlock(address, network_info.application_data.data(), size);
-
- rb.Push(RESULT_SUCCESS);
-}
-
-/**
- * NWM_UDS::DecryptBeaconData service function.
- * Decrypts the encrypted data tags contained in the 802.11 beacons.
- * Inputs:
- * 1 : Input network struct buffer descriptor.
- * 2 : Input network struct buffer ptr.
- * 3 : Input tag0 encrypted buffer descriptor.
- * 4 : Input tag0 encrypted buffer ptr.
- * 5 : Input tag1 encrypted buffer descriptor.
- * 6 : Input tag1 encrypted buffer ptr.
- * 64 : Output buffer descriptor.
- * 65 : Output buffer ptr.
- * Outputs:
- * 0 : Return header
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void DecryptBeaconData(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1F, 0, 6);
-
- size_t desc_size;
- const VAddr network_struct_addr = rp.PopStaticBuffer(&desc_size);
- ASSERT(desc_size == sizeof(NetworkInfo));
-
- size_t data0_size;
- const VAddr encrypted_data0_addr = rp.PopStaticBuffer(&data0_size);
-
- size_t data1_size;
- const VAddr encrypted_data1_addr = rp.PopStaticBuffer(&data1_size);
-
- size_t output_buffer_size;
- const VAddr output_buffer_addr = rp.PeekStaticBuffer(0, &output_buffer_size);
-
- // This size is hardcoded in the 3DS UDS code.
- ASSERT(output_buffer_size == sizeof(NodeInfo) * UDSMaxNodes);
-
- LOG_WARNING(Service_NWM, "called in0=%08X in1=%08X out=%08X", encrypted_data0_addr,
- encrypted_data1_addr, output_buffer_addr);
-
- NetworkInfo net_info;
- Memory::ReadBlock(network_struct_addr, &net_info, sizeof(net_info));
-
- // Read the encrypted data.
- // The first 4 bytes should be the OUI and the OUI Type of the tags.
- std::array<u8, 3> oui;
- Memory::ReadBlock(encrypted_data0_addr, oui.data(), oui.size());
- ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI");
- Memory::ReadBlock(encrypted_data1_addr, oui.data(), oui.size());
- ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI");
-
- ASSERT_MSG(Memory::Read8(encrypted_data0_addr + 3) ==
- static_cast<u8>(NintendoTagId::EncryptedData0),
- "Unexpected tag id");
- ASSERT_MSG(Memory::Read8(encrypted_data1_addr + 3) ==
- static_cast<u8>(NintendoTagId::EncryptedData1),
- "Unexpected tag id");
-
- std::vector<u8> beacon_data(data0_size + data1_size);
- Memory::ReadBlock(encrypted_data0_addr + 4, beacon_data.data(), data0_size);
- Memory::ReadBlock(encrypted_data1_addr + 4, beacon_data.data() + data0_size, data1_size);
-
- // Decrypt the data
- DecryptBeaconData(net_info, beacon_data);
-
- // The beacon data header contains the MD5 hash of the data.
- BeaconData beacon_header;
- std::memcpy(&beacon_header, beacon_data.data(), sizeof(beacon_header));
-
- // TODO(Subv): Verify the MD5 hash of the data and return 0xE1211005 if invalid.
-
- u8 num_nodes = net_info.max_nodes;
-
- std::vector<NodeInfo> nodes;
-
- for (int i = 0; i < num_nodes; ++i) {
- BeaconNodeInfo info;
- std::memcpy(&info, beacon_data.data() + sizeof(beacon_header) + i * sizeof(info),
- sizeof(info));
-
- // Deserialize the node information.
- NodeInfo node{};
- node.friend_code_seed = info.friend_code_seed;
- node.network_node_id = info.network_node_id;
- for (int i = 0; i < info.username.size(); ++i)
- node.username[i] = info.username[i];
-
- nodes.push_back(node);
- }
-
- Memory::ZeroBlock(output_buffer_addr, sizeof(NodeInfo) * UDSMaxNodes);
- Memory::WriteBlock(output_buffer_addr, nodes.data(), sizeof(NodeInfo) * nodes.size());
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
- rb.PushStaticBuffer(output_buffer_addr, output_buffer_size, 0);
- rb.Push(RESULT_SUCCESS);
-}
-
-// Sends a 802.11 beacon frame with information about the current network.
-static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
- // Don't do anything if we're not actually hosting a network
- if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost))
- return;
-
- std::vector<u8> frame = GenerateBeaconFrame(network_info, node_info);
-
- using Network::WifiPacket;
- WifiPacket packet;
- packet.type = WifiPacket::PacketType::Beacon;
- packet.data = std::move(frame);
- packet.destination_address = Network::BroadcastMac;
- packet.channel = network_channel;
-
- SendPacket(packet);
-
- // Start broadcasting the network, send a beacon frame every 102.4ms.
- CoreTiming::ScheduleEvent(msToCycles(DefaultBeaconInterval * MillisecondsPerTU) - cycles_late,
- beacon_broadcast_event, 0);
-}
-
-/*
- * Called when a client connects to an UDS network we're hosting,
- * updates the connection status and signals the update event.
- * @param network_node_id Network Node Id of the connecting client.
- */
-void OnClientConnected(u16 network_node_id) {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost),
- "Can not accept clients if we're not hosting a network");
- ASSERT_MSG(connection_status.total_nodes < connection_status.max_nodes,
- "Can not accept connections on a full network");
-
- u32 node_id = GetNextAvailableNodeId();
- connection_status.node_bitmask |= 1 << node_id;
- connection_status.changed_nodes |= 1 << node_id;
- connection_status.nodes[node_id] = network_node_id;
- connection_status.total_nodes++;
- connection_status_event->Signal();
-}
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x000102C2, nullptr, "Initialize (deprecated)"},
- {0x00020000, nullptr, "Scrap"},
- {0x00030000, Shutdown, "Shutdown"},
- {0x00040402, nullptr, "CreateNetwork (deprecated)"},
- {0x00050040, nullptr, "EjectClient"},
- {0x00060000, nullptr, "EjectSpectator"},
- {0x00070080, nullptr, "UpdateNetworkAttribute"},
- {0x00080000, DestroyNetwork, "DestroyNetwork"},
- {0x00090442, nullptr, "ConnectNetwork (deprecated)"},
- {0x000A0000, nullptr, "DisconnectNetwork"},
- {0x000B0000, GetConnectionStatus, "GetConnectionStatus"},
- {0x000D0040, nullptr, "GetNodeInformation"},
- {0x000E0006, nullptr, "DecryptBeaconData (deprecated)"},
- {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"},
- {0x00100042, SetApplicationData, "SetApplicationData"},
- {0x00110040, nullptr, "GetApplicationData"},
- {0x00120100, Bind, "Bind"},
- {0x00130040, nullptr, "Unbind"},
- {0x001400C0, nullptr, "PullPacket"},
- {0x00150080, nullptr, "SetMaxSendDelay"},
- {0x00170182, SendTo, "SendTo"},
- {0x001A0000, GetChannel, "GetChannel"},
- {0x001B0302, InitializeWithVersion, "InitializeWithVersion"},
- {0x001D0044, BeginHostingNetwork, "BeginHostingNetwork"},
- {0x001E0084, nullptr, "ConnectToNetwork"},
- {0x001F0006, DecryptBeaconData, "DecryptBeaconData"},
- {0x00200040, nullptr, "Flush"},
- {0x00210080, nullptr, "SetProbeResponseParam"},
- {0x00220402, nullptr, "ScanOnConnection"},
-};
-
-NWM_UDS::NWM_UDS() {
- connection_status_event =
- Kernel::Event::Create(Kernel::ResetType::OneShot, "NWM::connection_status_event");
-
- Register(FunctionTable);
-
- beacon_broadcast_event =
- CoreTiming::RegisterEvent("UDS::BeaconBroadcastCallback", BeaconBroadcastCallback);
-}
-
-NWM_UDS::~NWM_UDS() {
- network_info = {};
- bind_node_events.clear();
- connection_status_event = nullptr;
- recv_buffer_memory = nullptr;
-
- {
- std::lock_guard<std::mutex> lock(connection_status_mutex);
- connection_status = {};
- connection_status.status = static_cast<u32>(NetworkStatus::NotConnected);
- }
-
- CoreTiming::UnscheduleEvent(beacon_broadcast_event, 0);
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/nwm_uds.h b/src/core/hle/service/nwm/nwm_uds.h
deleted file mode 100644
index f1caaf974..000000000
--- a/src/core/hle/service/nwm/nwm_uds.h
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-#include <cstddef>
-#include <vector>
-#include "common/common_types.h"
-#include "common/swap.h"
-#include "core/hle/service/service.h"
-
-// Local-WLAN service
-
-namespace Service {
-namespace NWM {
-
-const size_t ApplicationDataSize = 0xC8;
-const u8 DefaultNetworkChannel = 11;
-
-// Number of milliseconds in a TU.
-const double MillisecondsPerTU = 1.024;
-// Interval measured in TU, the default value is 100TU = 102.4ms
-const u16 DefaultBeaconInterval = 100;
-
-/// The maximum number of nodes that can exist in an UDS session.
-constexpr u32 UDSMaxNodes = 16;
-
-struct NodeInfo {
- u64_le friend_code_seed;
- std::array<u16_le, 10> username;
- INSERT_PADDING_BYTES(4);
- u16_le network_node_id;
- INSERT_PADDING_BYTES(6);
-};
-
-static_assert(sizeof(NodeInfo) == 40, "NodeInfo has incorrect size.");
-
-using NodeList = std::vector<NodeInfo>;
-
-enum class NetworkStatus {
- NotConnected = 3,
- ConnectedAsHost = 6,
- Connecting = 7,
- ConnectedAsClient = 9,
- ConnectedAsSpectator = 10,
-};
-
-struct ConnectionStatus {
- u32_le status;
- INSERT_PADDING_WORDS(1);
- u16_le network_node_id;
- u16_le changed_nodes;
- u16_le nodes[UDSMaxNodes];
- u8 total_nodes;
- u8 max_nodes;
- u16_le node_bitmask;
-};
-
-static_assert(sizeof(ConnectionStatus) == 0x30, "ConnectionStatus has incorrect size.");
-
-struct NetworkInfo {
- std::array<u8, 6> host_mac_address;
- u8 channel;
- INSERT_PADDING_BYTES(1);
- u8 initialized;
- INSERT_PADDING_BYTES(3);
- std::array<u8, 3> oui_value;
- u8 oui_type;
- // This field is received as BigEndian from the game.
- u32_be wlan_comm_id;
- u8 id;
- INSERT_PADDING_BYTES(1);
- u16_be attributes;
- u32_be network_id;
- u8 total_nodes;
- u8 max_nodes;
- INSERT_PADDING_BYTES(2);
- INSERT_PADDING_BYTES(0x1F);
- u8 application_data_size;
- std::array<u8, ApplicationDataSize> application_data;
-};
-
-static_assert(offsetof(NetworkInfo, oui_value) == 0xC, "oui_value is at the wrong offset.");
-static_assert(offsetof(NetworkInfo, wlan_comm_id) == 0x10, "wlancommid is at the wrong offset.");
-static_assert(sizeof(NetworkInfo) == 0x108, "NetworkInfo has incorrect size.");
-
-/// Additional block tag ids in the Beacon and Association Response frames
-enum class TagId : u8 {
- SSID = 0,
- SupportedRates = 1,
- DSParameterSet = 2,
- TrafficIndicationMap = 5,
- CountryInformation = 7,
- ERPInformation = 42,
- VendorSpecific = 221
-};
-
-class NWM_UDS final : public Interface {
-public:
- NWM_UDS();
- ~NWM_UDS() override;
-
- std::string GetPortName() const override {
- return "nwm::UDS";
- }
-};
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/uds_beacon.cpp b/src/core/hle/service/nwm/uds_beacon.cpp
deleted file mode 100644
index 73a80d940..000000000
--- a/src/core/hle/service/nwm/uds_beacon.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <cstring>
-#include <cryptopp/aes.h>
-#include <cryptopp/md5.h>
-#include <cryptopp/modes.h>
-#include <cryptopp/sha.h>
-#include "common/assert.h"
-#include "core/hle/service/nwm/nwm_uds.h"
-#include "core/hle/service/nwm/uds_beacon.h"
-
-namespace Service {
-namespace NWM {
-
-// 802.11 broadcast MAC address
-constexpr MacAddress BroadcastMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
-constexpr u64 DefaultNetworkUptime = 900000000; // 15 minutes in microseconds.
-
-// Note: These values were taken from a packet capture of an o3DS XL
-// broadcasting a Super Smash Bros. 4 lobby.
-constexpr u16 DefaultExtraCapabilities = 0x0431;
-
-// Size of the SSID broadcast by an UDS beacon frame.
-constexpr u8 UDSBeaconSSIDSize = 8;
-
-// The maximum size of the data stored in the EncryptedData0 tag (24).
-constexpr u32 EncryptedDataSizeCutoff = 0xFA;
-
-/**
- * NWM Beacon data encryption key, taken from the NWM module code.
- * We stub this with an all-zeros key as that is enough for Citra's purpose.
- * The real key can be used here to generate beacons that will be accepted by
- * a real 3ds.
- */
-constexpr std::array<u8, CryptoPP::AES::BLOCKSIZE> nwm_beacon_key = {};
-
-/**
- * Generates a buffer with the fixed parameters of an 802.11 Beacon frame
- * using dummy values.
- * @returns A buffer with the fixed parameters of the beacon frame.
- */
-std::vector<u8> GenerateFixedParameters() {
- std::vector<u8> buffer(sizeof(BeaconFrameHeader));
-
- BeaconFrameHeader header{};
- // Use a fixed default time for now.
- // TODO(Subv): Perhaps use the difference between now and the time the network was started?
- header.timestamp = DefaultNetworkUptime;
- header.beacon_interval = DefaultBeaconInterval;
- header.capabilities = DefaultExtraCapabilities;
-
- std::memcpy(buffer.data(), &header, sizeof(header));
-
- return buffer;
-}
-
-/**
- * Generates an SSID tag of an 802.11 Beacon frame with an 8-byte all-zero SSID value.
- * @returns A buffer with the SSID tag.
- */
-std::vector<u8> GenerateSSIDTag() {
- std::vector<u8> buffer(sizeof(TagHeader) + UDSBeaconSSIDSize);
-
- TagHeader tag_header{};
- tag_header.tag_id = static_cast<u8>(TagId::SSID);
- tag_header.length = UDSBeaconSSIDSize;
-
- std::memcpy(buffer.data(), &tag_header, sizeof(TagHeader));
-
- // The rest of the buffer is already filled with zeros.
-
- return buffer;
-}
-
-/**
- * Generates a buffer with the basic tagged parameters of an 802.11 Beacon frame
- * such as SSID, Rate Information, Country Information, etc.
- * @returns A buffer with the tagged parameters of the beacon frame.
- */
-std::vector<u8> GenerateBasicTaggedParameters() {
- // Append the SSID tag
- std::vector<u8> buffer = GenerateSSIDTag();
-
- // TODO(Subv): Add the SupportedRates tag.
- // TODO(Subv): Add the DSParameterSet tag.
- // TODO(Subv): Add the TrafficIndicationMap tag.
- // TODO(Subv): Add the CountryInformation tag.
- // TODO(Subv): Add the ERPInformation tag.
-
- return buffer;
-}
-
-/**
- * Generates a buffer with the Dummy Nintendo tag.
- * It is currently unknown what this tag does.
- * TODO(Subv): Figure out if this is needed and what it does.
- * @returns A buffer with the Nintendo tagged parameters of the beacon frame.
- */
-std::vector<u8> GenerateNintendoDummyTag() {
- // Note: These values were taken from a packet capture of an o3DS XL
- // broadcasting a Super Smash Bros. 4 lobby.
- constexpr std::array<u8, 3> dummy_data = {0x0A, 0x00, 0x00};
-
- DummyTag tag{};
- tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific);
- tag.header.length = sizeof(DummyTag) - sizeof(TagHeader);
- tag.oui_type = static_cast<u8>(NintendoTagId::Dummy);
- tag.oui = NintendoOUI;
- tag.data = dummy_data;
-
- std::vector<u8> buffer(sizeof(DummyTag));
- std::memcpy(buffer.data(), &tag, sizeof(DummyTag));
-
- return buffer;
-}
-
-/**
- * Generates a buffer with the Network Info Nintendo tag.
- * This tag contains the network information of the network that is being broadcast.
- * It also contains the application data provided by the application that opened the network.
- * @returns A buffer with the Nintendo network info parameter of the beacon frame.
- */
-std::vector<u8> GenerateNintendoNetworkInfoTag(const NetworkInfo& network_info) {
- NetworkInfoTag tag{};
- tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific);
- tag.header.length =
- sizeof(NetworkInfoTag) - sizeof(TagHeader) + network_info.application_data_size;
- tag.appdata_size = network_info.application_data_size;
- // Set the hash to zero initially, it will be updated once we calculate it.
- tag.sha_hash = {};
-
- // Ensure the network structure has the correct OUI and OUI type.
- ASSERT(network_info.oui_type == static_cast<u8>(NintendoTagId::NetworkInfo));
- ASSERT(network_info.oui_value == NintendoOUI);
-
- // Ensure the application data size is less than the maximum value.
- ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize, "Data size is too big.");
-
- // This tag contains the network info structure starting at the OUI.
- std::memcpy(tag.network_info.data(), &network_info.oui_value, tag.network_info.size());
-
- // Copy the tag and the data so we can calculate the SHA1 over it.
- std::vector<u8> buffer(sizeof(tag) + network_info.application_data_size);
- std::memcpy(buffer.data(), &tag, sizeof(tag));
- std::memcpy(buffer.data() + sizeof(tag), network_info.application_data.data(),
- network_info.application_data_size);
-
- // Calculate the SHA1 of the contents of the tag.
- std::array<u8, CryptoPP::SHA1::DIGESTSIZE> hash;
- CryptoPP::SHA1().CalculateDigest(hash.data(),
- buffer.data() + offsetof(NetworkInfoTag, network_info),
- buffer.size() - sizeof(TagHeader));
-
- // Copy it directly into the buffer, overwriting the zeros that we had previously placed there.
- std::memcpy(buffer.data() + offsetof(NetworkInfoTag, sha_hash), hash.data(), hash.size());
-
- return buffer;
-}
-
-/*
- * Calculates the CTR used for the AES-CTR encryption of the data stored in the
- * EncryptedDataTags.
- * @returns The CTR used for beacon crypto.
- */
-std::array<u8, CryptoPP::AES::BLOCKSIZE> GetBeaconCryptoCTR(const NetworkInfo& network_info) {
- BeaconDataCryptoCTR data{};
-
- data.host_mac = network_info.host_mac_address;
- data.wlan_comm_id = network_info.wlan_comm_id;
- data.id = network_info.id;
- data.network_id = network_info.network_id;
-
- std::array<u8, CryptoPP::AES::BLOCKSIZE> hash;
- std::memcpy(hash.data(), &data, sizeof(data));
-
- return hash;
-}
-
-/*
- * Serializes the node information into the format needed for network transfer,
- * and then encrypts it with the NWM key.
- * @returns The serialized and encrypted node information.
- */
-std::vector<u8> GeneratedEncryptedData(const NetworkInfo& network_info, const NodeList& nodes) {
- std::vector<u8> buffer(sizeof(BeaconData));
-
- BeaconData data{};
- std::memcpy(buffer.data(), &data, sizeof(BeaconData));
-
- for (const NodeInfo& node : nodes) {
- // Serialize each node and convert the data from
- // host byte-order to Big Endian.
- BeaconNodeInfo info{};
- info.friend_code_seed = node.friend_code_seed;
- info.network_node_id = node.network_node_id;
- for (int i = 0; i < info.username.size(); ++i)
- info.username[i] = node.username[i];
-
- buffer.insert(buffer.end(), reinterpret_cast<u8*>(&info),
- reinterpret_cast<u8*>(&info) + sizeof(info));
- }
-
- // Calculate the MD5 hash of the data in the buffer, not including the hash field.
- std::array<u8, CryptoPP::MD5::DIGESTSIZE> hash;
- CryptoPP::MD5().CalculateDigest(hash.data(), buffer.data() + offsetof(BeaconData, bitmask),
- buffer.size() - sizeof(data.md5_hash));
-
- // Copy the hash into the buffer.
- std::memcpy(buffer.data(), hash.data(), hash.size());
-
- // Encrypt the data using AES-CTR and the NWM beacon key.
- using CryptoPP::AES;
- std::array<u8, AES::BLOCKSIZE> counter = GetBeaconCryptoCTR(network_info);
- CryptoPP::CTR_Mode<AES>::Encryption aes;
- aes.SetKeyWithIV(nwm_beacon_key.data(), AES::BLOCKSIZE, counter.data());
- aes.ProcessData(buffer.data(), buffer.data(), buffer.size());
-
- return buffer;
-}
-
-void DecryptBeaconData(const NetworkInfo& network_info, std::vector<u8>& buffer) {
- // Decrypt the data using AES-CTR and the NWM beacon key.
- using CryptoPP::AES;
- std::array<u8, AES::BLOCKSIZE> counter = GetBeaconCryptoCTR(network_info);
- CryptoPP::CTR_Mode<AES>::Decryption aes;
- aes.SetKeyWithIV(nwm_beacon_key.data(), AES::BLOCKSIZE, counter.data());
- aes.ProcessData(buffer.data(), buffer.data(), buffer.size());
-}
-
-/**
- * Generates a buffer with the Network Info Nintendo tag.
- * This tag contains the first portion of the encrypted payload in the 802.11 beacon frame.
- * The encrypted payload contains information about the nodes currently connected to the network.
- * @returns A buffer with the first Nintendo encrypted data parameters of the beacon frame.
- */
-std::vector<u8> GenerateNintendoFirstEncryptedDataTag(const NetworkInfo& network_info,
- const NodeList& nodes) {
- const size_t payload_size =
- std::min<size_t>(EncryptedDataSizeCutoff, nodes.size() * sizeof(NodeInfo));
-
- EncryptedDataTag tag{};
- tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific);
- tag.header.length = static_cast<u8>(sizeof(tag) - sizeof(TagHeader) + payload_size);
- tag.oui_type = static_cast<u8>(NintendoTagId::EncryptedData0);
- tag.oui = NintendoOUI;
-
- std::vector<u8> buffer(sizeof(tag) + payload_size);
- std::memcpy(buffer.data(), &tag, sizeof(tag));
-
- std::vector<u8> encrypted_data = GeneratedEncryptedData(network_info, nodes);
- std::memcpy(buffer.data() + sizeof(tag), encrypted_data.data(), payload_size);
-
- return buffer;
-}
-
-/**
- * Generates a buffer with the Network Info Nintendo tag.
- * This tag contains the second portion of the encrypted payload in the 802.11 beacon frame.
- * The encrypted payload contains information about the nodes currently connected to the network.
- * This tag is only present if the payload size is greater than EncryptedDataSizeCutoff (0xFA)
- * bytes.
- * @returns A buffer with the second Nintendo encrypted data parameters of the beacon frame.
- */
-std::vector<u8> GenerateNintendoSecondEncryptedDataTag(const NetworkInfo& network_info,
- const NodeList& nodes) {
- // This tag is only present if the payload is larger than EncryptedDataSizeCutoff (0xFA).
- if (nodes.size() * sizeof(NodeInfo) <= EncryptedDataSizeCutoff)
- return {};
-
- const size_t payload_size = nodes.size() * sizeof(NodeInfo) - EncryptedDataSizeCutoff;
-
- const size_t tag_length = sizeof(EncryptedDataTag) - sizeof(TagHeader) + payload_size;
-
- // TODO(Subv): What does the 3DS do when a game has too much data to fit into the tag?
- ASSERT_MSG(tag_length <= 255, "Data is too big.");
-
- EncryptedDataTag tag{};
- tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific);
- tag.header.length = static_cast<u8>(tag_length);
- tag.oui_type = static_cast<u8>(NintendoTagId::EncryptedData1);
- tag.oui = NintendoOUI;
-
- std::vector<u8> buffer(sizeof(tag) + payload_size);
- std::memcpy(buffer.data(), &tag, sizeof(tag));
-
- std::vector<u8> encrypted_data = GeneratedEncryptedData(network_info, nodes);
- std::memcpy(buffer.data() + sizeof(tag), encrypted_data.data() + EncryptedDataSizeCutoff,
- payload_size);
-
- return buffer;
-}
-
-/**
- * Generates a buffer with the Nintendo tagged parameters of an 802.11 Beacon frame
- * for UDS communication.
- * @returns A buffer with the Nintendo tagged parameters of the beacon frame.
- */
-std::vector<u8> GenerateNintendoTaggedParameters(const NetworkInfo& network_info,
- const NodeList& nodes) {
- ASSERT_MSG(network_info.max_nodes == nodes.size(), "Inconsistent network state.");
-
- std::vector<u8> buffer = GenerateNintendoDummyTag();
- std::vector<u8> network_info_tag = GenerateNintendoNetworkInfoTag(network_info);
- std::vector<u8> first_data_tag = GenerateNintendoFirstEncryptedDataTag(network_info, nodes);
- std::vector<u8> second_data_tag = GenerateNintendoSecondEncryptedDataTag(network_info, nodes);
-
- buffer.insert(buffer.end(), network_info_tag.begin(), network_info_tag.end());
- buffer.insert(buffer.end(), first_data_tag.begin(), first_data_tag.end());
- buffer.insert(buffer.end(), second_data_tag.begin(), second_data_tag.end());
-
- return buffer;
-}
-
-std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeList& nodes) {
- std::vector<u8> buffer = GenerateFixedParameters();
- std::vector<u8> basic_tags = GenerateBasicTaggedParameters();
- std::vector<u8> nintendo_tags = GenerateNintendoTaggedParameters(network_info, nodes);
-
- buffer.insert(buffer.end(), basic_tags.begin(), basic_tags.end());
- buffer.insert(buffer.end(), nintendo_tags.begin(), nintendo_tags.end());
-
- return buffer;
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/uds_beacon.h b/src/core/hle/service/nwm/uds_beacon.h
deleted file mode 100644
index 50cc76da2..000000000
--- a/src/core/hle/service/nwm/uds_beacon.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-#include <deque>
-#include <vector>
-#include "common/common_types.h"
-#include "common/swap.h"
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace NWM {
-
-using MacAddress = std::array<u8, 6>;
-constexpr std::array<u8, 3> NintendoOUI = {0x00, 0x1F, 0x32};
-
-/**
- * Internal vendor-specific tag ids as stored inside
- * VendorSpecific blocks in the Beacon frames.
- */
-enum class NintendoTagId : u8 {
- Dummy = 20,
- NetworkInfo = 21,
- EncryptedData0 = 24,
- EncryptedData1 = 25,
-};
-
-struct BeaconEntryHeader {
- u32_le total_size;
- INSERT_PADDING_BYTES(1);
- u8 wifi_channel;
- INSERT_PADDING_BYTES(2);
- MacAddress mac_address;
- INSERT_PADDING_BYTES(6);
- u32_le unk_size;
- u32_le header_size;
-};
-
-static_assert(sizeof(BeaconEntryHeader) == 0x1C, "BeaconEntryHeader has incorrect size.");
-
-struct BeaconDataReplyHeader {
- u32_le max_output_size;
- u32_le total_size;
- u32_le total_entries;
-};
-
-static_assert(sizeof(BeaconDataReplyHeader) == 12, "BeaconDataReplyHeader has incorrect size.");
-
-#pragma pack(push, 1)
-struct BeaconFrameHeader {
- // Number of microseconds the AP has been active.
- u64_le timestamp;
- // Interval between beacon transmissions, expressed in TU.
- u16_le beacon_interval;
- // Indicates the presence of optional capabilities.
- u16_le capabilities;
-};
-#pragma pack(pop)
-
-static_assert(sizeof(BeaconFrameHeader) == 12, "BeaconFrameHeader has incorrect size.");
-
-struct TagHeader {
- u8 tag_id;
- u8 length;
-};
-
-static_assert(sizeof(TagHeader) == 2, "TagHeader has incorrect size.");
-
-struct DummyTag {
- TagHeader header;
- std::array<u8, 3> oui;
- u8 oui_type;
- std::array<u8, 3> data;
-};
-
-static_assert(sizeof(DummyTag) == 9, "DummyTag has incorrect size.");
-
-struct NetworkInfoTag {
- TagHeader header;
- std::array<u8, 0x1F> network_info;
- std::array<u8, 0x14> sha_hash;
- u8 appdata_size;
-};
-
-static_assert(sizeof(NetworkInfoTag) == 54, "NetworkInfoTag has incorrect size.");
-
-struct EncryptedDataTag {
- TagHeader header;
- std::array<u8, 3> oui;
- u8 oui_type;
-};
-
-static_assert(sizeof(EncryptedDataTag) == 6, "EncryptedDataTag has incorrect size.");
-
-#pragma pack(push, 1)
-// The raw bytes of this structure are the CTR used in the encryption (AES-CTR)
-// of the beacon data stored in the EncryptedDataTags.
-struct BeaconDataCryptoCTR {
- MacAddress host_mac;
- u32_le wlan_comm_id;
- u8 id;
- INSERT_PADDING_BYTES(1);
- u32_le network_id;
-};
-
-static_assert(sizeof(BeaconDataCryptoCTR) == 0x10, "BeaconDataCryptoCTR has incorrect size.");
-
-struct BeaconNodeInfo {
- u64_be friend_code_seed;
- std::array<u16_be, 10> username;
- u16_be network_node_id;
-};
-
-static_assert(sizeof(BeaconNodeInfo) == 0x1E, "BeaconNodeInfo has incorrect size.");
-
-struct BeaconData {
- std::array<u8, 0x10> md5_hash;
- u16_be bitmask;
-};
-#pragma pack(pop)
-
-static_assert(sizeof(BeaconData) == 0x12, "BeaconData has incorrect size.");
-
-/**
- * Decrypts the beacon data buffer for the network described by `network_info`.
- */
-void DecryptBeaconData(const NetworkInfo& network_info, std::vector<u8>& buffer);
-
-/**
- * Generates an 802.11 beacon frame starting at the management frame header.
- * This frame contains information about the network and its connected clients.
- * @returns The generated frame.
- */
-std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeList& nodes);
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/uds_connection.cpp b/src/core/hle/service/nwm/uds_connection.cpp
deleted file mode 100644
index c74f51253..000000000
--- a/src/core/hle/service/nwm/uds_connection.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/nwm/nwm_uds.h"
-#include "core/hle/service/nwm/uds_connection.h"
-#include "fmt/format.h"
-
-namespace Service {
-namespace NWM {
-
-// Note: These values were taken from a packet capture of an o3DS XL
-// broadcasting a Super Smash Bros. 4 lobby.
-constexpr u16 DefaultExtraCapabilities = 0x0431;
-
-std::vector<u8> GenerateAuthenticationFrame(AuthenticationSeq seq) {
- AuthenticationFrame frame{};
- frame.auth_seq = static_cast<u16>(seq);
-
- std::vector<u8> data(sizeof(frame));
- std::memcpy(data.data(), &frame, sizeof(frame));
-
- return data;
-}
-
-AuthenticationSeq GetAuthenticationSeqNumber(const std::vector<u8>& body) {
- AuthenticationFrame frame;
- std::memcpy(&frame, body.data(), sizeof(frame));
-
- return static_cast<AuthenticationSeq>(frame.auth_seq);
-}
-
-/**
- * Generates an SSID tag of an 802.11 Beacon frame with an 8-byte character representation of the
- * specified network id as the SSID value.
- * @param network_id The network id to use.
- * @returns A buffer with the SSID tag.
- */
-static std::vector<u8> GenerateSSIDTag(u32 network_id) {
- constexpr u8 SSIDSize = 8;
-
- struct {
- u8 id = static_cast<u8>(TagId::SSID);
- u8 size = SSIDSize;
- } tag_header;
-
- std::vector<u8> buffer(sizeof(tag_header) + SSIDSize);
-
- std::memcpy(buffer.data(), &tag_header, sizeof(tag_header));
-
- std::string network_name = fmt::format("{0:08X}", network_id);
-
- std::memcpy(buffer.data() + sizeof(tag_header), network_name.c_str(), SSIDSize);
-
- return buffer;
-}
-
-std::vector<u8> GenerateAssocResponseFrame(AssocStatus status, u16 association_id, u32 network_id) {
- AssociationResponseFrame frame{};
- frame.capabilities = DefaultExtraCapabilities;
- frame.status_code = static_cast<u16>(status);
- // The association id is ORed with this magic value (0xC000)
- constexpr u16 AssociationIdMagic = 0xC000;
- frame.assoc_id = association_id | AssociationIdMagic;
-
- std::vector<u8> data(sizeof(frame));
- std::memcpy(data.data(), &frame, sizeof(frame));
-
- auto ssid_tag = GenerateSSIDTag(network_id);
- data.insert(data.end(), ssid_tag.begin(), ssid_tag.end());
-
- // TODO(Subv): Add the SupportedRates tag.
- // TODO(Subv): Add the DSParameterSet tag.
- // TODO(Subv): Add the ERPInformation tag.
- return data;
-}
-
-std::tuple<AssocStatus, u16> GetAssociationResult(const std::vector<u8>& body) {
- AssociationResponseFrame frame;
- memcpy(&frame, body.data(), sizeof(frame));
-
- constexpr u16 AssociationIdMask = 0x3FFF;
- return std::make_tuple(static_cast<AssocStatus>(frame.status_code),
- frame.assoc_id & AssociationIdMask);
-}
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/uds_connection.h b/src/core/hle/service/nwm/uds_connection.h
deleted file mode 100644
index a664f8471..000000000
--- a/src/core/hle/service/nwm/uds_connection.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <tuple>
-#include <vector>
-#include "common/common_types.h"
-#include "common/swap.h"
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace NWM {
-
-/// Sequence number of the 802.11 authentication frames.
-enum class AuthenticationSeq : u16 { SEQ1 = 1, SEQ2 = 2 };
-
-enum class AuthAlgorithm : u16 { OpenSystem = 0 };
-
-enum class AuthStatus : u16 { Successful = 0 };
-
-enum class AssocStatus : u16 { Successful = 0 };
-
-struct AuthenticationFrame {
- u16_le auth_algorithm = static_cast<u16>(AuthAlgorithm::OpenSystem);
- u16_le auth_seq;
- u16_le status_code = static_cast<u16>(AuthStatus::Successful);
-};
-
-static_assert(sizeof(AuthenticationFrame) == 6, "AuthenticationFrame has wrong size");
-
-struct AssociationResponseFrame {
- u16_le capabilities;
- u16_le status_code;
- u16_le assoc_id;
-};
-
-static_assert(sizeof(AssociationResponseFrame) == 6, "AssociationResponseFrame has wrong size");
-
-/// Generates an 802.11 authentication frame, starting at the frame body.
-std::vector<u8> GenerateAuthenticationFrame(AuthenticationSeq seq);
-
-/// Returns the sequence number from the body of an Authentication frame.
-AuthenticationSeq GetAuthenticationSeqNumber(const std::vector<u8>& body);
-
-/// Generates an 802.11 association response frame with the specified status, association id and
-/// network id, starting at the frame body.
-std::vector<u8> GenerateAssocResponseFrame(AssocStatus status, u16 association_id, u32 network_id);
-
-/// Returns a tuple of (association status, association id) from the body of an AssociationResponse
-/// frame.
-std::tuple<AssocStatus, u16> GetAssociationResult(const std::vector<u8>& body);
-
-} // namespace NWM
-} // namespace Service
diff --git a/src/core/hle/service/nwm/uds_data.cpp b/src/core/hle/service/nwm/uds_data.cpp
deleted file mode 100644
index 4b389710f..000000000
--- a/src/core/hle/service/nwm/uds_data.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// 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>
-#include <cryptopp/filters.h>
-#include <cryptopp/md5.h>
-#include <cryptopp/modes.h>
-#include "core/hle/service/nwm/nwm_uds.h"
-#include "core/hle/service/nwm/uds_data.h"
-#include "core/hw/aes/key.h"
-
-namespace Service {
-namespace NWM {
-
-using MacAddress = std::array<u8, 6>;
-
-/*
- * Generates a SNAP-enabled 802.2 LLC header for the specified protocol.
- * @returns a buffer with the bytes of the generated header.
- */
-static std::vector<u8> GenerateLLCHeader(EtherType protocol) {
- LLCHeader header{};
- header.protocol = static_cast<u16>(protocol);
-
- std::vector<u8> buffer(sizeof(header));
- memcpy(buffer.data(), &header, sizeof(header));
-
- return buffer;
-}
-
-/*
- * Generates a Nintendo UDS SecureData header with the specified parameters.
- * @returns a buffer with the bytes of the generated header.
- */
-static std::vector<u8> GenerateSecureDataHeader(u16 data_size, u8 channel, u16 dest_node_id,
- u16 src_node_id, u16 sequence_number) {
- SecureDataHeader header{};
- header.protocol_size = data_size + sizeof(SecureDataHeader);
- // Note: This size includes everything except the first 4 bytes of the structure,
- // reinforcing the hypotheses that the first 4 bytes are actually the header of
- // another container protocol.
- header.securedata_size = data_size + sizeof(SecureDataHeader) - 4;
- // Frames sent by the emulated application are never UDS management frames
- header.is_management = 0;
- header.data_channel = channel;
- header.sequence_number = sequence_number;
- header.dest_node_id = dest_node_id;
- header.src_node_id = src_node_id;
-
- std::vector<u8> buffer(sizeof(header));
- memcpy(buffer.data(), &header, sizeof(header));
-
- return buffer;
-}
-
-/*
- * Calculates the CTR used for the AES-CTR process that calculates
- * the CCMP crypto key for data frames.
- * @returns The CTR used for data frames crypto key generation.
- */
-static std::array<u8, CryptoPP::MD5::DIGESTSIZE> GetDataCryptoCTR(const NetworkInfo& network_info) {
- DataFrameCryptoCTR data{};
-
- data.host_mac = network_info.host_mac_address;
- data.wlan_comm_id = network_info.wlan_comm_id;
- data.id = network_info.id;
- data.network_id = network_info.network_id;
-
- std::array<u8, CryptoPP::MD5::DIGESTSIZE> hash;
- CryptoPP::MD5().CalculateDigest(hash.data(), reinterpret_cast<u8*>(&data), sizeof(data));
-
- return hash;
-}
-
-/*
- * Generates the key used for encrypting the 802.11 data frames generated by UDS.
- * @returns The key used for data frames crypto.
- */
-static std::array<u8, CryptoPP::AES::BLOCKSIZE> GenerateDataCCMPKey(
- const std::vector<u8>& passphrase, const NetworkInfo& network_info) {
- // Calculate the MD5 hash of the input passphrase.
- std::array<u8, CryptoPP::MD5::DIGESTSIZE> passphrase_hash;
- CryptoPP::MD5().CalculateDigest(passphrase_hash.data(), passphrase.data(), passphrase.size());
-
- std::array<u8, CryptoPP::AES::BLOCKSIZE> ccmp_key;
-
- // The CCMP key is the result of encrypting the MD5 hash of the passphrase with AES-CTR using
- // keyslot 0x2D.
- using CryptoPP::AES;
- std::array<u8, CryptoPP::MD5::DIGESTSIZE> counter = GetDataCryptoCTR(network_info);
- std::array<u8, AES::BLOCKSIZE> key = HW::AES::GetNormalKey(HW::AES::KeySlotID::UDSDataKey);
- CryptoPP::CTR_Mode<AES>::Encryption aes;
- aes.SetKeyWithIV(key.data(), AES::BLOCKSIZE, counter.data());
- aes.ProcessData(ccmp_key.data(), passphrase_hash.data(), passphrase_hash.size());
-
- return ccmp_key;
-}
-
-/*
- * Generates the Additional Authenticated Data (AAD) for an UDS 802.11 encrypted data frame.
- * @returns a buffer with the bytes of the AAD.
- */
-static std::vector<u8> GenerateCCMPAAD(const MacAddress& sender, const MacAddress& receiver,
- const MacAddress& bssid, u16 frame_control) {
- // Reference: IEEE 802.11-2007
-
- // 8.3.3.3.2 Construct AAD (22-30 bytes)
- // The AAD is constructed from the MPDU header. The AAD does not include the header Duration
- // field, because the Duration field value can change due to normal IEEE 802.11 operation (e.g.,
- // a rate change during retransmission). For similar reasons, several subfields in the Frame
- // Control field are masked to 0.
- struct {
- u16_be FC; // MPDU Frame Control field
- MacAddress A1;
- MacAddress A2;
- MacAddress A3;
- u16_be SC; // MPDU Sequence Control field
- } aad_struct{};
-
- constexpr u16 AADFrameControlMask = 0x8FC7;
- aad_struct.FC = frame_control & AADFrameControlMask;
- aad_struct.SC = 0;
-
- bool to_ds = (frame_control & (1 << 0)) != 0;
- bool from_ds = (frame_control & (1 << 1)) != 0;
- // In the 802.11 standard, ToDS = 1 and FromDS = 1 is a valid configuration,
- // however, the 3DS doesn't seem to transmit frames with such combination.
- ASSERT_MSG(to_ds != from_ds, "Invalid combination");
-
- // The meaning of the address fields depends on the ToDS and FromDS fields.
- if (from_ds) {
- aad_struct.A1 = receiver;
- aad_struct.A2 = bssid;
- aad_struct.A3 = sender;
- }
-
- if (to_ds) {
- aad_struct.A1 = bssid;
- aad_struct.A2 = sender;
- aad_struct.A3 = receiver;
- }
-
- std::vector<u8> aad(sizeof(aad_struct));
- std::memcpy(aad.data(), &aad_struct, sizeof(aad_struct));
-
- return aad;
-}
-
-/*
- * Decrypts the payload of an encrypted 802.11 data frame using the specified key.
- * @returns The decrypted payload.
- */
-static std::vector<u8> DecryptDataFrame(const std::vector<u8>& encrypted_payload,
- const std::array<u8, CryptoPP::AES::BLOCKSIZE>& ccmp_key,
- const MacAddress& sender, const MacAddress& receiver,
- const MacAddress& bssid, u16 sequence_number,
- u16 frame_control) {
-
- // Reference: IEEE 802.11-2007
-
- std::vector<u8> aad = GenerateCCMPAAD(sender, receiver, bssid, frame_control);
-
- std::vector<u8> packet_number{0,
- 0,
- 0,
- 0,
- static_cast<u8>((sequence_number >> 8) & 0xFF),
- static_cast<u8>(sequence_number & 0xFF)};
-
- // 8.3.3.3.3 Construct CCM nonce (13 bytes)
- std::vector<u8> nonce;
- nonce.push_back(0); // priority
- nonce.insert(nonce.end(), sender.begin(), sender.end()); // Address 2
- nonce.insert(nonce.end(), packet_number.begin(), packet_number.end()); // PN
-
- try {
- CryptoPP::CCM<CryptoPP::AES, 8>::Decryption d;
- d.SetKeyWithIV(ccmp_key.data(), ccmp_key.size(), nonce.data(), nonce.size());
- d.SpecifyDataLengths(aad.size(), encrypted_payload.size() - 8, 0);
-
- CryptoPP::AuthenticatedDecryptionFilter df(
- d, nullptr, CryptoPP::AuthenticatedDecryptionFilter::MAC_AT_END |
- CryptoPP::AuthenticatedDecryptionFilter::THROW_EXCEPTION);
- // put aad
- df.ChannelPut(CryptoPP::AAD_CHANNEL, aad.data(), aad.size());
-
- // put cipher with mac
- df.ChannelPut(CryptoPP::DEFAULT_CHANNEL, encrypted_payload.data(),
- encrypted_payload.size() - 8);
- df.ChannelPut(CryptoPP::DEFAULT_CHANNEL,
- encrypted_payload.data() + encrypted_payload.size() - 8, 8);
-
- df.ChannelMessageEnd(CryptoPP::AAD_CHANNEL);
- df.ChannelMessageEnd(CryptoPP::DEFAULT_CHANNEL);
- df.SetRetrievalChannel(CryptoPP::DEFAULT_CHANNEL);
-
- size_t size = df.MaxRetrievable();
-
- std::vector<u8> pdata(size);
- df.Get(pdata.data(), size);
- return pdata;
- } catch (CryptoPP::Exception&) {
- LOG_ERROR(Service_NWM, "failed to decrypt");
- }
-
- return {};
-}
-
-/*
- * Encrypts the payload of an 802.11 data frame using the specified key.
- * @returns The encrypted payload.
- */
-static std::vector<u8> EncryptDataFrame(const std::vector<u8>& payload,
- const std::array<u8, CryptoPP::AES::BLOCKSIZE>& ccmp_key,
- const MacAddress& sender, const MacAddress& receiver,
- const MacAddress& bssid, u16 sequence_number,
- u16 frame_control) {
- // Reference: IEEE 802.11-2007
-
- std::vector<u8> aad = GenerateCCMPAAD(sender, receiver, bssid, frame_control);
-
- std::vector<u8> packet_number{0,
- 0,
- 0,
- 0,
- static_cast<u8>((sequence_number >> 8) & 0xFF),
- static_cast<u8>(sequence_number & 0xFF)};
-
- // 8.3.3.3.3 Construct CCM nonce (13 bytes)
- std::vector<u8> nonce;
- nonce.push_back(0); // priority
- nonce.insert(nonce.end(), sender.begin(), sender.end()); // Address 2
- nonce.insert(nonce.end(), packet_number.begin(), packet_number.end()); // PN
-
- try {
- CryptoPP::CCM<CryptoPP::AES, 8>::Encryption d;
- d.SetKeyWithIV(ccmp_key.data(), ccmp_key.size(), nonce.data(), nonce.size());
- d.SpecifyDataLengths(aad.size(), payload.size(), 0);
-
- CryptoPP::AuthenticatedEncryptionFilter df(d);
- // put aad
- df.ChannelPut(CryptoPP::AAD_CHANNEL, aad.data(), aad.size());
- df.ChannelMessageEnd(CryptoPP::AAD_CHANNEL);
-
- // put plaintext
- df.ChannelPut(CryptoPP::DEFAULT_CHANNEL, payload.data(), payload.size());
- df.ChannelMessageEnd(CryptoPP::DEFAULT_CHANNEL);
-
- df.SetRetrievalChannel(CryptoPP::DEFAULT_CHANNEL);
-
- size_t size = df.MaxRetrievable();
-
- std::vector<u8> cipher(size);
- df.Get(cipher.data(), size);
- return cipher;
- } catch (CryptoPP::Exception&) {
- LOG_ERROR(Service_NWM, "failed to encrypt");
- }
-
- return {};
-}
-
-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(
- 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
diff --git a/src/core/hle/service/nwm/uds_data.h b/src/core/hle/service/nwm/uds_data.h
deleted file mode 100644
index 76bccb1bf..000000000
--- a/src/core/hle/service/nwm/uds_data.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-#include <vector>
-#include "common/common_types.h"
-#include "common/swap.h"
-#include "core/hle/service/nwm/uds_beacon.h"
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace NWM {
-
-enum class SAP : u8 { SNAPExtensionUsed = 0xAA };
-
-enum class PDUControl : u8 { UnnumberedInformation = 3 };
-
-enum class EtherType : u16 { SecureData = 0x876D, EAPoL = 0x888E };
-
-/*
- * 802.2 header, UDS packets always use SNAP for these headers,
- * which means the dsap and ssap are always SNAPExtensionUsed (0xAA)
- * and the OUI is always 0.
- */
-struct LLCHeader {
- u8 dsap = static_cast<u8>(SAP::SNAPExtensionUsed);
- u8 ssap = static_cast<u8>(SAP::SNAPExtensionUsed);
- u8 control = static_cast<u8>(PDUControl::UnnumberedInformation);
- std::array<u8, 3> OUI = {};
- u16_be protocol;
-};
-
-static_assert(sizeof(LLCHeader) == 8, "LLCHeader has the wrong size");
-
-/*
- * Nintendo SecureData header, every UDS packet contains one,
- * it is used to store metadata about the transmission such as
- * the source and destination network node ids.
- */
-struct SecureDataHeader {
- // TODO(Subv): It is likely that the first 4 bytes of this header are
- // actually part of another container protocol.
- u16_be protocol_size;
- INSERT_PADDING_BYTES(2);
- u16_be securedata_size;
- u8 is_management;
- u8 data_channel;
- u16_be sequence_number;
- u16_be dest_node_id;
- u16_be src_node_id;
-};
-
-static_assert(sizeof(SecureDataHeader) == 14, "SecureDataHeader has the wrong size");
-
-/*
- * The raw bytes of this structure are the CTR used in the encryption (AES-CTR)
- * process used to generate the CCMP key for data frame encryption.
- */
-struct DataFrameCryptoCTR {
- u32_le wlan_comm_id;
- u32_le network_id;
- std::array<u8, 6> host_mac;
- u16_le id;
-};
-
-static_assert(sizeof(DataFrameCryptoCTR) == 16, "DataFrameCryptoCTR has the wrong size");
-
-struct EAPoLNodeInfo {
- u64_be friend_code_seed;
- std::array<u16_be, 10> username;
- INSERT_PADDING_BYTES(4);
- u16_be network_node_id;
- INSERT_PADDING_BYTES(6);
-};
-
-static_assert(sizeof(EAPoLNodeInfo) == 0x28, "EAPoLNodeInfo has the wrong size");
-
-constexpr u16 EAPoLStartMagic = 0x201;
-
-/*
- * Nintendo EAPoLStartPacket, is used to initaliaze a connection between client and host
- */
-struct EAPoLStartPacket {
- u16_be magic = EAPoLStartMagic;
- u16_be association_id;
- // This value is hardcoded to 1 in the NWM module.
- u16_be unknown = 1;
- INSERT_PADDING_BYTES(2);
- EAPoLNodeInfo node;
-};
-
-static_assert(sizeof(EAPoLStartPacket) == 0x30, "EAPoLStartPacket has the wrong size");
-
-constexpr u16 EAPoLLogoffMagic = 0x202;
-
-struct EAPoLLogoffPacket {
- u16_be magic = EAPoLLogoffMagic;
- INSERT_PADDING_BYTES(2);
- u16_be assigned_node_id;
- MacAddress client_mac_address;
- INSERT_PADDING_BYTES(6);
- u8 connected_nodes;
- u8 max_nodes;
- INSERT_PADDING_BYTES(4);
-
- std::array<EAPoLNodeInfo, UDSMaxNodes> nodes;
-};
-
-static_assert(sizeof(EAPoLLogoffPacket) == 0x298, "EAPoLLogoffPacket has the wrong size");
-
-/**
- * Generates an unencrypted 802.11 data payload.
- * @returns The generated frame payload.
- */
-std::vector<u8> GenerateDataPayload(const std::vector<u8>& data, u8 channel, u16 dest_node,
- u16 src_node, u16 sequence_number);
-
-/*
- * Generates an unencrypted 802.11 data frame body with the EAPoL-Start format for UDS
- * communication.
- * @returns The generated frame body.
- */
-std::vector<u8> GenerateEAPoLStartFrame(u16 association_id, const NodeInfo& node_info);
-
-/*
- * Returns the EtherType of the specified 802.11 frame.
- */
-EtherType GetFrameEtherType(const std::vector<u8>& frame);
-
-/*
- * Returns the EAPoL type (Start / Logoff) of the specified 802.11 frame.
- * Note: The frame *must* be an EAPoL frame.
- */
-u16 GetEAPoLFrameType(const std::vector<u8>& frame);
-
-/*
- * Returns a deserialized NodeInfo structure from the information inside an EAPoL-Start packet
- * encapsulated in an 802.11 data frame.
- */
-NodeInfo DeserializeNodeInfoFromFrame(const std::vector<u8>& frame);
-
-/*
- * Returns a NodeInfo constructed from the data in the specified EAPoLNodeInfo.
- */
-NodeInfo DeserializeNodeInfo(const EAPoLNodeInfo& node);
-
-/*
- * Generates an unencrypted 802.11 data frame body with the EAPoL-Logoff format for UDS
- * communication.
- * @returns The generated frame body.
- */
-std::vector<u8> GenerateEAPoLLogoffFrame(const MacAddress& mac_address, u16 network_node_id,
- const NodeList& nodes, u8 max_nodes, u8 total_nodes);
-
-/*
- * Returns a EAPoLLogoffPacket representing the specified 802.11-encapsulated data frame.
- */
-EAPoLLogoffPacket ParseEAPoLLogoffFrame(const std::vector<u8>& frame);
-
-} // namespace NWM
-} // namespace Service