From 583925045e713dd0f9025acba4cc3399f9497c19 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Fri, 1 Apr 2022 10:39:04 -0700 Subject: [PATCH] clean up memory handling for client configs --- src/Client.cc | 8 +++++++- src/Client.hh | 7 ++++++- src/CommandFormats.hh | 16 +++++++++------- src/ProxyServer.cc | 8 +++----- src/ReceiveCommands.cc | 4 ++-- src/SendCommands.cc | 2 +- 6 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/Client.cc b/src/Client.cc index aa1cd7b8..bd93c05b 100644 --- a/src/Client.cc +++ b/src/Client.cc @@ -65,7 +65,13 @@ ClientConfig Client::export_config() const { cc.proxy_destination_address = this->proxy_destination_address; cc.proxy_destination_port = this->proxy_destination_port; cc.unused.clear(0xFF); - cc.unused_bb_only.clear(0xFF); + return cc; +} + +ClientConfigBB Client::export_config_bb() const { + ClientConfigBB cc; + cc.cfg = this->export_config(); + cc.unused.clear(0xFF); return cc; } diff --git a/src/Client.hh b/src/Client.hh index 76b34e6e..05b25c46 100644 --- a/src/Client.hh +++ b/src/Client.hh @@ -34,7 +34,11 @@ struct ClientConfig { uint32_t proxy_destination_address; uint16_t proxy_destination_port; parray unused; - parray unused_bb_only; +} __attribute__((packed)); + +struct ClientConfigBB { + ClientConfig cfg; + parray unused; } __attribute__((packed)); struct Client { @@ -91,5 +95,6 @@ struct Client { ServerBehavior server_behavior); ClientConfig export_config() const; + ClientConfigBB export_config_bb() const; void import_config(const ClientConfig& cc); }; diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index ca2510c1..37677020 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -579,7 +579,7 @@ struct C_Login_BB_93 { ptext unused2; ptext password; ptext unused3; - ClientConfig cfg; + ClientConfigBB client_config; }; // 94: Invalid command @@ -649,11 +649,13 @@ struct C_Login_PC_GC_9D_9E { ptext serial_number2; ptext access_key2; ptext name; - // Note: there are 8 bytes at the end of cfg that are technically not - // included in the client config on GC, but the field after it is - // sufficiently large and unused anyway - ClientConfig cfg; - parray unused4; + union ClientConfigFields { + ClientConfig cfg; + parray data; + + ClientConfigFields() : cfg() { } + } client_config; + parray unused4; }; // 9F: Invalid command @@ -1081,7 +1083,7 @@ struct S_ClientInit_BB_E6 { le_uint32_t player_tag; le_uint32_t guild_card_number; le_uint32_t team_id; - ClientConfig cfg; + ClientConfigBB cfg; le_uint32_t caps; // should be 0x00000102 }; diff --git a/src/ProxyServer.cc b/src/ProxyServer.cc index d9dc8c51..8e3049ad 100644 --- a/src/ProxyServer.cc +++ b/src/ProxyServer.cc @@ -204,8 +204,7 @@ void ProxyServer::UnlinkedSession::on_client_input() { serial_number, cmd->access_key.c_str(), nullptr); sub_version = cmd->sub_version; character_name = cmd->name; - memcpy(&client_config, &cmd->cfg, offsetof(ClientConfig, unused_bb_only)); - client_config.unused_bb_only.clear(0xFF); + client_config = cmd->client_config.cfg; } catch (const exception& e) { log(ERROR, "[ProxyServer] Unlinked client has no valid license"); should_close_unlinked_session = true; @@ -626,7 +625,6 @@ void ProxyServer::LinkedSession::on_server_input() { // did (when it was in an unlinked session). if (command == 0x17) { C_VerifyLicense_GC_DB cmd; - memset(&cmd, 0, sizeof(cmd)); cmd.serial_number = string_printf("%08" PRIX32 "", this->license->serial_number); cmd.access_key = this->license->access_key; @@ -664,7 +662,7 @@ void ProxyServer::LinkedSession::on_server_input() { cmd.serial_number2 = cmd.serial_number; cmd.access_key2 = cmd.access_key; cmd.name = this->character_name; - memcpy(&cmd.cfg, this->remote_client_config_data.data(), 0x20); + cmd.client_config.data = this->remote_client_config_data; // If there's a guild card number, a shorter 9E is sent that ends // right after the client config data @@ -675,7 +673,7 @@ void ProxyServer::LinkedSession::on_server_input() { 0x9E, 0x01, &cmd, - this->guild_card_number ? (offsetof(C_Login_PC_GC_9D_9E, cfg) + 0x20) : sizeof(cmd), + this->guild_card_number ? offsetof(C_Login_PC_GC_9D_9E, unused4) : sizeof(cmd), name.c_str()); break; } diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index d633a9b7..dea467e9 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -335,7 +335,7 @@ void process_login_d_e_pc_gc(shared_ptr s, shared_ptr c, } try { - c->import_config(cmd.cfg); + c->import_config(cmd.client_config.cfg); } catch (const invalid_argument&) { // If we can't import the config, assume that the client was not connected // to newserv before, so we should show the welcome message. @@ -370,7 +370,7 @@ void process_login_bb(shared_ptr s, shared_ptr c, } try { - c->import_config(cmd.cfg); + c->import_config(cmd.client_config.cfg); c->bb_game_state++; } catch (const invalid_argument&) { c->bb_game_state = 0; diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 2ab378d0..57cbbaf8 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -278,7 +278,7 @@ void send_client_init_bb(shared_ptr c, uint32_t error) { cmd.player_tag = 0x00010000; cmd.guild_card_number = c->license->serial_number; cmd.team_id = static_cast(random_object()); - cmd.cfg = c->export_config(); + cmd.cfg = c->export_config_bb(); cmd.caps = 0x00000102; send_command(c, 0x00E6, 0x00000000, cmd); }