From c8da3dc6c585b0c1c2d19f40beee7cff8997ef7b Mon Sep 17 00:00:00 2001 From: rtw1x1 Date: Thu, 12 Feb 2026 23:57:32 +0000 Subject: [PATCH] code cleanup removed firewall_manager and experimentals --- src/game/SecureCipher.cpp | 4 - src/game/config.cpp | 43 ------- src/game/config.h | 4 - src/game/desc.cpp | 49 -------- src/game/desc.h | 16 --- src/game/desc_manager.cpp | 39 +----- src/game/desc_manager.h | 2 - src/game/firewall_manager.cpp | 227 ---------------------------------- src/game/firewall_manager.h | 33 ----- src/game/input.cpp | 6 - src/game/input.h | 8 -- src/game/input_main.cpp | 13 +- src/game/main.cpp | 62 ---------- src/game/packet_reader.h | 2 - 14 files changed, 6 insertions(+), 502 deletions(-) delete mode 100644 src/game/firewall_manager.cpp delete mode 100644 src/game/firewall_manager.h diff --git a/src/game/SecureCipher.cpp b/src/game/SecureCipher.cpp index 1b35253..da4a8cb 100644 --- a/src/game/SecureCipher.cpp +++ b/src/game/SecureCipher.cpp @@ -119,10 +119,6 @@ bool SecureCipher::ComputeServerKeys(const uint8_t* client_pk) sodium_memzero(m_rx_stream_nonce, NONCE_SIZE); m_rx_stream_nonce[0] = 0x02; - sys_log(0, "[CIPHER] Server keys computed (tx_key: %02x%02x%02x%02x, rx_key: %02x%02x%02x%02x)", - m_tx_key[0], m_tx_key[1], m_tx_key[2], m_tx_key[3], - m_rx_key[0], m_rx_key[1], m_rx_key[2], m_rx_key[3]); - return true; } diff --git a/src/game/config.cpp b/src/game/config.cpp index 8422297..e7aa635 100644 --- a/src/game/config.cpp +++ b/src/game/config.cpp @@ -101,14 +101,6 @@ bool g_bCheckMultiHack = true; int g_iSpamBlockMaxLevel = 10; -int g_iFloodMaxPacketsPerSec = 300; -int g_iFloodMaxConnectionsPerIP = 10; -int g_iFloodMaxGlobalConnections = 8192; - -bool g_bFirewallEnable = false; -int g_iFirewallTcpSynLimit = 500; -int g_iFirewallTcpSynBurst = 1000; - void LoadStateUserCount(); void LoadValidCRCList(); bool LoadClientVersion(); @@ -703,41 +695,6 @@ void config_init(const string& st_localeServiceName) str_to_number(g_iSpamBlockMaxLevel, value_string); } - TOKEN("flood_max_packets_per_sec") - { - str_to_number(g_iFloodMaxPacketsPerSec, value_string); - g_iFloodMaxPacketsPerSec = MAX(50, g_iFloodMaxPacketsPerSec); - } - - TOKEN("flood_max_connections_per_ip") - { - str_to_number(g_iFloodMaxConnectionsPerIP, value_string); - g_iFloodMaxConnectionsPerIP = MAX(1, g_iFloodMaxConnectionsPerIP); - } - - TOKEN("flood_max_global_connections") - { - str_to_number(g_iFloodMaxGlobalConnections, value_string); - g_iFloodMaxGlobalConnections = MAX(64, g_iFloodMaxGlobalConnections); - } - - TOKEN("firewall_enable") - { - str_to_number(g_bFirewallEnable, value_string); - } - - TOKEN("firewall_tcp_syn_limit") - { - str_to_number(g_iFirewallTcpSynLimit, value_string); - g_iFirewallTcpSynLimit = MAX(10, g_iFirewallTcpSynLimit); - } - - TOKEN("firewall_tcp_syn_burst") - { - str_to_number(g_iFirewallTcpSynBurst, value_string); - g_iFirewallTcpSynBurst = MAX(10, g_iFirewallTcpSynBurst); - } - TOKEN("protect_normal_player") { str_to_number(g_protectNormalPlayer, value_string); diff --git a/src/game/config.h b/src/game/config.h index 13d3548..ce8d3fe 100644 --- a/src/game/config.h +++ b/src/game/config.h @@ -105,9 +105,5 @@ extern int gPlayerMaxLevel; extern bool g_BlockCharCreation; -extern bool g_bFirewallEnable; -extern int g_iFirewallTcpSynLimit; -extern int g_iFirewallTcpSynBurst; - #endif /* __INC_METIN_II_GAME_CONFIG_H__ */ diff --git a/src/game/desc.cpp b/src/game/desc.cpp index 38017e9..2b82ca3 100644 --- a/src/game/desc.cpp +++ b/src/game/desc.cpp @@ -81,10 +81,6 @@ void DESC::Initialize() m_offtime = 0; m_pkDisconnectEvent = NULL; - - m_iFloodCheckPulse = 0; - m_dwFloodPacketCount = 0; - m_bIPCountTracked = false; } void DESC::Destroy() @@ -216,7 +212,6 @@ bool DESC::Setup(LPFDWATCH _fdw, socket_t _fd, const struct sockaddr_in & c_rSoc m_pkPingEvent = event_create(ping_event, info, ping_event_second_cycle); - // Set Phase to handshake and begin secure key exchange SetPhase(PHASE_HANDSHAKE); m_handshake_time = get_dword_time(); SendKeyChallenge(); @@ -242,7 +237,6 @@ int DESC::ProcessInput() else if (bytes_read == 0) return 0; - // Decrypt only the newly received bytes before committing to the buffer if (m_secureCipher.IsActivated()) { m_secureCipher.DecryptInPlace(m_inputBuffer.WritePtr(), bytes_read); } @@ -328,7 +322,6 @@ void DESC::Packet(const void * c_pvData, int iSize) if (m_iPhase == PHASE_CLOSE) return; - // Log the packet for sequence tracking (only for real packet sends, not buffered flushes) if (!m_hasBufferedOutput && iSize >= (int)sizeof(uint16_t) * 2) { const uint16_t wHeader = *static_cast(c_pvData); @@ -465,43 +458,13 @@ bool DESC::IsExpiredHandshake() const return (m_handshake_time + (5 * 1000)) < get_dword_time(); } -bool DESC::CheckPacketFlood() -{ - extern int g_iFloodMaxPacketsPerSec; - - // Use thecore_pulse() (cached per game-loop iteration) instead of - // get_dword_time() (gettimeofday syscall) to avoid per-packet syscall overhead. - int pulse = thecore_pulse(); - int pps = static_cast(thecore_pulse_per_second()); - - if (pulse - m_iFloodCheckPulse >= pps) - { - m_iFloodCheckPulse = pulse; - m_dwFloodPacketCount = 1; - return false; - } - - ++m_dwFloodPacketCount; - - if (m_dwFloodPacketCount > (uint32_t)g_iFloodMaxPacketsPerSec) - { - sys_log(0, "FLOOD: %s exceeded %d packets/sec (count: %u), disconnecting", - GetHostName(), g_iFloodMaxPacketsPerSec, m_dwFloodPacketCount); - return true; - } - - return false; -} - DWORD DESC::GetClientTime() { return m_dwClientTime; } -// Secure key exchange methods (libsodium/XChaCha20-Poly1305) void DESC::SendKeyChallenge() { - // Initialize cipher and generate keypair if (!m_secureCipher.Initialize()) { sys_err("Failed to initialize SecureCipher"); @@ -509,10 +472,8 @@ void DESC::SendKeyChallenge() return; } - // Generate challenge m_secureCipher.GenerateChallenge(m_challenge); - // Build and send challenge packet TPacketGCKeyChallenge packet; packet.header = GC::KEY_CHALLENGE; packet.length = sizeof(packet); @@ -529,14 +490,12 @@ void DESC::SendKeyChallenge() bool DESC::HandleKeyResponse(const uint8_t* client_pk, const uint8_t* challenge_response) { - // Compute session keys from client's public key if (!m_secureCipher.ComputeServerKeys(client_pk)) { sys_err("Failed to compute server session keys for %s", GetHostName()); return false; } - // Verify challenge response if (!m_secureCipher.VerifyChallengeResponse(m_challenge, challenge_response)) { sys_err("Challenge response verification failed for %s", GetHostName()); @@ -550,17 +509,14 @@ bool DESC::HandleKeyResponse(const uint8_t* client_pk, const uint8_t* challenge_ void DESC::SendKeyComplete() { - // Generate session token uint8_t session_token[SecureCipher::SESSION_TOKEN_SIZE]; randombytes_buf(session_token, sizeof(session_token)); m_secureCipher.SetSessionToken(session_token); - // Build and send complete packet TPacketGCKeyComplete packet; packet.header = GC::KEY_COMPLETE; packet.length = sizeof(packet); - // Encrypt the session token if (!m_secureCipher.EncryptToken(session_token, sizeof(session_token), packet.encrypted_token, packet.nonce)) { @@ -571,10 +527,7 @@ void DESC::SendKeyComplete() Packet(&packet, sizeof(packet)); - // Flush before activating encryption ProcessOutput(); - - // Activate encryption m_secureCipher.SetActivated(true); sys_log(0, "[HANDSHAKE] Cipher ACTIVATED for %s (tx_nonce: %llu, rx_nonce: %llu)", @@ -852,8 +805,6 @@ void DESC::ChatPacket(BYTE type, const char * format, ...) Packet(buf.read_peek(), buf.size()); } -// --- Packet sequence tracking --- - void DESC::LogRecvPacket(uint16_t header, uint16_t length) { auto& e = m_aRecentRecvPackets[m_dwRecvPacketSeq % PACKET_LOG_SIZE]; diff --git a/src/game/desc.h b/src/game/desc.h index 3e54ad1..ca7e4c3 100644 --- a/src/game/desc.h +++ b/src/game/desc.h @@ -104,7 +104,6 @@ class DESC DWORD GetClientTime(); - // Secure key exchange (libsodium/XChaCha20-Poly1305) void SendKeyChallenge(); bool HandleKeyResponse(const uint8_t* client_pk, const uint8_t* challenge_response); void SendKeyComplete(); @@ -142,15 +141,9 @@ class DESC bool isChannelStatusRequested() const { return m_bChannelStatusRequested; } void SetChannelStatusRequested(bool bChannelStatusRequested) { m_bChannelStatusRequested = bChannelStatusRequested; } - // Handshake timeout check bool IsExpiredHandshake() const; void SetHandshakeTime(uint32_t handshake_time) { m_handshake_time = handshake_time; } - // Flood protection - bool CheckPacketFlood(); - void SetIPCountTracked(bool b) { m_bIPCountTracked = b; } - bool IsIPCountTracked() const { return m_bIPCountTracked; } - protected: void Initialize(); @@ -215,15 +208,7 @@ class DESC bool m_bDestroyed; bool m_bChannelStatusRequested; - // Handshake timeout protection uint32_t m_handshake_time; - - // Flood protection - int m_iFloodCheckPulse; - uint32_t m_dwFloodPacketCount; - bool m_bIPCountTracked; - - // Secure cipher (libsodium/XChaCha20-Poly1305) SecureCipher m_secureCipher; uint8_t m_challenge[SecureCipher::CHALLENGE_SIZE]; @@ -242,7 +227,6 @@ class DESC void RawPacket(const void * c_pvData, int iSize); void ChatPacket(BYTE type, const char * format, ...); - // --- Packet sequence tracking (debug aid) --- public: struct PacketLogEntry { diff --git a/src/game/desc_manager.cpp b/src/game/desc_manager.cpp index 6a7a728..b4183df 100644 --- a/src/game/desc_manager.cpp +++ b/src/game/desc_manager.cpp @@ -88,27 +88,6 @@ LPDESC DESC_MANAGER::AcceptDesc(LPFDWATCH fdw, socket_t s) strlcpy(host, inet_ntoa(peer.sin_addr), sizeof(host)); - // Global connection limit - extern int g_iFloodMaxGlobalConnections; - if (m_iSocketsConnected >= g_iFloodMaxGlobalConnections) - { - sys_log(0, "FLOOD: rejecting connection from %s (global limit %d/%d reached)", - host, m_iSocketsConnected, g_iFloodMaxGlobalConnections); - socket_close(desc); - return NULL; - } - - // Per-IP connection limit - extern int g_iFloodMaxConnectionsPerIP; - auto itIP = m_map_ipConnCount.find(host); - if (itIP != m_map_ipConnCount.end() && itIP->second >= g_iFloodMaxConnectionsPerIP) - { - sys_log(0, "FLOOD: rejecting connection from %s (%d/%d connections)", - host, itIP->second, g_iFloodMaxConnectionsPerIP); - socket_close(desc); - return NULL; - } - newd = M2_NEW DESC; if (!newd->Setup(fdw, desc, peer, ++m_iHandleCount)) @@ -123,10 +102,6 @@ LPDESC DESC_MANAGER::AcceptDesc(LPFDWATCH fdw, socket_t s) m_set_pkDesc.insert(newd); ++m_iSocketsConnected; - // Track per-IP count - ++m_map_ipConnCount[host]; - newd->SetIPCountTracked(true); - return (newd); } @@ -181,17 +156,6 @@ void DESC_MANAGER::DestroyDesc(LPDESC d, bool bEraseFromSet) else m_set_pkClientDesc.erase((LPCLIENT_DESC) d); - // Decrement per-IP connection count (before Destroy invalidates state) - if (d->IsIPCountTracked()) - { - auto it = m_map_ipConnCount.find(d->GetHostName()); - if (it != m_map_ipConnCount.end()) - { - if (--it->second <= 0) - m_map_ipConnCount.erase(it); - } - } - // Explicit call to the virtual function Destroy() d->Destroy(); @@ -419,7 +383,7 @@ DWORD DESC_MANAGER::CreateLoginKey(LPDESC d) do { - dwKey = randombytes_uniform(INT_MAX) + 1; // CSPRNG: [1, INT_MAX] + dwKey = randombytes_uniform(INT_MAX) + 1; if (m_map_pkLoginKey.find(dwKey) != m_map_pkLoginKey.end()) continue; @@ -445,7 +409,6 @@ void DESC_MANAGER::ProcessExpiredLoginKey() { it2 = it++; - // Clean up orphaned keys (descriptor gone but never expired) if (it2->second->m_dwExpireTime == 0 && it2->second->m_pkDesc == NULL) { M2_DELETE(it2->second); diff --git a/src/game/desc_manager.h b/src/game/desc_manager.h index f70e5f3..10f8ead 100644 --- a/src/game/desc_manager.h +++ b/src/game/desc_manager.h @@ -67,8 +67,6 @@ class DESC_MANAGER : public singleton CLIENT_DESC_SET m_set_pkClientDesc; DESC_SET m_set_pkDesc; - std::unordered_map m_map_ipConnCount; - DESC_HANDLE_MAP m_map_handle; //DESC_ACCOUNTID_MAP m_AccountIDMap; DESC_LOGINNAME_MAP m_map_loginName; diff --git a/src/game/firewall_manager.cpp b/src/game/firewall_manager.cpp deleted file mode 100644 index 65fc291..0000000 --- a/src/game/firewall_manager.cpp +++ /dev/null @@ -1,227 +0,0 @@ -#include "stdafx.h" -#include "config.h" -#include "firewall_manager.h" - -#ifndef OS_WINDOWS -#include -#include -#include -#include -#include -#endif - -extern bool g_bFirewallEnable; -extern int g_iFirewallTcpSynLimit; -extern int g_iFirewallTcpSynBurst; - -FirewallManager::FirewallManager() = default; -FirewallManager::~FirewallManager() = default; - -#ifdef OS_WINDOWS - -// Windows: no-op stubs -bool FirewallManager::Initialize(WORD, WORD) { return false; } -void FirewallManager::Destroy() {} - -#else - -bool FirewallManager::RunCommand(const char* fmt, ...) -{ - char cmd[512]; - va_list args; - va_start(args, fmt); - vsnprintf(cmd, sizeof(cmd), fmt, args); - va_end(args); - - // Temporarily set SIGCHLD to SIG_DFL before calling system(). - // The game server sets SIGCHLD to SIG_IGN (auto-reap children), which - // causes waitpid() inside system() to return -1/ECHILD on FreeBSD - // because the child gets reaped before status can be collected. - struct sigaction saved, dflt; - memset(&dflt, 0, sizeof(dflt)); - dflt.sa_handler = SIG_DFL; - sigemptyset(&dflt.sa_mask); - sigaction(SIGCHLD, &dflt, &saved); - - int status = system(cmd); - - sigaction(SIGCHLD, &saved, NULL); - - if (status == -1) - { - sys_err("FirewallManager: system() failed for: %s", cmd); - return false; - } - - return (WIFEXITED(status) && WEXITSTATUS(status) == 0); -} - -#ifdef OS_FREEBSD - -// --------------------------------------------------------------- -// FreeBSD: ipfw -// Uses deterministic rule numbers based on port to avoid conflicts -// between multiple game processes on the same machine. -// Rule base = 50000 + (gamePort % 1000) * 10 -// --------------------------------------------------------------- - -void FirewallManager::CleanupRules() -{ - if (m_ruleBase == 0) - return; - - for (int i = 0; i < 10; ++i) - RunCommand("/sbin/ipfw -q delete %d 2>/dev/null", m_ruleBase + i); - - m_ruleCount = 0; -} - -bool FirewallManager::Initialize(WORD gamePort, WORD p2pPort) -{ - if (!g_bFirewallEnable) - return false; - - m_ruleBase = 50000 + (gamePort % 1000) * 10; - - // Clean up stale rules from previous crash - CleanupRules(); - - // Test if ipfw is available (use absolute path — popen() may have minimal PATH) - if (!RunCommand("/sbin/ipfw -q list >/dev/null 2>&1")) - { - sys_err("FirewallManager: ipfw not available (module not loaded? try: kldload ipfw)"); - m_ruleBase = 0; - return false; - } - - int r = m_ruleBase; - - // Drop inbound UDP to game and P2P ports - RunCommand("/sbin/ipfw -q add %d deny udp from any to me dst-port %d in", r++, gamePort); - RunCommand("/sbin/ipfw -q add %d deny udp from any to me dst-port %d in", r++, p2pPort); - - // Drop ICMP port-unreachable (type 3) - RunCommand("/sbin/ipfw -q add %d deny icmp from any to me icmptypes 3 in", r++); - - // TCP SYN rate limiting on game port (per-source concurrent connection limit) - RunCommand("/sbin/ipfw -q add %d allow tcp from any to me dst-port %d setup limit src-addr %d", - r++, gamePort, g_iFirewallTcpSynLimit); - RunCommand("/sbin/ipfw -q add %d deny tcp from any to me dst-port %d setup", - r++, gamePort); - - // TCP SYN rate limiting on P2P port - RunCommand("/sbin/ipfw -q add %d allow tcp from any to me dst-port %d setup limit src-addr %d", - r++, p2pPort, g_iFirewallTcpSynLimit); - RunCommand("/sbin/ipfw -q add %d deny tcp from any to me dst-port %d setup", - r++, p2pPort); - - m_ruleCount = r - m_ruleBase; - m_initialized = true; - sys_log(0, "FirewallManager: ipfw rules %d-%d installed (UDP DROP ports %d/%d, TCP SYN limit %d/src)", - m_ruleBase, r - 1, gamePort, p2pPort, g_iFirewallTcpSynLimit); - return true; -} - -#else - -// --------------------------------------------------------------- -// Linux: iptables -// Uses a dedicated chain per process (e.g., M2_GUARD_11011) -// --------------------------------------------------------------- - -void FirewallManager::CleanupRules() -{ - if (m_chainName.empty()) - return; - - // Unhook from INPUT (ignore failure — may not exist) - RunCommand("iptables -D INPUT -j %s 2>/dev/null", m_chainName.c_str()); - - // Flush and delete the chain (ignore failure) - RunCommand("iptables -F %s 2>/dev/null", m_chainName.c_str()); - RunCommand("iptables -X %s 2>/dev/null", m_chainName.c_str()); -} - -bool FirewallManager::Initialize(WORD gamePort, WORD p2pPort) -{ - if (!g_bFirewallEnable) - return false; - - // Chain name includes port to avoid conflicts with multi-channel servers - char buf[64]; - snprintf(buf, sizeof(buf), "M2_GUARD_%d", gamePort); - m_chainName = buf; - - // Always clean up stale rules first (handles crash recovery) - CleanupRules(); - - // Create fresh chain - if (!RunCommand("iptables -N %s", m_chainName.c_str())) - { - sys_err("FirewallManager: failed to create chain %s (not root? iptables not installed?)", m_chainName.c_str()); - m_chainName.clear(); - return false; - } - - // Allow established/related UDP (e.g. DNS replies from outbound queries) - RunCommand("iptables -A %s -p udp -m state --state ESTABLISHED,RELATED -j ACCEPT", - m_chainName.c_str()); - - // DROP all unsolicited inbound UDP - RunCommand("iptables -A %s -p udp -j DROP", m_chainName.c_str()); - - // Rate-limit ICMP to prevent reflection attacks - RunCommand("iptables -A %s -p icmp --icmp-type port-unreachable -j DROP", - m_chainName.c_str()); - RunCommand("iptables -A %s -p icmp -m limit --limit 10/s --limit-burst 20 -j ACCEPT", - m_chainName.c_str()); - RunCommand("iptables -A %s -p icmp -j DROP", m_chainName.c_str()); - - // TCP SYN flood protection on game port - RunCommand("iptables -A %s -p tcp --dport %d --syn -m limit --limit %d/s --limit-burst %d -j ACCEPT", - m_chainName.c_str(), gamePort, g_iFirewallTcpSynLimit, g_iFirewallTcpSynBurst); - RunCommand("iptables -A %s -p tcp --dport %d --syn -j DROP", - m_chainName.c_str(), gamePort); - - // TCP SYN flood protection on P2P port - RunCommand("iptables -A %s -p tcp --dport %d --syn -m limit --limit %d/s --limit-burst %d -j ACCEPT", - m_chainName.c_str(), p2pPort, g_iFirewallTcpSynLimit, g_iFirewallTcpSynBurst); - RunCommand("iptables -A %s -p tcp --dport %d --syn -j DROP", - m_chainName.c_str(), p2pPort); - - // Hook chain into INPUT - if (!RunCommand("iptables -A INPUT -j %s", m_chainName.c_str())) - { - sys_err("FirewallManager: failed to hook chain into INPUT"); - CleanupRules(); - m_chainName.clear(); - return false; - } - - m_initialized = true; - sys_log(0, "FirewallManager: chain %s installed (UDP DROP, TCP SYN limit %d/s burst %d)", - m_chainName.c_str(), g_iFirewallTcpSynLimit, g_iFirewallTcpSynBurst); - return true; -} - -#endif // OS_FREEBSD - -void FirewallManager::Destroy() -{ - if (!m_initialized) - return; - - CleanupRules(); - m_initialized = false; - -#ifdef OS_FREEBSD - sys_log(0, "FirewallManager: ipfw rules %d-%d removed", m_ruleBase, m_ruleBase + m_ruleCount - 1); - m_ruleBase = 0; - m_ruleCount = 0; -#else - sys_log(0, "FirewallManager: chain %s removed", m_chainName.c_str()); - m_chainName.clear(); -#endif -} - -#endif // !OS_WINDOWS diff --git a/src/game/firewall_manager.h b/src/game/firewall_manager.h deleted file mode 100644 index bdd8ff8..0000000 --- a/src/game/firewall_manager.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __INC_FIREWALL_MANAGER_H__ -#define __INC_FIREWALL_MANAGER_H__ - -// Kernel-level firewall management. -// Linux: iptables chains. FreeBSD: ipfw rules. -// Installs DROP rules for unsolicited UDP and rate-limits TCP SYN floods. -// Windows: no-op stubs. - -class FirewallManager : public singleton -{ -public: - FirewallManager(); - ~FirewallManager(); - - // Install firewall rules — call after config_init() - bool Initialize(WORD gamePort, WORD p2pPort); - - // Remove firewall rules — call during shutdown - void Destroy(); - -private: -#ifndef OS_WINDOWS - bool RunCommand(const char* fmt, ...); - void CleanupRules(); -#endif - - std::string m_chainName; // Linux: iptables chain name - int m_ruleBase = 0; // FreeBSD: ipfw rule number base - int m_ruleCount = 0; // FreeBSD: number of rules installed - bool m_initialized = false; -}; - -#endif diff --git a/src/game/input.cpp b/src/game/input.cpp index 9463649..c2ee70f 100644 --- a/src/game/input.cpp +++ b/src/game/input.cpp @@ -131,12 +131,6 @@ bool CInputProcessor::Process(LPDESC lpDesc, const void * c_pvOrig, int iBytes, if (wHeader) { - if (lpDesc->CheckPacketFlood()) - { - lpDesc->SetPhase(PHASE_CLOSE); - return true; - } - m_pPacketInfo->Start(); int iExtraPacketSize = Analyze(lpDesc, wHeader, c_pData); diff --git a/src/game/input.h b/src/game/input.h index d09e71b..ad9eec4 100644 --- a/src/game/input.h +++ b/src/game/input.h @@ -128,7 +128,6 @@ class CInputMain : public CInputProcessor protected: int Analyze(LPDESC d, uint16_t wHeader, const char * c_pData) override; - // Handler dispatch using MainHandler = int (CInputMain::*)(LPDESC, const char*); struct HandlerEntry { MainHandler handler; @@ -137,14 +136,12 @@ class CInputMain : public CInputProcessor std::unordered_map m_handlers; virtual void RegisterHandlers(); - // Template adapters for common handler patterns (defined in input_main.cpp) template int SimpleHandler(LPDESC d, const char* p); template int SimpleHandlerV(LPDESC d, const char* p); - // Custom adapters for non-standard handler signatures int HandlePong(LPDESC d, const char* p); int HandleChat(LPDESC d, const char* p); int HandleWhisper(LPDESC d, const char* p); @@ -262,19 +259,14 @@ protected: void RegisterHandlers(); LPDESC FindByHandle() const; - // Template: void handler(const char*) — data-only template int DataHandler(LPDESC, const char* p) { (this->*fn)(p); return 0; } - // Template: void handler(LPDESC, const char*) — desc from FindByHandle template int DescHandler(LPDESC, const char* p) { (this->*fn)(FindByHandle(), p); return 0; } - // Template: void handler(T*) — cast c_pData to typed pointer template int TypedHandler(LPDESC, const char* p) { (this->*fn)((T*)p); return 0; } - - // Custom adapters for special signatures int HandleLoginSuccess(LPDESC, const char*); int HandleLoginNotExist(LPDESC, const char*); int HandleLoginWrongPasswd(LPDESC, const char*); diff --git a/src/game/input_main.cpp b/src/game/input_main.cpp index ea84b73..a9fe56d 100644 --- a/src/game/input_main.cpp +++ b/src/game/input_main.cpp @@ -1729,7 +1729,6 @@ void CInputMain::Attack(LPCHARACTER ch, const uint16_t header, const char* data) if (NULL == ch) return; - // Updated for new packet format: [header:2][length:2][bType:1] struct type_identifier { uint16_t header; @@ -2673,7 +2672,7 @@ int CInputMain::Guild(LPCHARACTER ch, const char * data, size_t uiBytes) } // --------------------------------------------------------------------------- -// Guild sub-handlers — extracted from Guild() switch cases +// Guild sub-handlers // --------------------------------------------------------------------------- int CInputMain::GuildSub_DepositMoney(LPCHARACTER ch, const char* data, size_t uiBytes) @@ -3214,7 +3213,7 @@ CInputMain::CInputMain() RegisterHandlers(); } -// Custom adapter methods — bridge varied handler signatures to unified MainHandler +// Custom adapter methods int CInputMain::HandlePong(LPDESC d, const char*) { @@ -3391,7 +3390,7 @@ void CInputMain::RegisterHandlers() reg(CG::CLIENT_VERSION, &CInputMain::HandleClientVersion); reg(CG::DRAGON_SOUL_REFINE,&CInputMain::HandleDragonSoulRefine); - // Simple void(LPCHARACTER, const char*) — via template adapter + // SimpleHandler(LPCHARACTER, const char*) reg(CG::CHARACTER_POSITION,&CInputMain::SimpleHandler<&CInputMain::Position>); reg(CG::ITEM_USE, &CInputMain::SimpleHandler<&CInputMain::ItemUse>, true); reg(CG::ITEM_DROP, &CInputMain::SimpleHandler<&CInputMain::ItemDrop>, true); @@ -3421,7 +3420,7 @@ void CInputMain::RegisterHandlers() reg(CG::HACK, &CInputMain::SimpleHandler<&CInputMain::Hack>); reg(CG::REFINE, &CInputMain::SimpleHandler<&CInputMain::Refine>); - // void(LPCHARACTER, const void*) — via template adapter + // SimpleHandlerV(LPCHARACTER, const void*) reg(CG::SCRIPT_ANSWER, &CInputMain::SimpleHandlerV<&CInputMain::ScriptAnswer>); reg(CG::SCRIPT_BUTTON, &CInputMain::SimpleHandlerV<&CInputMain::ScriptButton>); reg(CG::SCRIPT_SELECT_ITEM, &CInputMain::SimpleHandlerV<&CInputMain::ScriptSelectItem>); @@ -3429,8 +3428,6 @@ void CInputMain::RegisterHandlers() reg(CG::QUEST_CONFIRM, &CInputMain::SimpleHandlerV<&CInputMain::QuestConfirm>); } -// --------------------------------------------------------------------------- -// Table-driven Analyze — replaces switch statement // --------------------------------------------------------------------------- int CInputMain::Analyze(LPDESC d, uint16_t wHeader, const char * c_pData) @@ -3458,7 +3455,7 @@ int CInputMain::Analyze(LPDESC d, uint16_t wHeader, const char * c_pData) } // --------------------------------------------------------------------------- -// CInputDead — only allows PONG, CHAT, WHISPER, HACK +// CInputDead // --------------------------------------------------------------------------- CInputDead::CInputDead() diff --git a/src/game/main.cpp b/src/game/main.cpp index edc25de..bcedeab 100644 --- a/src/game/main.cpp +++ b/src/game/main.cpp @@ -54,7 +54,6 @@ #include "DragonLair.h" #include "skill_power.h" #include "DragonSoul.h" -#include "firewall_manager.h" // #ifndef OS_WINDOWS // #include @@ -89,11 +88,6 @@ BYTE g_bLogLevel = 0; socket_t tcp_socket = 0; socket_t p2p_socket = 0; -// UDP sink sockets — bound but never read, prevents kernel ICMP port-unreachable generation -// during UDP floods (kernel silently drops once the tiny receive buffer fills) -static socket_t udp_sink_game = INVALID_SOCKET; -static socket_t udp_sink_p2p = INVALID_SOCKET; - LPFDWATCH main_fdw = NULL; int io_loop(LPFDWATCH fdw); @@ -347,7 +341,6 @@ int main(int argc, char **argv) CThreeWayWar threeway_war; CDragonLairManager dl_manager; DSManager dsManager; - FirewallManager firewall_manager; if (!start(argc, argv)) { CleanUpForEarlyExit(); @@ -421,8 +414,6 @@ int main(int argc, char **argv) char_manager.Destroy(); sys_log(0, " Destroying ITEM_MANAGER..."); item_manager.Destroy(); - sys_log(0, " Destroying FirewallManager..."); - firewall_manager.Destroy(); sys_log(0, " Destroying DESC_MANAGER..."); desc_manager.Destroy(); sys_log(0, " Destroying quest::CQuestManager..."); @@ -440,49 +431,6 @@ int main(int argc, char **argv) return 1; } -// Create a UDP sink socket: bind to ip:port with minimal receive buffer, never read. -// Prevents ICMP port-unreachable replies during UDP floods — the kernel silently drops -// packets once the tiny buffer fills. Returns INVALID_SOCKET on failure (non-fatal). -static socket_t create_udp_sink(const char* ip, WORD port) -{ -#ifdef OS_WINDOWS - (void)ip; (void)port; - return INVALID_SOCKET; -#else - socket_t s = socket(AF_INET, SOCK_DGRAM, 0); - if (s < 0) - { - sys_err("create_udp_sink: socket() failed for port %d: %s", port, strerror(errno)); - return INVALID_SOCKET; - } - - // Allow rebind if previous instance didn't clean up - int reuse = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); - - // Minimal receive buffer — kernel rounds up to its minimum (typically 256 bytes on Linux). - // Once full, incoming UDP is silently dropped with zero CPU overhead. - int rcvbuf = 1; - setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(ip); - - if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) - { - sys_err("create_udp_sink: bind() failed for port %d: %s", port, strerror(errno)); - close(s); - return INVALID_SOCKET; - } - - sys_log(0, "UDP sink bound on %s:%d (fd %d) — ICMP suppression active", ip, port, s); - return s; -#endif -} - void usage() { printf("Option list\n" @@ -613,13 +561,6 @@ int start(int argc, char **argv) fdwatch_add_fd(main_fdw, tcp_socket, NULL, FDW_READ, false); fdwatch_add_fd(main_fdw, p2p_socket, NULL, FDW_READ, false); - // UDP sink sockets — suppress ICMP port-unreachable during UDP floods - udp_sink_game = create_udp_sink(g_szPublicIP, mother_port); - udp_sink_p2p = create_udp_sink(g_szPublicIP, p2p_port); - - // Kernel-level firewall — DROP unsolicited UDP + rate-limit TCP SYN at netfilter layer - FirewallManager::instance().Initialize(mother_port, p2p_port); - db_clientdesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, db_addr, db_port, PHASE_DBCLIENT, true); if (!g_bAuthServer) { db_clientdesc->UpdateChannelStatus(0, true); @@ -669,9 +610,6 @@ void destroy() socket_close(tcp_socket); socket_close(p2p_socket); - if (udp_sink_game != INVALID_SOCKET) { socket_close(udp_sink_game); udp_sink_game = INVALID_SOCKET; } - if (udp_sink_p2p != INVALID_SOCKET) { socket_close(udp_sink_p2p); udp_sink_p2p = INVALID_SOCKET; } - sys_log(0, " fdwatch_delete()..."); fdwatch_delete(main_fdw); diff --git a/src/game/packet_reader.h b/src/game/packet_reader.h index 7d46379..fdbf8e8 100644 --- a/src/game/packet_reader.h +++ b/src/game/packet_reader.h @@ -128,8 +128,6 @@ public: return v; } - // --- Read struct (for backward compatibility during migration) --- - // Reads a struct directly via memcpy. Use sparingly — prefer typed reads. template bool ReadStruct(T& out) {