mirror of
https://github.com/azahar-emu/azahar
synced 2025-11-06 23:19:57 +01:00
Improve DLP and multiplayer compatability (#1375)
* Added NWM spectator mode (DLP now partially working), fixed debug assert, added applet utility cmd fallback * Reverted AppletUtility command change * Fixed inconsistent mac address * Enabled DLP Child authorization * Added the DLP module to recommended online modules * Clean up * Changed the returned number of words on GetProgramInfoFromCia to 7 insteead of 8, futher reverted AppletUtility function to match its original form
This commit is contained in:
parent
eb1197a65c
commit
0be78e9550
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
@ -90,7 +90,8 @@ void DirectConnectWindow::Connect() {
|
|||||||
room_member->Join(ui->nickname->text().toStdString(),
|
room_member->Join(ui->nickname->text().toStdString(),
|
||||||
Service::CFG::GetConsoleIdHash(system),
|
Service::CFG::GetConsoleIdHash(system),
|
||||||
ui->ip->text().toStdString().c_str(), port, 0,
|
ui->ip->text().toStdString().c_str(), port, 0,
|
||||||
Network::NoPreferredMac, ui->password->text().toStdString().c_str());
|
Service::CFG::GetConsoleMacAddress(system),
|
||||||
|
ui->password->text().toStdString().c_str());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
watcher->setFuture(f);
|
watcher->setFuture(f);
|
||||||
|
|||||||
@ -193,8 +193,8 @@ void HostRoomWindow::Host() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
member->Join(ui->username->text().toStdString(), Service::CFG::GetConsoleIdHash(system),
|
member->Join(ui->username->text().toStdString(), Service::CFG::GetConsoleIdHash(system),
|
||||||
"127.0.0.1", static_cast<u16>(port), 0, Network::NoPreferredMac, password,
|
"127.0.0.1", static_cast<u16>(port), 0,
|
||||||
token);
|
Service::CFG::GetConsoleMacAddress(system), password, token);
|
||||||
|
|
||||||
// Store settings
|
// Store settings
|
||||||
UISettings::values.room_nickname = ui->username->text();
|
UISettings::values.room_nickname = ui->username->text();
|
||||||
|
|||||||
@ -175,7 +175,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
|
|||||||
#endif
|
#endif
|
||||||
if (auto room_member = Network::GetRoomMember().lock()) {
|
if (auto room_member = Network::GetRoomMember().lock()) {
|
||||||
room_member->Join(nickname, Service::CFG::GetConsoleIdHash(system), ip.c_str(),
|
room_member->Join(nickname, Service::CFG::GetConsoleIdHash(system), ip.c_str(),
|
||||||
static_cast<u16>(port), 0, Network::NoPreferredMac, password, token);
|
static_cast<u16>(port), 0, Service::CFG::GetConsoleMacAddress(system),
|
||||||
|
password, token);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
watcher->setFuture(f);
|
watcher->setFuture(f);
|
||||||
|
|||||||
@ -67,6 +67,9 @@ HackManager hack_manager = {
|
|||||||
0x0004013000002C02, // Normal
|
0x0004013000002C02, // Normal
|
||||||
0x0004013000002C03, // Safe mode
|
0x0004013000002C03, // Safe mode
|
||||||
0x0004013020002C03, // New 3DS safe mode
|
0x0004013020002C03, // New 3DS safe mode
|
||||||
|
|
||||||
|
// DLP
|
||||||
|
0x0004013000002802,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
|||||||
@ -3255,9 +3255,15 @@ void Module::Interface::BeginImportProgramTemporarily(Kernel::HLERequestContext&
|
|||||||
// Create our CIAFile handle for the app to write to, and while the app writes Citra will store
|
// Create our CIAFile handle for the app to write to, and while the app writes Citra will store
|
||||||
// contents out to sdmc/nand
|
// contents out to sdmc/nand
|
||||||
const FileSys::Path cia_path = {};
|
const FileSys::Path cia_path = {};
|
||||||
auto file = std::make_shared<Service::FS::File>(
|
std::shared_ptr<Service::FS::File> file;
|
||||||
am->system.Kernel(), std::make_unique<CIAFile>(am->system, FS::MediaType::NAND), cia_path);
|
{
|
||||||
|
auto cia_file = std::make_unique<CIAFile>(am->system, FS::MediaType::NAND);
|
||||||
|
|
||||||
|
AuthorizeCIAFileDecryption(cia_file.get(), ctx);
|
||||||
|
|
||||||
|
file =
|
||||||
|
std::make_shared<Service::FS::File>(am->system.Kernel(), std::move(cia_file), cia_path);
|
||||||
|
}
|
||||||
am->cia_installing = true;
|
am->cia_installing = true;
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||||
@ -3448,7 +3454,7 @@ void Module::Interface::GetProgramInfoFromCia(Kernel::HLERequestContext& ctx) {
|
|||||||
title_info.version = tmd.GetTitleVersion();
|
title_info.version = tmd.GetTitleVersion();
|
||||||
title_info.type = tmd.GetTitleType();
|
title_info.type = tmd.GetTitleType();
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(8, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(7, 0);
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw<TitleInfo>(title_info);
|
rb.PushRaw<TitleInfo>(title_info);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1264,6 +1264,10 @@ std::string GetConsoleIdHash(Core::System& system) {
|
|||||||
return fmt::format("{:02x}", fmt::join(hash.begin(), hash.end(), ""));
|
return fmt::format("{:02x}", fmt::join(hash.begin(), hash.end(), ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<u8, 6> GetConsoleMacAddress(Core::System& system) {
|
||||||
|
return MacToArray(GetModule(system)->GetMacAddress());
|
||||||
|
}
|
||||||
|
|
||||||
std::array<u8, 6> MacToArray(const std::string& mac) {
|
std::array<u8, 6> MacToArray(const std::string& mac) {
|
||||||
std::array<u8, 6> ret;
|
std::array<u8, 6> ret;
|
||||||
int last = -1;
|
int last = -1;
|
||||||
|
|||||||
@ -672,6 +672,8 @@ u64 MacToU64(const std::string& mac);
|
|||||||
|
|
||||||
std::string GenerateRandomMAC();
|
std::string GenerateRandomMAC();
|
||||||
|
|
||||||
|
std::array<u8, 6> GetConsoleMacAddress(Core::System& system);
|
||||||
|
|
||||||
} // namespace Service::CFG
|
} // namespace Service::CFG
|
||||||
|
|
||||||
SERVICE_CONSTRUCT(Service::CFG::Module)
|
SERVICE_CONSTRUCT(Service::CFG::Module)
|
||||||
|
|||||||
@ -106,15 +106,19 @@ void NWM_UDS::BroadcastNodeMap() {
|
|||||||
packet.channel = network_channel;
|
packet.channel = network_channel;
|
||||||
packet.type = Network::WifiPacket::PacketType::NodeMap;
|
packet.type = Network::WifiPacket::PacketType::NodeMap;
|
||||||
packet.destination_address = Network::BroadcastMac;
|
packet.destination_address = Network::BroadcastMac;
|
||||||
std::size_t num_entries = std::count_if(node_map.begin(), node_map.end(),
|
auto node_can_broad = [](auto& node) -> bool {
|
||||||
[](const auto& node) { return node.second.connected; });
|
return node.second.connected && !node.second.spec;
|
||||||
|
};
|
||||||
|
std::size_t num_entries =
|
||||||
|
std::count_if(node_map.begin(), node_map.end(),
|
||||||
|
[&node_can_broad](const auto& node) { return node_can_broad(node); });
|
||||||
using node_t = decltype(node_map)::value_type;
|
using node_t = decltype(node_map)::value_type;
|
||||||
packet.data.resize(sizeof(num_entries) +
|
packet.data.resize(sizeof(num_entries) +
|
||||||
(sizeof(node_t::first) + sizeof(node_t::second.node_id)) * num_entries);
|
(sizeof(node_t::first) + sizeof(node_t::second.node_id)) * num_entries);
|
||||||
std::memcpy(packet.data.data(), &num_entries, sizeof(num_entries));
|
std::memcpy(packet.data.data(), &num_entries, sizeof(num_entries));
|
||||||
std::size_t offset = sizeof(num_entries);
|
std::size_t offset = sizeof(num_entries);
|
||||||
for (const auto& node : node_map) {
|
for (const auto& node : node_map) {
|
||||||
if (node.second.connected) {
|
if (node_can_broad(node)) {
|
||||||
std::memcpy(packet.data.data() + offset, node.first.data(), sizeof(node.first));
|
std::memcpy(packet.data.data() + offset, node.first.data(), sizeof(node.first));
|
||||||
std::memcpy(packet.data.data() + offset + sizeof(node.first), &node.second.node_id,
|
std::memcpy(packet.data.data() + offset + sizeof(node.first), &node.second.node_id,
|
||||||
sizeof(node.second.node_id));
|
sizeof(node.second.node_id));
|
||||||
@ -185,7 +189,8 @@ void NWM_UDS::HandleAssociationResponseFrame(const Network::WifiPacket& packet)
|
|||||||
using Network::WifiPacket;
|
using Network::WifiPacket;
|
||||||
WifiPacket eapol_start;
|
WifiPacket eapol_start;
|
||||||
eapol_start.channel = network_channel;
|
eapol_start.channel = network_channel;
|
||||||
eapol_start.data = GenerateEAPoLStartFrame(std::get<u16>(assoc_result), current_node);
|
eapol_start.data =
|
||||||
|
GenerateEAPoLStartFrame(std::get<u16>(assoc_result), conn_type, current_node);
|
||||||
// TODO(B3N30): Encrypt the packet.
|
// TODO(B3N30): Encrypt the packet.
|
||||||
eapol_start.destination_address = packet.transmitter_address;
|
eapol_start.destination_address = packet.transmitter_address;
|
||||||
eapol_start.type = WifiPacket::PacketType::Data;
|
eapol_start.type = WifiPacket::PacketType::Data;
|
||||||
@ -217,24 +222,36 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) {
|
|||||||
|
|
||||||
ASSERT(connection_status.max_nodes != connection_status.total_nodes);
|
ASSERT(connection_status.max_nodes != connection_status.total_nodes);
|
||||||
|
|
||||||
auto node = DeserializeNodeInfoFromFrame(packet.data);
|
auto eapol_start = DeserializeEAPolStartPacket(packet.data);
|
||||||
|
|
||||||
// Get an unused network node id
|
auto node = DeserializeNodeInfo(eapol_start.node);
|
||||||
u16 node_id = GetNextAvailableNodeId();
|
|
||||||
node.network_node_id = node_id;
|
|
||||||
|
|
||||||
connection_status.node_bitmask |= 1 << (node_id - 1);
|
if (eapol_start.conn_type == ConnectionType::Client) {
|
||||||
connection_status.changed_nodes |= 1 << (node_id - 1);
|
// Get an unused network node id
|
||||||
connection_status.nodes[node_id - 1] = node.network_node_id;
|
u16 node_id = GetNextAvailableNodeId();
|
||||||
connection_status.total_nodes++;
|
node.network_node_id = node_id;
|
||||||
|
|
||||||
node_info[node_id - 1] = node;
|
connection_status.node_bitmask |= 1 << (node_id - 1);
|
||||||
network_info.total_nodes++;
|
connection_status.changed_nodes |= 1 << (node_id - 1);
|
||||||
|
connection_status.nodes[node_id - 1] = node.network_node_id;
|
||||||
|
connection_status.total_nodes++;
|
||||||
|
|
||||||
node_map[packet.transmitter_address].node_id = node.network_node_id;
|
node_info[node_id - 1] = node;
|
||||||
node_map[packet.transmitter_address].connected = true;
|
network_info.total_nodes++;
|
||||||
|
|
||||||
BroadcastNodeMap();
|
node_map[packet.transmitter_address].node_id = node.network_node_id;
|
||||||
|
node_map[packet.transmitter_address].connected = true;
|
||||||
|
node_map[packet.transmitter_address].spec = false;
|
||||||
|
|
||||||
|
BroadcastNodeMap();
|
||||||
|
} else if (eapol_start.conn_type == ConnectionType::Spectator) {
|
||||||
|
node_map[packet.transmitter_address].node_id = NodeIDSpec;
|
||||||
|
node_map[packet.transmitter_address].connected = true;
|
||||||
|
node_map[packet.transmitter_address].spec = true;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR(Service_NWM, "Client tried connecting with unknown connection type: 0x{:x}",
|
||||||
|
static_cast<u32>(eapol_start.conn_type));
|
||||||
|
}
|
||||||
|
|
||||||
// Send the EAPoL-Logoff packet.
|
// Send the EAPoL-Logoff packet.
|
||||||
using Network::WifiPacket;
|
using Network::WifiPacket;
|
||||||
@ -282,15 +299,23 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) {
|
|||||||
node_info[index - 1] = DeserializeNodeInfo(node);
|
node_info[index - 1] = DeserializeNodeInfo(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn_type == ConnectionType::Client) {
|
||||||
|
connection_status.status = NetworkStatus::ConnectedAsClient;
|
||||||
|
} else if (conn_type == ConnectionType::Spectator) {
|
||||||
|
connection_status.status = NetworkStatus::ConnectedAsSpectator;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR(Service_NWM, "Unknown connection type: 0x{:x}", static_cast<u32>(conn_type));
|
||||||
|
}
|
||||||
|
|
||||||
// We're now connected, signal the application
|
// We're now connected, signal the application
|
||||||
connection_status.status = NetworkStatus::ConnectedAsClient;
|
|
||||||
connection_status.status_change_reason = NetworkStatusChangeReason::ConnectionEstablished;
|
connection_status.status_change_reason = NetworkStatusChangeReason::ConnectionEstablished;
|
||||||
// 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
|
||||||
connection_status_event->Signal();
|
connection_status_event->Signal();
|
||||||
connection_event->Signal();
|
connection_event->Signal();
|
||||||
} else if (connection_status.status == NetworkStatus::ConnectedAsClient) {
|
} else if (connection_status.status == NetworkStatus::ConnectedAsClient ||
|
||||||
|
connection_status.status == NetworkStatus::ConnectedAsSpectator) {
|
||||||
// TODO(B3N30): Remove that section and send/receive a proper connection_status packet
|
// TODO(B3N30): Remove that section and send/receive a proper connection_status packet
|
||||||
// On a 3ds this packet wouldn't be addressed to already connected clients
|
// On a 3ds this packet wouldn't be addressed to already connected clients
|
||||||
// We use this information because in the current implementation the host
|
// We use this information because in the current implementation the host
|
||||||
@ -328,9 +353,9 @@ void NWM_UDS::HandleSecureDataPacket(const Network::WifiPacket& packet) {
|
|||||||
std::scoped_lock lock{connection_status_mutex, system.Kernel().GetHLELock()};
|
std::scoped_lock lock{connection_status_mutex, system.Kernel().GetHLELock()};
|
||||||
|
|
||||||
if (connection_status.status != NetworkStatus::ConnectedAsHost &&
|
if (connection_status.status != NetworkStatus::ConnectedAsHost &&
|
||||||
connection_status.status != NetworkStatus::ConnectedAsClient) {
|
connection_status.status != NetworkStatus::ConnectedAsClient &&
|
||||||
// TODO(B3N30): Handle spectators
|
connection_status.status != NetworkStatus::ConnectedAsSpectator) {
|
||||||
LOG_DEBUG(Service_NWM, "Ignored SecureDataPacket, because connection status is {}",
|
LOG_DEBUG(Service_NWM, "Ignored SecureDataPacket because connection status is {}",
|
||||||
static_cast<u32>(connection_status.status));
|
static_cast<u32>(connection_status.status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -370,12 +395,14 @@ void NWM_UDS::HandleSecureDataPacket(const Network::WifiPacket& packet) {
|
|||||||
// TODO(B3N30): Allow more than one bind node per channel.
|
// TODO(B3N30): Allow more than one bind node per channel.
|
||||||
auto channel_info = channel_data.find(secure_data.data_channel);
|
auto channel_info = channel_data.find(secure_data.data_channel);
|
||||||
// Ignore packets from channels we're not interested in.
|
// Ignore packets from channels we're not interested in.
|
||||||
if (channel_info == channel_data.end())
|
if (channel_info == channel_data.end()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (channel_info->second.network_node_id != BroadcastNetworkNodeId &&
|
if (channel_info->second.network_node_id != BroadcastNetworkNodeId &&
|
||||||
channel_info->second.network_node_id != secure_data.src_node_id)
|
channel_info->second.network_node_id != secure_data.src_node_id) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Add the received packet to the data queue.
|
// Add the received packet to the data queue.
|
||||||
channel_info->second.received_packets.emplace_back(packet.data);
|
channel_info->second.received_packets.emplace_back(packet.data);
|
||||||
@ -432,7 +459,9 @@ void NWM_UDS::HandleAuthenticationFrame(const Network::WifiPacket& packet) {
|
|||||||
// Only the SEQ1 auth frame is handled here, the SEQ2 frame doesn't need any special behavior
|
// Only the SEQ1 auth frame is handled here, the SEQ2 frame doesn't need any special behavior
|
||||||
if (GetAuthenticationSeqNumber(packet.data) == AuthenticationSeq::SEQ1) {
|
if (GetAuthenticationSeqNumber(packet.data) == AuthenticationSeq::SEQ1) {
|
||||||
using Network::WifiPacket;
|
using Network::WifiPacket;
|
||||||
WifiPacket auth_request;
|
AuthenticationFrame auth_request;
|
||||||
|
memcpy(&auth_request, packet.data.data(), sizeof(auth_request));
|
||||||
|
WifiPacket auth_response;
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(connection_status_mutex);
|
std::scoped_lock lock(connection_status_mutex);
|
||||||
if (connection_status.status != NetworkStatus::ConnectedAsHost) {
|
if (connection_status.status != NetworkStatus::ConnectedAsHost) {
|
||||||
@ -454,13 +483,13 @@ void NWM_UDS::HandleAuthenticationFrame(const Network::WifiPacket& packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Respond with an authentication response frame with SEQ2
|
// Respond with an authentication response frame with SEQ2
|
||||||
auth_request.channel = network_channel;
|
auth_response.channel = network_channel;
|
||||||
auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ2);
|
auth_response.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ2);
|
||||||
auth_request.destination_address = packet.transmitter_address;
|
auth_response.destination_address = packet.transmitter_address;
|
||||||
auth_request.type = WifiPacket::PacketType::Authentication;
|
auth_response.type = WifiPacket::PacketType::Authentication;
|
||||||
node_map[packet.transmitter_address].connected = false;
|
node_map[packet.transmitter_address].connected = false;
|
||||||
}
|
}
|
||||||
SendPacket(auth_request);
|
SendPacket(auth_response);
|
||||||
|
|
||||||
SendAssociationResponseFrame(packet.transmitter_address);
|
SendAssociationResponseFrame(packet.transmitter_address);
|
||||||
}
|
}
|
||||||
@ -495,16 +524,16 @@ void NWM_UDS::HandleDeauthenticationFrame(const Network::WifiPacket& packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_status.node_bitmask &= ~(1 << (node.node_id - 1));
|
if (!node.spec) {
|
||||||
connection_status.changed_nodes |= 1 << (node.node_id - 1);
|
connection_status.node_bitmask &= ~(1 << (node.node_id - 1));
|
||||||
connection_status.total_nodes--;
|
connection_status.changed_nodes |= 1 << (node.node_id - 1);
|
||||||
connection_status.nodes[node.node_id - 1] = 0;
|
connection_status.total_nodes--;
|
||||||
|
connection_status.nodes[node.node_id - 1] = 0;
|
||||||
network_info.total_nodes--;
|
|
||||||
// TODO(B3N30): broadcast new connection_status to clients
|
|
||||||
|
|
||||||
|
network_info.total_nodes--;
|
||||||
|
// TODO(B3N30): broadcast new connection_status to clients
|
||||||
|
}
|
||||||
node_it->Reset();
|
node_it->Reset();
|
||||||
|
|
||||||
connection_status_event->Signal();
|
connection_status_event->Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,14 +617,19 @@ void NWM_UDS::RecvBeaconBroadcastData(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
u32 out_buffer_size = rp.Pop<u32>();
|
u32 out_buffer_size = rp.Pop<u32>();
|
||||||
|
|
||||||
|
// scan input struct
|
||||||
u32 unk1 = rp.Pop<u32>();
|
u32 unk1 = rp.Pop<u32>();
|
||||||
u32 unk2 = rp.Pop<u32>();
|
u32 unk2 = rp.Pop<u32>();
|
||||||
|
|
||||||
MacAddress mac_address;
|
MacAddress mac_address;
|
||||||
rp.PopRaw(mac_address);
|
rp.PopRaw(mac_address);
|
||||||
|
|
||||||
|
// uninitialized data in scan input struct
|
||||||
rp.Skip(9, false);
|
rp.Skip(9, false);
|
||||||
|
|
||||||
|
// end scan input struct
|
||||||
|
|
||||||
u32 wlan_comm_id = rp.Pop<u32>();
|
u32 wlan_comm_id = rp.Pop<u32>();
|
||||||
u32 id = rp.Pop<u32>();
|
u32 id = rp.Pop<u32>();
|
||||||
// From 3dbrew:
|
// From 3dbrew:
|
||||||
@ -1042,6 +1076,7 @@ void NWM_UDS::DestroyNetwork(Kernel::HLERequestContext& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NWM_UDS::DisconnectNetwork(Kernel::HLERequestContext& ctx) {
|
void NWM_UDS::DisconnectNetwork(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_NWM, "disconnecting from network");
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
|
||||||
@ -1277,6 +1312,7 @@ void NWM_UDS::ConnectToNetwork(Kernel::HLERequestContext& ctx, u16 command_id,
|
|||||||
std::vector<u8> passphrase) {
|
std::vector<u8> passphrase) {
|
||||||
network_info = {};
|
network_info = {};
|
||||||
std::memcpy(&network_info, network_info_buffer.data(), network_info_buffer.size());
|
std::memcpy(&network_info, network_info_buffer.data(), network_info_buffer.size());
|
||||||
|
conn_type = static_cast<ConnectionType>(connection_type);
|
||||||
|
|
||||||
// Start the connection sequence
|
// Start the connection sequence
|
||||||
StartConnectionSequence(network_info.host_mac_address);
|
StartConnectionSequence(network_info.host_mac_address);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
@ -18,6 +18,7 @@
|
|||||||
#include <boost/serialization/export.hpp>
|
#include <boost/serialization/export.hpp>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
|
#include "core/hle/service/nwm/uds_common.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
|
|
||||||
@ -47,6 +48,8 @@ const u16 DefaultBeaconInterval = 100;
|
|||||||
/// The maximum number of nodes that can exist in an UDS session.
|
/// The maximum number of nodes that can exist in an UDS session.
|
||||||
constexpr u32 UDSMaxNodes = 16;
|
constexpr u32 UDSMaxNodes = 16;
|
||||||
|
|
||||||
|
constexpr u16 NodeIDSpec = 0;
|
||||||
|
|
||||||
struct NodeInfo {
|
struct NodeInfo {
|
||||||
u64_le friend_code_seed;
|
u64_le friend_code_seed;
|
||||||
std::array<u16_le, 10> username;
|
std::array<u16_le, 10> username;
|
||||||
@ -95,7 +98,7 @@ static_assert(sizeof(ConnectionStatus) == 0x30, "ConnectionStatus has incorrect
|
|||||||
struct NetworkInfo {
|
struct NetworkInfo {
|
||||||
std::array<u8, 6> host_mac_address;
|
std::array<u8, 6> host_mac_address;
|
||||||
u8 channel;
|
u8 channel;
|
||||||
INSERT_PADDING_BYTES(1);
|
u8 unk1;
|
||||||
u8 initialized;
|
u8 initialized;
|
||||||
INSERT_PADDING_BYTES(3);
|
INSERT_PADDING_BYTES(3);
|
||||||
std::array<u8, 3> oui_value;
|
std::array<u8, 3> oui_value;
|
||||||
@ -477,7 +480,7 @@ private:
|
|||||||
void HandleSecureDataPacket(const Network::WifiPacket& packet);
|
void HandleSecureDataPacket(const Network::WifiPacket& packet);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start a connection sequence with an UDS server. The sequence starts by sending an 802.11
|
* Start a connection sequence with a UDS server. The sequence starts by sending an 802.11
|
||||||
* authentication frame with SEQ1.
|
* authentication frame with SEQ1.
|
||||||
*/
|
*/
|
||||||
void StartConnectionSequence(const MacAddress& server);
|
void StartConnectionSequence(const MacAddress& server);
|
||||||
@ -526,6 +529,9 @@ private:
|
|||||||
// Node information about our own system.
|
// Node information about our own system.
|
||||||
NodeInfo current_node;
|
NodeInfo current_node;
|
||||||
|
|
||||||
|
// whether you are connecting as a client or a spec
|
||||||
|
ConnectionType conn_type;
|
||||||
|
|
||||||
struct BindNodeData {
|
struct BindNodeData {
|
||||||
u32 bind_node_id; ///< Id of the bind node associated with this data.
|
u32 bind_node_id; ///< Id of the bind node associated with this data.
|
||||||
u8 channel; ///< Channel that this bind node was bound to.
|
u8 channel; ///< Channel that this bind node was bound to.
|
||||||
@ -548,6 +554,7 @@ private:
|
|||||||
// Mapping of mac addresses to their respective node_ids.
|
// Mapping of mac addresses to their respective node_ids.
|
||||||
struct Node {
|
struct Node {
|
||||||
bool connected;
|
bool connected;
|
||||||
|
bool spec;
|
||||||
u16 node_id;
|
u16 node_id;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
16
src/core/hle/service/nwm/uds_common.h
Normal file
16
src/core/hle/service/nwm/uds_common.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::NWM {
|
||||||
|
|
||||||
|
enum class ConnectionType : u8 {
|
||||||
|
Client = 0x1,
|
||||||
|
Spectator = 0x2,
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace Service::NWM
|
||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
@ -286,9 +286,11 @@ SecureDataHeader ParseSecureDataHeader(std::span<const u8> data) {
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> GenerateEAPoLStartFrame(u16 association_id, const NodeInfo& node_info) {
|
std::vector<u8> GenerateEAPoLStartFrame(u16 association_id, ConnectionType conn_type,
|
||||||
|
const NodeInfo& node_info) {
|
||||||
EAPoLStartPacket eapol_start{};
|
EAPoLStartPacket eapol_start{};
|
||||||
eapol_start.association_id = association_id;
|
eapol_start.association_id = association_id;
|
||||||
|
eapol_start.conn_type = conn_type;
|
||||||
eapol_start.node.friend_code_seed = node_info.friend_code_seed;
|
eapol_start.node.friend_code_seed = node_info.friend_code_seed;
|
||||||
|
|
||||||
std::copy(node_info.username.begin(), node_info.username.end(),
|
std::copy(node_info.username.begin(), node_info.username.end(),
|
||||||
@ -327,13 +329,7 @@ NodeInfo DeserializeNodeInfoFromFrame(std::span<const u8> frame) {
|
|||||||
// Skip the LLC header
|
// Skip the LLC header
|
||||||
std::memcpy(&eapol_start, frame.data() + sizeof(LLCHeader), sizeof(eapol_start));
|
std::memcpy(&eapol_start, frame.data() + sizeof(LLCHeader), sizeof(eapol_start));
|
||||||
|
|
||||||
NodeInfo node{};
|
return DeserializeNodeInfo(eapol_start.node);
|
||||||
node.friend_code_seed = eapol_start.node.friend_code_seed;
|
|
||||||
|
|
||||||
std::copy(eapol_start.node.username.begin(), eapol_start.node.username.end(),
|
|
||||||
node.username.begin());
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeInfo DeserializeNodeInfo(const EAPoLNodeInfo& node) {
|
NodeInfo DeserializeNodeInfo(const EAPoLNodeInfo& node) {
|
||||||
@ -380,4 +376,11 @@ EAPoLLogoffPacket ParseEAPoLLogoffFrame(std::span<const u8> frame) {
|
|||||||
return eapol_logoff;
|
return eapol_logoff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EAPoLStartPacket DeserializeEAPolStartPacket(std::span<const u8> frame) {
|
||||||
|
EAPoLStartPacket eapol_start;
|
||||||
|
|
||||||
|
std::memcpy(&eapol_start, frame.data() + sizeof(LLCHeader), sizeof(eapol_start));
|
||||||
|
return eapol_start;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::NWM
|
} // namespace Service::NWM
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
@ -10,6 +10,7 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/hle/service/nwm/uds_beacon.h"
|
#include "core/hle/service/nwm/uds_beacon.h"
|
||||||
|
#include "core/hle/service/nwm/uds_common.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::NWM {
|
namespace Service::NWM {
|
||||||
@ -90,9 +91,8 @@ constexpr u16 EAPoLStartMagic = 0x201;
|
|||||||
struct EAPoLStartPacket {
|
struct EAPoLStartPacket {
|
||||||
u16_be magic = EAPoLStartMagic;
|
u16_be magic = EAPoLStartMagic;
|
||||||
u16_be association_id;
|
u16_be association_id;
|
||||||
// This value is hardcoded to 1 in the NWM module.
|
enum_le<ConnectionType> conn_type;
|
||||||
u16_be unknown = 1;
|
INSERT_PADDING_BYTES(3);
|
||||||
INSERT_PADDING_BYTES(2);
|
|
||||||
EAPoLNodeInfo node;
|
EAPoLNodeInfo node;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,7 +132,8 @@ SecureDataHeader ParseSecureDataHeader(std::span<const u8> data);
|
|||||||
* communication.
|
* communication.
|
||||||
* @returns The generated frame body.
|
* @returns The generated frame body.
|
||||||
*/
|
*/
|
||||||
std::vector<u8> GenerateEAPoLStartFrame(u16 association_id, const NodeInfo& node_info);
|
std::vector<u8> GenerateEAPoLStartFrame(u16 association_id, ConnectionType conn_type,
|
||||||
|
const NodeInfo& node_info);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the EtherType of the specified 802.11 frame.
|
* Returns the EtherType of the specified 802.11 frame.
|
||||||
@ -151,6 +152,8 @@ u16 GetEAPoLFrameType(std::span<const u8> frame);
|
|||||||
*/
|
*/
|
||||||
NodeInfo DeserializeNodeInfoFromFrame(std::span<const u8> frame);
|
NodeInfo DeserializeNodeInfoFromFrame(std::span<const u8> frame);
|
||||||
|
|
||||||
|
EAPoLStartPacket DeserializeEAPolStartPacket(std::span<const u8> frame);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a NodeInfo constructed from the data in the specified EAPoLNodeInfo.
|
* Returns a NodeInfo constructed from the data in the specified EAPoLNodeInfo.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -78,7 +78,7 @@ const std::array<ServiceModuleInfo, 41> service_module_map{
|
|||||||
false},
|
false},
|
||||||
{"CECD", 0x00040130'00002602, CECD::InstallInterfaces, false},
|
{"CECD", 0x00040130'00002602, CECD::InstallInterfaces, false},
|
||||||
{"CFG", 0x00040130'00001702, CFG::InstallInterfaces, false},
|
{"CFG", 0x00040130'00001702, CFG::InstallInterfaces, false},
|
||||||
{"DLP", 0x00040130'00002802, DLP::InstallInterfaces, false},
|
{"DLP", 0x00040130'00002802, DLP::InstallInterfaces, true},
|
||||||
{"DSP", 0x00040130'00001A02, DSP::InstallInterfaces, false},
|
{"DSP", 0x00040130'00001A02, DSP::InstallInterfaces, false},
|
||||||
{"FRD", 0x00040130'00003202, FRD::InstallInterfaces, true},
|
{"FRD", 0x00040130'00003202, FRD::InstallInterfaces, true},
|
||||||
{"GSP", 0x00040130'00001C02, GSP::InstallInterfaces, false},
|
{"GSP", 0x00040130'00001C02, GSP::InstallInterfaces, false},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user