mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Services/UDS: Add functions to generate 802.11 auth and assoc response frames.
This commit is contained in:
		@@ -42,6 +42,7 @@ using NodeList = std::vector<NodeInfo>;
 | 
			
		||||
enum class NetworkStatus {
 | 
			
		||||
    NotConnected = 3,
 | 
			
		||||
    ConnectedAsHost = 6,
 | 
			
		||||
    Connecting = 7,
 | 
			
		||||
    ConnectedAsClient = 9,
 | 
			
		||||
    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(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();
 | 
			
		||||
 
 | 
			
		||||
@@ -17,17 +17,6 @@ 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.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										79
									
								
								src/core/hle/service/nwm/uds_connection.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/core/hle/service/nwm/uds_connection.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										51
									
								
								src/core/hle/service/nwm/uds_connection.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/core/hle/service/nwm/uds_connection.h
									
									
									
									
									
										Normal file
									
								
							@@ -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
	
	Block a user