DEV9: Add DHCP logger

Enabled by setting `EthLogDHCP = true` in PCSX2.ini
This commit is contained in:
TheLastRar 2024-04-13 15:06:58 +01:00 committed by Connor McLaughlin
parent dc20521b01
commit e53abb1989
9 changed files with 420 additions and 4 deletions

View File

@ -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

View File

@ -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};

View File

@ -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 <algorithm>
#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<IP_Address> 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<UDP_Packet*>(payload);
PayloadPtr* udpPayload = static_cast<PayloadPtr*>(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<UDP_Packet*>(payload);
PayloadPtr* udpPayload = static_cast<PayloadPtr*>(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<u8>& 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<u8>(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<DHCPopSubnet*>(entry);
Console.WriteLn("DEV9: DHCP: Subnet %s", IpToString(subnet->subnetMask).c_str());
break;
}
case 3:
{
const DHCPopRouter* routers = static_cast<DHCPopRouter*>(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<DHCPopDNS*>(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<DHCPopHostName*>(entry);
Console.WriteLn("DEV9: DHCP: Host Name %s", name->hostName.c_str());
break;
}
case 15:
{
const DHCPopDnsName* name = static_cast<DHCPopDnsName*>(entry);
Console.WriteLn("DEV9: DHCP: Domain Name %s", name->domainName.c_str());
break;
}
case 28:
{
const DHCPopBCIP* broadcast = static_cast<DHCPopBCIP*>(entry);
Console.WriteLn("DEV9: DHCP: Broadcast IP %s", IpToString(broadcast->broadcastIP).c_str());
break;
}
case 46:
{
DHCPopNBIOSType* biosType = static_cast<DHCPopNBIOSType*>(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<DHCPopREQIP*>(entry);
Console.WriteLn("DEV9: DHCP: Requested IP %s", IpToString(req->requestedIP).c_str());
break;
}
case 51:
{
const DHCPopIPLT* iplt = static_cast<DHCPopIPLT*>(entry);
Console.WriteLn("DEV9: DHCP: IP Least Time %i", iplt->ipLeaseTime);
break;
}
case 53:
{
const DHCPopMSG* msg = static_cast<DHCPopMSG*>(entry);
Console.WriteLn("DEV9: DHCP: Message %s (%i)", MessageCodeToString(msg->message), msg->message);
break;
}
case 54:
{
const DHCPopSERVIP* req = static_cast<DHCPopSERVIP*>(entry);
Console.WriteLn("DEV9: DHCP: Server IP %s", IpToString(req->serverIP).c_str());
break;
}
case 55:
{
const DHCPopREQLIST* reqList = static_cast<DHCPopREQLIST*>(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<DHCPopMSGStr*>(entry);
Console.WriteLn("DEV9: DHCP: Message %s", msg->message.c_str());
break;
}
case 57:
{
const DHCPopMMSGS* maxMs = static_cast<DHCPopMMSGS*>(entry);
Console.WriteLn("DEV9: DHCP: Max Message Size %i", maxMs->maxMessageSize);
break;
}
case 58:
{
const DHCPopT1* t1 = static_cast<DHCPopT1*>(entry);
Console.WriteLn("DEV9: DHCP: Renewal Time (T1) %i", t1->ipRenewalTimeT1);
break;
}
case 59:
{
const DHCPopT2* t2 = static_cast<DHCPopT2*>(entry);
Console.WriteLn("DEV9: DHCP: Rebinding Time (T2) %i", t2->ipRebindingTimeT2);
break;
}
case 60:
{
const DHCPopClassID* id = static_cast<DHCPopClassID*>(entry);
Console.WriteLn("DEV9: DHCP: Class ID %s", id->classID.c_str());
break;
}
case 61:
{
const DHCPopClientID* id = static_cast<DHCPopClientID*>(entry);
Console.WriteLn("DEV9: DHCP: Client ID %s", ClientIdToString(id->clientID).c_str());
break;
}
case 255:
break;
default:
break;
}
}
}
} // namespace InternalServers

View File

@ -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 <winsock2.h>
#include <iphlpapi.h>
#elif defined(__POSIX__)
#include <sys/types.h>
#include <ifaddrs.h>
#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<u8>& 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

View File

@ -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<IP_PayloadPtr*>(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<IP_PayloadPtr*>(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;
}

View File

@ -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 @@ private:
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(); });

View File

@ -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) &&

View File

@ -152,6 +152,7 @@
<ClCompile Include="DEV9\ATA\HddCreate.cpp" />
<ClCompile Include="DEV9\DEV9.cpp" />
<ClCompile Include="DEV9\flash.cpp" />
<ClCompile Include="DEV9\InternalServers\DHCP_Logger.cpp" />
<ClCompile Include="DEV9\InternalServers\DHCP_Server.cpp" />
<ClCompile Include="DEV9\InternalServers\DNS_Logger.cpp" />
<ClCompile Include="DEV9\InternalServers\DNS_Server.cpp" />
@ -490,6 +491,7 @@
<ClInclude Include="DEV9\ATA\ATA.h" />
<ClInclude Include="DEV9\ATA\HddCreate.h" />
<ClInclude Include="DEV9\DEV9.h" />
<ClInclude Include="DEV9\InternalServers\DHCP_Logger.h" />
<ClInclude Include="DEV9\InternalServers\DHCP_Server.h" />
<ClInclude Include="DEV9\InternalServers\DNS_Logger.h" />
<ClInclude Include="DEV9\InternalServers\DNS_Server.h" />

View File

@ -884,6 +884,9 @@
<ClCompile Include="DEV9\flash.cpp">
<Filter>System\Ps2\DEV9</Filter>
</ClCompile>
<ClCompile Include="DEV9\InternalServers\DHCP_Logger.cpp">
<Filter>System\Ps2\DEV9\InternalServers</Filter>
</ClCompile>
<ClCompile Include="DEV9\InternalServers\DHCP_Server.cpp">
<Filter>System\Ps2\DEV9\InternalServers</Filter>
</ClCompile>
@ -1736,6 +1739,9 @@
<ClInclude Include="DEV9\DEV9.h">
<Filter>System\Ps2\DEV9</Filter>
</ClInclude>
<ClInclude Include="DEV9\InternalServers\DHCP_Logger.h">
<Filter>System\Ps2\DEV9\InternalServers</Filter>
</ClInclude>
<ClInclude Include="DEV9\InternalServers\DHCP_Server.h">
<Filter>System\Ps2\DEV9\InternalServers</Filter>
</ClInclude>