NWM_UDS: implement disconnect_reason and EjectClient (#5331)

* NWM_UDS: Stub disconnect_reason and EjectClient

* addressed review comments

* fix additional semicolon

Co-authored-by: Valentin Vanelslande <vvanelslandedev@gmail.com>

Co-authored-by: Valentin Vanelslande <vvanelslandedev@gmail.com>
master
Ben 2021-05-16 10:41:54 +07:00 committed by GitHub
parent e7671d93b2
commit 7325f58763
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 2 deletions

@ -279,6 +279,7 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) {
// We're now connected, signal the application // We're now connected, signal the application
connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsClient); connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsClient);
connection_status.disconnect_reason = static_cast<u32>(DisconnectStatus::Connected);
// Some games require ConnectToNetwork to block, for now it doesn't // Some games require ConnectToNetwork to block, for now it doesn't
// If blocking is implemented this lock needs to be changed, // If blocking is implemented this lock needs to be changed,
// otherwise it might cause deadlocks // otherwise it might cause deadlocks
@ -648,6 +649,7 @@ ResultVal<std::shared_ptr<Kernel::Event>> NWM_UDS::Initialize(
// Reset the connection status, it contains all zeros after initialization, // Reset the connection status, it contains all zeros after initialization,
// except for the actual status value. // except for the actual status value.
connection_status = {}; connection_status = {};
connection_status.disconnect_reason = static_cast<u32>(DisconnectStatus::NotConnected);
connection_status.status = static_cast<u32>(NetworkStatus::NotConnected); connection_status.status = static_cast<u32>(NetworkStatus::NotConnected);
node_info.clear(); node_info.clear();
node_info.push_back(current_node); node_info.push_back(current_node);
@ -837,6 +839,7 @@ ResultCode NWM_UDS::BeginHostingNetwork(const u8* network_info_buffer,
ASSERT_MSG(network_info.max_nodes > 1, "Trying to host a network of only one member."); ASSERT_MSG(network_info.max_nodes > 1, "Trying to host a network of only one member.");
connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsHost); connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsHost);
connection_status.disconnect_reason = static_cast<u32>(DisconnectStatus::Connected);
// Ensure the application data size is less than the maximum value. // Ensure the application data size is less than the maximum value.
ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize, ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize,
@ -928,6 +931,57 @@ void NWM_UDS::BeginHostingNetworkDeprecated(Kernel::HLERequestContext& ctx) {
rb.Push(result); rb.Push(result);
} }
void NWM_UDS::EjectClient(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x05, 1, 0);
const u16 network_node_id = rp.Pop<u16>();
LOG_WARNING(Service_NWM, "(stubbed) called");
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
// The host can not be kicked.
if (network_node_id == 1) {
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
ErrorSummary::WrongArgument, ErrorLevel::Usage));
return;
}
std::lock_guard lock(connection_status_mutex);
if (connection_status.status != static_cast<u8>(NetworkStatus::ConnectedAsHost)) {
// Only the host can kick people.
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
ErrorSummary::InvalidState, ErrorLevel::Usage));
LOG_WARNING(Service_NWM, "called with status {}", connection_status.status);
return;
}
// This function always returns success if the status is valid.
rb.Push(RESULT_SUCCESS);
using Network::WifiPacket;
Network::MacAddress dest_address = Network::BroadcastMac;
if (network_node_id != BroadcastNetworkNodeId) {
auto address = GetNodeMacAddress(network_node_id, 0);
if (!address) {
// There is no error if the network node id was not found.
return;
}
dest_address = *address;
}
WifiPacket deauth;
deauth.channel = network_channel;
deauth.destination_address = dest_address;
deauth.type = WifiPacket::PacketType::Deauthentication;
SendPacket(deauth);
if (network_node_id == BroadcastNetworkNodeId) {
SendPacket(deauth);
SendPacket(deauth);
}
}
void NWM_UDS::UpdateNetworkAttribute(Kernel::HLERequestContext& ctx) { void NWM_UDS::UpdateNetworkAttribute(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x07, 2, 0); IPC::RequestParser rp(ctx, 0x07, 2, 0);
rp.Skip(2, false); rp.Skip(2, false);
@ -1394,7 +1448,7 @@ NWM_UDS::NWM_UDS(Core::System& system) : ServiceFramework("nwm::UDS"), system(sy
{0x00020000, nullptr, "Scrap"}, {0x00020000, nullptr, "Scrap"},
{0x00030000, &NWM_UDS::Shutdown, "Shutdown"}, {0x00030000, &NWM_UDS::Shutdown, "Shutdown"},
{0x00040402, &NWM_UDS::BeginHostingNetworkDeprecated, "BeginHostingNetwork (deprecated)"}, {0x00040402, &NWM_UDS::BeginHostingNetworkDeprecated, "BeginHostingNetwork (deprecated)"},
{0x00050040, nullptr, "EjectClient"}, {0x00050040, &NWM_UDS::EjectClient, "EjectClient"},
{0x00060000, nullptr, "EjectSpectator"}, {0x00060000, nullptr, "EjectSpectator"},
{0x00070080, &NWM_UDS::UpdateNetworkAttribute, "UpdateNetworkAttribute"}, {0x00070080, &NWM_UDS::UpdateNetworkAttribute, "UpdateNetworkAttribute"},
{0x00080000, &NWM_UDS::DestroyNetwork, "DestroyNetwork"}, {0x00080000, &NWM_UDS::DestroyNetwork, "DestroyNetwork"},

@ -73,9 +73,15 @@ enum class NetworkStatus {
ConnectedAsSpectator = 10, ConnectedAsSpectator = 10,
}; };
enum class DisconnectStatus {
Connected = 1,
NotConnected = 2,
// TODO(B3N30): Figure out the other values
};
struct ConnectionStatus { struct ConnectionStatus {
u32_le status; u32_le status;
INSERT_PADDING_WORDS(1); u32_le disconnect_reason;
u16_le network_node_id; u16_le network_node_id;
u16_le changed_nodes; u16_le changed_nodes;
u16_le nodes[UDSMaxNodes]; u16_le nodes[UDSMaxNodes];
@ -409,6 +415,17 @@ private:
*/ */
void ConnectToNetworkDeprecated(Kernel::HLERequestContext& ctx); void ConnectToNetworkDeprecated(Kernel::HLERequestContext& ctx);
/**
* NWM_UDS::EjectClient Disconnects clients.
* Inputs:
* 0 : Command header
* 1 : Network node id
* Outputs:
* 0 : Return header
* 1 : Result of function, 0 on success, otherwise error code
*/
void EjectClient(Kernel::HLERequestContext& ctx);
/** /**
* NWM_UDS::DecryptBeaconData service function. * NWM_UDS::DecryptBeaconData service function.
* Decrypts the encrypted data tags contained in the 802.11 beacons. * Decrypts the encrypted data tags contained in the 802.11 beacons.