summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/nwm/uds_beacon.h
blob: caacf4c6fa190fc231672086c4e2e03965790e0f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// 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};

/// 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