Services/UDS: Add functions to generate 802.11 auth and assoc response frames.
This commit is contained in:
parent
22e7402ab1
commit
54411bef4e
|
@ -144,6 +144,7 @@ set(SRCS
|
||||||
hle/service/nwm/nwm_tst.cpp
|
hle/service/nwm/nwm_tst.cpp
|
||||||
hle/service/nwm/nwm_uds.cpp
|
hle/service/nwm/nwm_uds.cpp
|
||||||
hle/service/nwm/uds_beacon.cpp
|
hle/service/nwm/uds_beacon.cpp
|
||||||
|
hle/service/nwm/uds_connection.cpp
|
||||||
hle/service/nwm/uds_data.cpp
|
hle/service/nwm/uds_data.cpp
|
||||||
hle/service/pm_app.cpp
|
hle/service/pm_app.cpp
|
||||||
hle/service/ptm/ptm.cpp
|
hle/service/ptm/ptm.cpp
|
||||||
|
@ -342,6 +343,7 @@ set(HEADERS
|
||||||
hle/service/nwm/nwm_tst.h
|
hle/service/nwm/nwm_tst.h
|
||||||
hle/service/nwm/nwm_uds.h
|
hle/service/nwm/nwm_uds.h
|
||||||
hle/service/nwm/uds_beacon.h
|
hle/service/nwm/uds_beacon.h
|
||||||
|
hle/service/nwm/uds_connection.h
|
||||||
hle/service/nwm/uds_data.h
|
hle/service/nwm/uds_data.h
|
||||||
hle/service/pm_app.h
|
hle/service/pm_app.h
|
||||||
hle/service/ptm/ptm.h
|
hle/service/ptm/ptm.h
|
||||||
|
|
|
@ -42,6 +42,7 @@ using NodeList = std::vector<NodeInfo>;
|
||||||
enum class NetworkStatus {
|
enum class NetworkStatus {
|
||||||
NotConnected = 3,
|
NotConnected = 3,
|
||||||
ConnectedAsHost = 6,
|
ConnectedAsHost = 6,
|
||||||
|
Connecting = 7,
|
||||||
ConnectedAsClient = 9,
|
ConnectedAsClient = 9,
|
||||||
ConnectedAsSpectator = 10,
|
ConnectedAsSpectator = 10,
|
||||||
};
|
};
|
||||||
|
@ -85,6 +86,17 @@ static_assert(offsetof(NetworkInfo, oui_value) == 0xC, "oui_value is at the wron
|
||||||
static_assert(offsetof(NetworkInfo, wlan_comm_id) == 0x10, "wlancommid 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.");
|
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 {
|
class NWM_UDS final : public Interface {
|
||||||
public:
|
public:
|
||||||
NWM_UDS();
|
NWM_UDS();
|
||||||
|
|
|
@ -17,17 +17,6 @@ namespace NWM {
|
||||||
using MacAddress = std::array<u8, 6>;
|
using MacAddress = std::array<u8, 6>;
|
||||||
constexpr std::array<u8, 3> NintendoOUI = {0x00, 0x1F, 0x32};
|
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
|
* Internal vendor-specific tag ids as stored inside
|
||||||
* VendorSpecific blocks in the Beacon frames.
|
* VendorSpecific blocks in the Beacon frames.
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace NWM
|
||||||
|
} // namespace Service
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright 2017 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
} // namespace NWM
|
||||||
|
} // namespace Service
|
Reference in New Issue