diff options
Diffstat (limited to 'src/core/hle/service/nwm/uds_beacon.h')
-rw-r--r-- | src/core/hle/service/nwm/uds_beacon.h | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/core/hle/service/nwm/uds_beacon.h b/src/core/hle/service/nwm/uds_beacon.h new file mode 100644 index 000000000..6df4c4f47 --- /dev/null +++ b/src/core/hle/service/nwm/uds_beacon.h @@ -0,0 +1,173 @@ +// 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>; + +/// The maximum number of nodes that can exist in an UDS session. +constexpr u32 UDSMaxNodes = 16; +constexpr std::array<u8, 3> NintendoOUI = {0x00, 0x1F, 0x32}; + +/// Additional block tag ids in the Beacon frames +enum class TagId : u8 { + SSID = 0, + SupportedRates = 1, + DSParameterSet = 2, + TrafficIndicationMap = 5, + CountryInformation = 7, + ERPInformation = 42, + VendorSpecific = 221 +}; + +/** + * 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."); + +/// Information about a received WiFi packet. +/// Acts as our own 802.11 header. +struct WifiPacket { + enum class PacketType { Beacon, Data }; + + PacketType type; ///< The type of 802.11 frame, Beacon / Data. + + /// Raw 802.11 frame data, starting at the management frame header for management frames. + std::vector<u8> data; + MacAddress transmitter_address; ///< Mac address of the transmitter. + MacAddress destination_address; ///< Mac address of the receiver. + u8 channel; ///< WiFi channel where this frame was transmitted. +}; + +/** + * 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); + +/** + * Returns a list of received 802.11 frames from the specified sender + * matching the type since the last call. + */ +std::deque<WifiPacket> GetReceivedPackets(WifiPacket::PacketType type, const MacAddress& sender); +} // namespace NWM +} // namespace Service |