From e53abb198965f91a5fe9ed9518efee7355654046 Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Sat, 13 Apr 2024 15:06:58 +0100 Subject: [PATCH] DEV9: Add DHCP logger Enabled by setting `EthLogDHCP = true` in PCSX2.ini --- pcsx2/CMakeLists.txt | 2 + pcsx2/Config.h | 1 + pcsx2/DEV9/InternalServers/DHCP_Logger.cpp | 338 +++++++++++++++++++++ pcsx2/DEV9/InternalServers/DHCP_Logger.h | 46 +++ pcsx2/DEV9/net.cpp | 25 +- pcsx2/DEV9/net.h | 2 + pcsx2/Pcsx2Config.cpp | 2 + pcsx2/pcsx2.vcxproj | 2 + pcsx2/pcsx2.vcxproj.filters | 6 + 9 files changed, 420 insertions(+), 4 deletions(-) create mode 100644 pcsx2/DEV9/InternalServers/DHCP_Logger.cpp create mode 100644 pcsx2/DEV9/InternalServers/DHCP_Logger.h diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index e88eab4d68636..572b94ab442c6 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -287,6 +287,7 @@ set(pcsx2DEV9Sources DEV9/ATA/ATA_State.cpp DEV9/ATA/ATA_Transfer.cpp DEV9/ATA/HddCreate.cpp + DEV9/InternalServers/DHCP_Logger.cpp DEV9/InternalServers/DHCP_Server.cpp DEV9/InternalServers/DNS_Logger.cpp DEV9/InternalServers/DNS_Server.cpp @@ -325,6 +326,7 @@ set(pcsx2DEV9Headers DEV9/ATA/ATA.h DEV9/ATA/HddCreate.h DEV9/DEV9.h + DEV9/InternalServers/DHCP_Logger.h DEV9/InternalServers/DHCP_Server.h DEV9/InternalServers/DNS_Logger.h DEV9/InternalServers/DNS_Server.h diff --git a/pcsx2/Config.h b/pcsx2/Config.h index e4ab52b9a4afb..c8e1a4a33346a 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -861,6 +861,7 @@ struct Pcsx2Config bool EthEnable{false}; NetApi EthApi{NetApi::Unset}; std::string EthDevice; + bool EthLogDHCP{false}; bool EthLogDNS{false}; bool InterceptDHCP{false}; diff --git a/pcsx2/DEV9/InternalServers/DHCP_Logger.cpp b/pcsx2/DEV9/InternalServers/DHCP_Logger.cpp new file mode 100644 index 0000000000000..f0ebd81bc75c2 --- /dev/null +++ b/pcsx2/DEV9/InternalServers/DHCP_Logger.cpp @@ -0,0 +1,338 @@ +// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team +// SPDX-License-Identifier: LGPL-3.0+ + +#include "DHCP_Logger.h" +#include "DEV9/PacketReader/IP/UDP/UDP_Packet.h" +#include "DEV9/PacketReader/IP/UDP/DHCP/DHCP_Packet.h" + +#include + +#include "common/Console.h" +#include "common/StringUtil.h" + +#include "DEV9/AdapterUtils.h" + +using PacketReader::PayloadPtr; +using namespace PacketReader::IP; +using namespace PacketReader::IP::UDP; +using namespace PacketReader::IP::UDP::DHCP; + +namespace InternalServers +{ +#ifdef _WIN32 + void DHCP_Logger::Init(PIP_ADAPTER_ADDRESSES adapter) +#elif defined(__POSIX__) + void DHCP_Logger::Init(ifaddrs* adapter) +#endif + { + std::optional adIP = AdapterUtils::GetAdapterIP(adapter); + if (adIP.has_value()) + pcIP = adIP.value(); + else + pcIP = {}; + } + + void DHCP_Logger::InspectRecv(IP_Payload* payload) + { + UDP_Packet* udpPacket = static_cast(payload); + PayloadPtr* udpPayload = static_cast(udpPacket->GetPayload()); + DHCP_Packet dhcp(udpPayload->data, udpPayload->GetLength()); + Console.WriteLn("DEV9: DHCP: Host PC IP is %s", IpToString(pcIP).c_str()); + LogPacket(&dhcp); + } + + void DHCP_Logger::InspectSend(IP_Payload* payload) + { + UDP_Packet* udpPacket = static_cast(payload); + PayloadPtr* udpPayload = static_cast(udpPacket->GetPayload()); + DHCP_Packet dhcp(udpPayload->data, udpPayload->GetLength()); + Console.WriteLn("DEV9: DHCP: Host PC IP is %s", IpToString(pcIP).c_str()); + LogPacket(&dhcp); + } + + std::string DHCP_Logger::IpToString(IP_Address ip) + { + return StringUtil::StdStringFromFormat("%u.%u.%u.%u", ip.bytes[0], ip.bytes[1], ip.bytes[2], ip.bytes[3]); + } + + std::string DHCP_Logger::HardwareAddressToString(u8* data, size_t len) + { + std::string str; + if (len != 0) + { + str.reserve(len * 4); + for (size_t i = 0; i < len; i++) + str += StringUtil::StdStringFromFormat("%.2X:", data[i]); + + str.pop_back(); + } // else leave string empty + return str; + } + + std::string DHCP_Logger::ClientIdToString(const std::vector& data) + { + std::string str; + if (data.size() != 0) + { + str.reserve(data.size() * 4); + for (size_t i = 0; i < data.size(); i++) + str += StringUtil::StdStringFromFormat("%.2X:", data[i]); + + str.pop_back(); + } // else leave string empty + return str; + } + + const char* DHCP_Logger::OpToString(u8 op) + { + switch (op) + { + case 1: + return "Request"; + case 2: + return "Reply"; + default: + return "Unknown"; + } + } + + const char* DHCP_Logger::HardwareTypeToString(u8 op) + { + switch (op) + { + case 1: + return "Ethernet"; + case 6: + return "IEEE 802"; + default: + return "Unknown"; + } + } + + const char* DHCP_Logger::OptionToString(u8 option) + { + switch (option) + { + case 0: + return "Nop"; + case 1: + return "Subnet"; + case 3: + return "Routers"; + case 6: + return "DNS"; + case 12: + return "Host Name"; + case 15: + return "DNS Name"; + case 28: + return "Broadcast IP"; + case 46: + return "NetBIOS Type"; + case 50: + return "Requested IP"; + case 51: + return "IP Lease Time"; + case 53: + return "Message Type"; + case 54: + return "Server IP"; + case 55: + return "Request List"; + case 56: + return "Message String"; + case 57: + return "Max Message Size"; + case 58: + return "Renewal Time T1"; + case 59: + return "Rebinding Time T2"; + case 60: + return "Class ID"; + case 61: + return "Client ID"; + case 255: + return "End"; + default: + return "Unknown"; + } + } + + const char* DHCP_Logger::MessageCodeToString(u8 op) + { + switch (op) + { + case 1: + return "DHCP Discover"; + case 2: + return "DHCP Offer"; + case 3: + return "DHCP Request"; + case 4: + return "DHCP Decline"; + case 5: + return "DHCP ACK"; + case 6: + return "DHCP NACK"; + case 7: + return "DHCP Release"; + case 8: + return "DHCP Inform"; + default: + return "Unknown"; + } + } + + void DHCP_Logger::LogPacket(DHCP_Packet* dhcp) + { + Console.WriteLn("DEV9: DHCP: Op %s (%i)", OpToString(dhcp->op), dhcp->op); + Console.WriteLn("DEV9: DHCP: Hardware Type %s (%i)", HardwareTypeToString(dhcp->hardwareType), dhcp->hardwareType); + Console.WriteLn("DEV9: DHCP: Hardware Address Length %i", dhcp->hardwareAddressLength); + Console.WriteLn("DEV9: DHCP: Hops %i", dhcp->hops); + Console.WriteLn("DEV9: DHCP: Transaction ID %i", dhcp->transactionID); + Console.WriteLn("DEV9: DHCP: Seconds %i", dhcp->seconds); + Console.WriteLn("DEV9: DHCP: Flags 0x%.4X", dhcp->flags); + Console.WriteLn("DEV9: DHCP: Client IP %s", IpToString(dhcp->clientIP).c_str()); + Console.WriteLn("DEV9: DHCP: Your IP %s", IpToString(dhcp->yourIP).c_str()); + Console.WriteLn("DEV9: DHCP: Server IP %s", IpToString(dhcp->serverIP).c_str()); + Console.WriteLn("DEV9: DHCP: Gateway IP %s", IpToString(dhcp->gatewayIP).c_str()); + Console.WriteLn("DEV9: DHCP: Gateway IP %s", IpToString(dhcp->gatewayIP).c_str()); + Console.WriteLn("DEV9: DHCP: Client Hardware Address %s", HardwareAddressToString(dhcp->clientHardwareAddress, std::min(dhcp->hardwareAddressLength, 16)).c_str()); + Console.WriteLn("DEV9: DHCP: Magic Cookie 0x%.8X", dhcp->magicCookie); + + Console.WriteLn("DEV9: DHCP: Options Count %i", dhcp->options.size()); + + for (size_t i = 0; i < dhcp->options.size(); i++) + { + BaseOption* entry = dhcp->options[i]; + Console.WriteLn("DEV9: DHCP: Option %s (%i)", OptionToString(entry->GetCode()), entry->GetCode()); + Console.WriteLn("DEV9: DHCP: Option Size %i", entry->GetLength()); + switch (entry->GetCode()) + { + case 0: + break; + case 1: + { + const DHCPopSubnet* subnet = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Subnet %s", IpToString(subnet->subnetMask).c_str()); + break; + } + case 3: + { + const DHCPopRouter* routers = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Routers Count %i", routers->routers.size()); + for (size_t j = 0; j < routers->routers.size(); j++) + Console.WriteLn("DEV9: DHCP: Router %s", IpToString(routers->routers[j]).c_str()); + break; + } + case 6: + { + const DHCPopDNS* dns = static_cast(entry); + Console.WriteLn("DEV9: DHCP: DNS Count %i", dns->dnsServers.size()); + for (size_t j = 0; j < dns->dnsServers.size(); j++) + Console.WriteLn("DEV9: DHCP: DNS %s", IpToString(dns->dnsServers[j]).c_str()); + break; + } + case 12: + { + const DHCPopHostName* name = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Host Name %s", name->hostName.c_str()); + break; + } + case 15: + { + const DHCPopDnsName* name = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Domain Name %s", name->domainName.c_str()); + break; + } + case 28: + { + const DHCPopBCIP* broadcast = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Broadcast IP %s", IpToString(broadcast->broadcastIP).c_str()); + break; + } + case 46: + { + DHCPopNBIOSType* biosType = static_cast(entry); + Console.WriteLn("DEV9: DHCP: NetBIOS B-Node %s", biosType->GetBNode() ? "True" : "False"); + Console.WriteLn("DEV9: DHCP: NetBIOS P-Node %s", biosType->GetPNode() ? "True" : "False"); + Console.WriteLn("DEV9: DHCP: NetBIOS M-Node %s", biosType->GetMNode() ? "True" : "False"); + Console.WriteLn("DEV9: DHCP: NetBIOS H-Node %s", biosType->GetHNode() ? "True" : "False"); + break; + } + case 50: + { + const DHCPopREQIP* req = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Requested IP %s", IpToString(req->requestedIP).c_str()); + break; + } + case 51: + { + const DHCPopIPLT* iplt = static_cast(entry); + Console.WriteLn("DEV9: DHCP: IP Least Time %i", iplt->ipLeaseTime); + break; + } + case 53: + { + const DHCPopMSG* msg = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Message %s (%i)", MessageCodeToString(msg->message), msg->message); + break; + } + case 54: + { + const DHCPopSERVIP* req = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Server IP %s", IpToString(req->serverIP).c_str()); + break; + } + case 55: + { + const DHCPopREQLIST* reqList = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Request Count %i", reqList->requests.size()); + for (size_t j = 0; j < reqList->requests.size(); j++) + Console.WriteLn("DEV9: DHCP: Requested %s (%i)", OptionToString(reqList->requests[j]), reqList->requests[j]); + break; + } + case 56: + { + const DHCPopMSGStr* msg = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Message %s", msg->message.c_str()); + break; + } + case 57: + { + const DHCPopMMSGS* maxMs = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Max Message Size %i", maxMs->maxMessageSize); + break; + } + case 58: + { + const DHCPopT1* t1 = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Renewal Time (T1) %i", t1->ipRenewalTimeT1); + break; + } + case 59: + { + const DHCPopT2* t2 = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Rebinding Time (T2) %i", t2->ipRebindingTimeT2); + break; + } + case 60: + { + const DHCPopClassID* id = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Class ID %s", id->classID.c_str()); + break; + } + case 61: + { + const DHCPopClientID* id = static_cast(entry); + Console.WriteLn("DEV9: DHCP: Client ID %s", ClientIdToString(id->clientID).c_str()); + break; + } + case 255: + break; + default: + break; + } + } + } +} // namespace InternalServers diff --git a/pcsx2/DEV9/InternalServers/DHCP_Logger.h b/pcsx2/DEV9/InternalServers/DHCP_Logger.h new file mode 100644 index 0000000000000..5f796d5895434 --- /dev/null +++ b/pcsx2/DEV9/InternalServers/DHCP_Logger.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team +// SPDX-License-Identifier: LGPL-3.0+ + +#pragma once +#include "DEV9/PacketReader/IP/IP_Packet.h" +#include "DEV9/PacketReader/IP/UDP/DHCP/DHCP_Packet.h" + +#ifdef _WIN32 +#include +#include +#elif defined(__POSIX__) +#include +#include +#endif + +namespace InternalServers +{ + class DHCP_Logger + { + public: + DHCP_Logger(){}; + +#ifdef _WIN32 + void Init(PIP_ADAPTER_ADDRESSES adapter); +#elif defined(__POSIX__) + void Init(ifaddrs* adapter); +#endif + + // Expects a UDP_payload + void InspectRecv(PacketReader::IP::IP_Payload* payload); + // Expects a UDP_payload + void InspectSend(PacketReader::IP::IP_Payload* payload); + + private: + PacketReader::IP::IP_Address pcIP{}; + + std::string IpToString(PacketReader::IP::IP_Address ip); + std::string HardwareAddressToString(u8* data, size_t len); + std::string ClientIdToString(const std::vector& data); + const char* OpToString(u8 op); + const char* HardwareTypeToString(u8 op); + const char* OptionToString(u8 option); + const char* MessageCodeToString(u8 msg); + void LogPacket(PacketReader::IP::UDP::DHCP::DHCP_Packet* payload); + }; +} // namespace InternalServers diff --git a/pcsx2/DEV9/net.cpp b/pcsx2/DEV9/net.cpp index ffcd741a4703f..5c10891a07d4e 100644 --- a/pcsx2/DEV9/net.cpp +++ b/pcsx2/DEV9/net.cpp @@ -205,7 +205,7 @@ NetAdapter::~NetAdapter() void NetAdapter::InspectSend(NetPacket* pkt) { - if (EmuConfig.DEV9.EthLogDNS) + if (EmuConfig.DEV9.EthLogDNS || EmuConfig.DEV9.EthLogDHCP) { EthernetFrame frame(pkt); if (frame.protocol == (u16)EtherType::IPv4) @@ -218,19 +218,26 @@ void NetAdapter::InspectSend(NetPacket* pkt) IP_PayloadPtr* ipPayload = static_cast(ippkt.GetPayload()); UDP_Packet udppkt(ipPayload->data, ipPayload->GetLength()); - if (udppkt.destinationPort == 53) + if (EmuConfig.DEV9.EthLogDNS && udppkt.destinationPort == 53) { Console.WriteLn("DEV9: DNS: Packet Sent To %i.%i.%i.%i", ippkt.destinationIP.bytes[0], ippkt.destinationIP.bytes[1], ippkt.destinationIP.bytes[2], ippkt.destinationIP.bytes[3]); dnsLogger.InspectSend(&udppkt); } + + if (EmuConfig.DEV9.EthLogDHCP && udppkt.destinationPort == 67) + { + Console.WriteLn("DEV9: DHCP: Packet Sent To %i.%i.%i.%i", + ippkt.destinationIP.bytes[0], ippkt.destinationIP.bytes[1], ippkt.destinationIP.bytes[2], ippkt.destinationIP.bytes[3]); + dhcpLogger.InspectSend(&udppkt); + } } } } } void NetAdapter::InspectRecv(NetPacket* pkt) { - if (EmuConfig.DEV9.EthLogDNS) + if (EmuConfig.DEV9.EthLogDNS || EmuConfig.DEV9.EthLogDHCP) { EthernetFrame frame(pkt); if (frame.protocol == (u16)EtherType::IPv4) @@ -243,12 +250,19 @@ void NetAdapter::InspectRecv(NetPacket* pkt) IP_PayloadPtr* ipPayload = static_cast(ippkt.GetPayload()); UDP_Packet udppkt(ipPayload->data, ipPayload->GetLength()); - if (udppkt.sourcePort == 53) + if (EmuConfig.DEV9.EthLogDNS && udppkt.sourcePort == 53) { Console.WriteLn("DEV9: DNS: Packet Sent From %i.%i.%i.%i", ippkt.sourceIP.bytes[0], ippkt.sourceIP.bytes[1], ippkt.sourceIP.bytes[2], ippkt.sourceIP.bytes[3]); dnsLogger.InspectRecv(&udppkt); } + + if (EmuConfig.DEV9.EthLogDHCP && udppkt.sourcePort == 67) + { + Console.WriteLn("DEV9: DHCP: Packet Sent From %i.%i.%i.%i", + ippkt.sourceIP.bytes[0], ippkt.sourceIP.bytes[1], ippkt.sourceIP.bytes[2], ippkt.sourceIP.bytes[3]); + dhcpLogger.InspectRecv(&udppkt); + } } } } @@ -293,6 +307,8 @@ void NetAdapter::InitInternalServer(ifaddrs* adapter, bool dhcpForceEnable, IP_A if (adapter == nullptr) Console.Error("DEV9: InitInternalServer() got nullptr for adapter"); + dhcpLogger.Init(adapter); + dhcpOn = EmuConfig.DEV9.InterceptDHCP || dhcpForceEnable; if (dhcpOn) dhcpServer.Init(adapter, ipOverride, subnetOverride, gatewayOvveride); @@ -336,6 +352,7 @@ bool NetAdapter::InternalServerRecv(NetPacket* pkt) frame.destinationMAC = ps2MAC; frame.protocol = (u16)EtherType::IPv4; frame.WritePacket(pkt); + InspectRecv(pkt); return true; } diff --git a/pcsx2/DEV9/net.h b/pcsx2/DEV9/net.h index 6c0dc9e0b407a..e78bc367e3fce 100644 --- a/pcsx2/DEV9/net.h +++ b/pcsx2/DEV9/net.h @@ -24,6 +24,7 @@ #include "PacketReader/MAC_Address.h" #include "PacketReader/IP/IP_Address.h" +#include "InternalServers/DHCP_Logger.h" #include "InternalServers/DHCP_Server.h" #include "InternalServers/DNS_Logger.h" #include "InternalServers/DNS_Server.h" @@ -99,6 +100,7 @@ class NetAdapter bool dhcpOn = false; protected: + InternalServers::DHCP_Logger dhcpLogger; InternalServers::DHCP_Server dhcpServer = InternalServers::DHCP_Server([&] { InternalSignalReceived(); }); InternalServers::DNS_Logger dnsLogger; InternalServers::DNS_Server dnsServer = InternalServers::DNS_Server([&] { InternalSignalReceived(); }); diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index c308903a6a936..228f7ae9a032c 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -1161,6 +1161,7 @@ void Pcsx2Config::DEV9Options::LoadSave(SettingsWrapper& wrap) SettingsWrapEntry(EthEnable); SettingsWrapEnumEx(EthApi, "EthApi", NetApiNames); SettingsWrapEntry(EthDevice); + SettingsWrapEntry(EthLogDHCP); SettingsWrapEntry(EthLogDNS); SettingsWrapEntry(InterceptDHCP); @@ -1254,6 +1255,7 @@ bool Pcsx2Config::DEV9Options::operator==(const DEV9Options& right) const return OpEqu(EthEnable) && OpEqu(EthApi) && OpEqu(EthDevice) && + OpEqu(EthLogDHCP) && OpEqu(EthLogDNS) && OpEqu(InterceptDHCP) && diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj index 584fb19b6578e..7661da8d4146a 100644 --- a/pcsx2/pcsx2.vcxproj +++ b/pcsx2/pcsx2.vcxproj @@ -152,6 +152,7 @@ + @@ -490,6 +491,7 @@ + diff --git a/pcsx2/pcsx2.vcxproj.filters b/pcsx2/pcsx2.vcxproj.filters index a380ff0dfdbb0..deec19ba763f9 100644 --- a/pcsx2/pcsx2.vcxproj.filters +++ b/pcsx2/pcsx2.vcxproj.filters @@ -884,6 +884,9 @@ System\Ps2\DEV9 + + System\Ps2\DEV9\InternalServers + System\Ps2\DEV9\InternalServers @@ -1736,6 +1739,9 @@ System\Ps2\DEV9 + + System\Ps2\DEV9\InternalServers + System\Ps2\DEV9\InternalServers