From dc9f61e70a81bd20016e46348b024e059792377c Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Sun, 15 Jan 2023 21:18:13 +0000 Subject: [PATCH] DEV9: Add classes for editing packets and make PCAP use them --- pcsx2/CMakeLists.txt | 4 + .../PacketReader/ARP/ARP_PacketEditor.cpp | 79 ++++++++++ .../DEV9/PacketReader/ARP/ARP_PacketEditor.h | 42 +++++ .../DEV9/PacketReader/EthernetFrameEditor.cpp | 66 ++++++++ pcsx2/DEV9/PacketReader/EthernetFrameEditor.h | 45 ++++++ pcsx2/DEV9/pcap_io.cpp | 49 +++--- pcsx2/DEV9/pcap_io.h | 149 ------------------ pcsx2/pcsx2core.vcxproj | 4 + pcsx2/pcsx2core.vcxproj.filters | 12 ++ 9 files changed, 278 insertions(+), 172 deletions(-) create mode 100644 pcsx2/DEV9/PacketReader/ARP/ARP_PacketEditor.cpp create mode 100644 pcsx2/DEV9/PacketReader/ARP/ARP_PacketEditor.h create mode 100644 pcsx2/DEV9/PacketReader/EthernetFrameEditor.cpp create mode 100644 pcsx2/DEV9/PacketReader/EthernetFrameEditor.h diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 47429450dc..0fda95c59b 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -329,6 +329,7 @@ set(pcsx2DEV9Sources DEV9/InternalServers/DNS_Logger.cpp DEV9/InternalServers/DNS_Server.cpp DEV9/PacketReader/ARP/ARP_Packet.cpp + DEV9/PacketReader/ARP/ARP_PacketEditor.cpp DEV9/PacketReader/IP/ICMP/ICMP_Packet.cpp DEV9/PacketReader/IP/TCP/TCP_Options.cpp DEV9/PacketReader/IP/TCP/TCP_Packet.cpp @@ -340,6 +341,7 @@ set(pcsx2DEV9Sources DEV9/PacketReader/IP/IP_Options.cpp DEV9/PacketReader/IP/IP_Packet.cpp DEV9/PacketReader/EthernetFrame.cpp + DEV9/PacketReader/EthernetFrameEditor.cpp DEV9/Sessions/BaseSession.cpp DEV9/Sessions/ICMP_Session/ICMP_Session.cpp DEV9/Sessions/TCP_Session/TCP_Session.cpp @@ -366,6 +368,7 @@ set(pcsx2DEV9Headers DEV9/InternalServers/DNS_Server.h DEV9/net.h DEV9/PacketReader/ARP/ARP_Packet.h + DEV9/PacketReader/ARP/ARP_PacketEditor.h DEV9/PacketReader/IP/ICMP/ICMP_Packet.h DEV9/PacketReader/IP/TCP/TCP_Options.h DEV9/PacketReader/IP/TCP/TCP_Packet.h @@ -380,6 +383,7 @@ set(pcsx2DEV9Headers DEV9/PacketReader/IP/IP_Packet.h DEV9/PacketReader/IP/IP_Payload.h DEV9/PacketReader/EthernetFrame.h + DEV9/PacketReader/EthernetFrameEditor.h DEV9/PacketReader/MAC_Address.h DEV9/PacketReader/NetLib.h DEV9/PacketReader/Payload.h diff --git a/pcsx2/DEV9/PacketReader/ARP/ARP_PacketEditor.cpp b/pcsx2/DEV9/PacketReader/ARP/ARP_PacketEditor.cpp new file mode 100644 index 0000000000..045b6f5382 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/ARP/ARP_PacketEditor.cpp @@ -0,0 +1,79 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2023 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#include "PrecompiledHeader.h" + +#include "ARP_PacketEditor.h" + +#ifdef _WIN32 +#include "winsock.h" +#else +#include +#endif + +namespace PacketReader::ARP +{ + ARP_PacketEditor::ARP_PacketEditor(PayloadPtr* pkt) + : basePkt{pkt} + { + } + + u16 ARP_PacketEditor::GetHardwareType() + { + return ntohs(*(u16*)&basePkt->data[0]); + } + + u16 ARP_PacketEditor::GetProtocol() + { + return ntohs(*(u16*)&basePkt->data[2]); + } + + u8 ARP_PacketEditor::GetHardwareAddressLength() + { + return basePkt->data[4]; + } + u8 ARP_PacketEditor::GetProtocolAddressLength() + { + return basePkt->data[5]; + } + + u16 ARP_PacketEditor::GetOp() + { + return ntohs(*(u16*)&basePkt->data[6]); + } + + u8* ARP_PacketEditor::SenderHardwareAddress() + { + return &basePkt->data[8]; + } + + u8* ARP_PacketEditor::SenderProtocolAddress() + { + int offset = 8 + GetHardwareAddressLength(); + return &basePkt->data[offset]; + } + + u8* ARP_PacketEditor::TargetHardwareAddress() + { + int offset = 8 + GetHardwareAddressLength() + GetProtocolAddressLength(); + return &basePkt->data[offset]; + } + + u8* ARP_PacketEditor::TargetProtocolAddress() + { + int offset = 8 + 2 * GetHardwareAddressLength() + GetProtocolAddressLength(); + return &basePkt->data[offset]; + } +} // namespace PacketReader::ARP diff --git a/pcsx2/DEV9/PacketReader/ARP/ARP_PacketEditor.h b/pcsx2/DEV9/PacketReader/ARP/ARP_PacketEditor.h new file mode 100644 index 0000000000..5e694dc7a6 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/ARP/ARP_PacketEditor.h @@ -0,0 +1,42 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2023 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#pragma once + +#include "DEV9/PacketReader/Payload.h" + +namespace PacketReader::ARP +{ + class ARP_PacketEditor + { + private: + PayloadPtr* basePkt; + + public: + + ARP_PacketEditor(PayloadPtr* pkt); + + u16 GetHardwareType(); + u16 GetProtocol(); + u8 GetHardwareAddressLength(); + u8 GetProtocolAddressLength(); + u16 GetOp(); + + u8* SenderHardwareAddress(); + u8* SenderProtocolAddress(); + u8* TargetHardwareAddress(); + u8* TargetProtocolAddress(); + }; +} // namespace PacketReader::ARP diff --git a/pcsx2/DEV9/PacketReader/EthernetFrameEditor.cpp b/pcsx2/DEV9/PacketReader/EthernetFrameEditor.cpp new file mode 100644 index 0000000000..5b0404055b --- /dev/null +++ b/pcsx2/DEV9/PacketReader/EthernetFrameEditor.cpp @@ -0,0 +1,66 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2023 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#include "PrecompiledHeader.h" + +#include "EthernetFrameEditor.h" + +#ifdef _WIN32 +#include "winsock.h" +#else +#include +#endif + +namespace PacketReader +{ + EthernetFrameEditor::EthernetFrameEditor(NetPacket* pkt) + : basePkt{pkt} + { + headerLength = 14; //(6+6+2) + + //Note: we don't have to worry about the Ethernet Frame CRC as it is not included in the packet + //Note: We don't support tagged frames + + payload = std::make_unique((u8*)&basePkt->buffer[14], pkt->size - headerLength); + } + + MAC_Address EthernetFrameEditor::GetDestinationMAC() + { + return *(MAC_Address*)&basePkt->buffer[0]; + } + void EthernetFrameEditor::SetDestinationMAC(MAC_Address value) + { + *(MAC_Address*)&basePkt->buffer[0] = value; + } + + MAC_Address EthernetFrameEditor::GetSourceMAC() + { + return *(MAC_Address*)&basePkt->buffer[6]; + } + void EthernetFrameEditor::SetSourceMAC(MAC_Address value) + { + *(MAC_Address*)&basePkt->buffer[6] = value; + } + + u16 EthernetFrameEditor::GetProtocol() + { + return ntohs(*(u16*)&basePkt->buffer[12]); + } + + PayloadPtr* EthernetFrameEditor::GetPayload() + { + return payload.get(); + } +} // namespace PacketReader diff --git a/pcsx2/DEV9/PacketReader/EthernetFrameEditor.h b/pcsx2/DEV9/PacketReader/EthernetFrameEditor.h new file mode 100644 index 0000000000..3dde9d52a9 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/EthernetFrameEditor.h @@ -0,0 +1,45 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2023 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#pragma once + +#include "DEV9/net.h" +#include "MAC_Address.h" +#include "Payload.h" + +namespace PacketReader +{ + class EthernetFrameEditor + { + public: + int headerLength = 14; + //Length + private: + NetPacket* basePkt; + std::unique_ptr payload; + + public: + EthernetFrameEditor(NetPacket* pkt); + + MAC_Address GetDestinationMAC(); + void SetDestinationMAC(MAC_Address value); + MAC_Address GetSourceMAC(); + void SetSourceMAC(MAC_Address value); + + u16 GetProtocol(); + + PayloadPtr* GetPayload(); + }; +} // namespace PacketReader diff --git a/pcsx2/DEV9/pcap_io.cpp b/pcsx2/DEV9/pcap_io.cpp index 57a59ae857..5dc70aa7f4 100644 --- a/pcsx2/DEV9/pcap_io.cpp +++ b/pcsx2/DEV9/pcap_io.cpp @@ -30,6 +30,9 @@ #include "DEV9.h" #include "AdapterUtils.h" #include "net.h" +#include "PacketReader/EthernetFrame.h" +#include "PacketReader/EthernetFrameEditor.h" +#include "PacketReader/ARP/ARP_PacketEditor.h" #ifndef PCAP_NETMASK_UNKNOWN #define PCAP_NETMASK_UNKNOWN 0xffffffff #endif @@ -39,6 +42,7 @@ #endif using namespace PacketReader; +using namespace PacketReader::ARP; using namespace PacketReader::IP; #ifdef _WIN32 @@ -157,6 +161,7 @@ bool PCAPAdapter::recv(NetPacket* pkt) pxAssert(header->len == header->caplen); memcpy(pkt->buffer, pkt_data, header->len); + pkt->size = (int)header->len; if (!switched) SetMACBridgedRecv(pkt); @@ -376,43 +381,41 @@ bool PCAPAdapter::SetMACSwitchedFilter(MAC_Address mac) void PCAPAdapter::SetMACBridgedRecv(NetPacket* pkt) { - ethernet_header* eth = (ethernet_header*)pkt->buffer; - if (eth->protocol == 0x0008) // IP + EthernetFrameEditor frame(pkt); + if (frame.GetProtocol() == (u16)EtherType::IPv4) // IP { // Compare DEST IP in IP with the PS2's IP, if they match, change DEST MAC to ps2MAC. - const ip_header* iph = ((ip_header*)(pkt->buffer + sizeof(ethernet_header))); - - if (*(IP_Address*)&iph->dst == ps2IP) - eth->dst = *(mac_address*)&ps2MAC; + PayloadPtr* payload = frame.GetPayload(); + IP_Packet ippkt(payload->data, payload->GetLength()); + if (ippkt.destinationIP == ps2IP) + frame.SetDestinationMAC(ps2MAC); } - - if (eth->protocol == 0x0608) // ARP + if (frame.GetProtocol() == (u16)EtherType::ARP) // ARP { // Compare DEST IP in ARP with the PS2's IP, if they match, DEST MAC to ps2MAC on both ARP and ETH Packet headers. - arp_packet* aph = ((arp_packet*)(pkt->buffer + sizeof(ethernet_header))); - - if (*(IP_Address*)&aph->p_dst == ps2IP) + ARP_PacketEditor arpPkt(frame.GetPayload()); + if (*(IP_Address*)arpPkt.TargetProtocolAddress() == ps2IP) { - eth->dst = *(mac_address*)&ps2MAC; - ((arp_packet*)(pkt->buffer + sizeof(ethernet_header)))->h_dst = *(mac_address*)&ps2MAC; + frame.SetDestinationMAC(ps2MAC); + *(MAC_Address*)arpPkt.TargetHardwareAddress() = ps2MAC; } } } void PCAPAdapter::SetMACBridgedSend(NetPacket* pkt) { - ethernet_header* eth = (ethernet_header*)pkt->buffer; - if (eth->protocol == 0x0008) // IP + EthernetFrameEditor frame(pkt); + if (frame.GetProtocol() == (u16)EtherType::IPv4) // IP { - const ip_address ps2_ip = ((ip_header*)((u8*)pkt->buffer + sizeof(ethernet_header)))->src; - ps2IP = *(IP_Address*)&ps2_ip; + PayloadPtr* payload = frame.GetPayload(); + IP_Packet ippkt(payload->data, payload->GetLength()); + ps2IP = ippkt.sourceIP; } - if (eth->protocol == 0x0608) // ARP + if (frame.GetProtocol() == (u16)EtherType::ARP) // ARP { - const ip_address ps2_ip = ((arp_packet*)((u8*)pkt->buffer + sizeof(ethernet_header)))->p_src; - ps2IP = *(IP_Address*)&ps2_ip; - - ((arp_packet*)(pkt->buffer + sizeof(ethernet_header)))->h_src = *(mac_address*)&hostMAC; + ARP_PacketEditor arpPkt(frame.GetPayload()); + ps2IP = *(IP_Address*)arpPkt.SenderProtocolAddress(); + *(MAC_Address*)arpPkt.SenderHardwareAddress() = hostMAC; } - eth->src = *(mac_address*)&hostMAC; + frame.SetSourceMAC(hostMAC); } diff --git a/pcsx2/DEV9/pcap_io.h b/pcsx2/DEV9/pcap_io.h index 34e9122916..a8b745f09f 100644 --- a/pcsx2/DEV9/pcap_io.h +++ b/pcsx2/DEV9/pcap_io.h @@ -18,160 +18,11 @@ #include "net.h" #include "PacketReader/MAC_Address.h" -#ifdef __cplusplus -extern "C" { -#endif - - -//#ifndef _WIN32 -#pragma pack(push, 1) -typedef struct _ip_address -{ - u_char bytes[4]; -} ip_address; - -typedef struct _mac_address -{ - u_char bytes[6]; -} mac_address; - -typedef struct _ethernet_header -{ - mac_address dst; - mac_address src; - u_short protocol; -} ethernet_header; - -typedef struct _arp_packet -{ - u_short hw_type; - u_short protocol; - u_char h_addr_len; - u_char p_addr_len; - u_short operation; - mac_address h_src; - ip_address p_src; - mac_address h_dst; - ip_address p_dst; -} arp_packet; - -typedef struct _ip_header -{ - u_char ver_hlen; /* version << 4 | header length >> 2 */ - u_char type; /* type of service */ - u_short len; /* total length */ - u_short id; /* identification */ - u_short offset; /* fragment offset field */ - u_char ttl; /* time to live */ - u_char proto; /* protocol */ - u_short hdr_csum; /* checksum */ - ip_address src; /* source and dest address */ - ip_address dst; -} ip_header; - -/* Internet Control Message Protocol Constants and Packet Format */ - -/* ic_type field */ -#define ICT_ECHORP 0 /* Echo reply */ -#define ICT_DESTUR 3 /* Destination unreachable */ -#define ICT_SRCQ 4 /* Source quench */ -#define ICT_REDIRECT 5 /* Redirect message type */ -#define ICT_ECHORQ 8 /* Echo request */ -#define ICT_TIMEX 11 /* Time exceeded */ -#define ICT_PARAMP 12 /* Parameter Problem */ -#define ICT_TIMERQ 13 /* Timestamp request */ -#define ICT_TIMERP 14 /* Timestamp reply */ -#define ICT_INFORQ 15 /* Information request */ -#define ICT_INFORP 16 /* Information reply */ -#define ICT_MASKRQ 17 /* Mask request */ -#define ICT_MASKRP 18 /* Mask reply */ - -/* ic_code field */ -#define ICC_NETUR 0 /* dest unreachable, net unreachable */ -#define ICC_HOSTUR 1 /* dest unreachable, host unreachable */ -#define ICC_PROTOUR 2 /* dest unreachable, proto unreachable */ -#define ICC_PORTUR 3 /* dest unreachable, port unreachable */ -#define ICC_FNADF 4 /* dest unr, frag needed & don't frag */ -#define ICC_SRCRT 5 /* dest unreachable, src route failed */ - -#define ICC_NETRD 0 /* redirect: net */ -#define ICC_HOSTRD 1 /* redirect: host */ -#define IC_TOSNRD 2 /* redirect: type of service, net */ -#define IC_TOSHRD 3 /* redirect: type of service, host */ - -#define ICC_TIMEX 0 /* time exceeded, ttl */ -#define ICC_FTIMEX 1 /* time exceeded, frag */ - -#define IC_HLEN 8 /* octets */ -#define IC_PADLEN 3 /* pad length (octets) */ - -#define IC_RDTTL 300 /* ttl for redirect routes */ - - -/* ICMP packet format (following the IP header) */ -typedef struct _icmp_header -{ /* ICMP packet */ - char type; /* type of message (ICT_* above)*/ - char code; /* code (ICC_* above) */ - short csum; /* checksum of ICMP header+data */ - - union - { - struct - { - int ic1_id : 16; /* echo type, a message id */ - int ic1_seq : 16; /* echo type, a seq. number */ - } ic1; - ip_address ic2_gw; /* for redirect, gateway */ - struct - { - char ic3_ptr; /* pointer, for ICT_PARAMP */ - char ic3_pad[IC_PADLEN]; - } ic3; - int ic4_mbz; /* must be zero */ - } icu; -} icmp_header; - -/*typedef struct _udp_header { - u16 src_port; - u16 dst_port; - u16 len; - u16 csum; -} udp_header;*/ - -typedef struct _full_arp_packet -{ - ethernet_header header; - arp_packet arp; -} full_arp_packet; - -#pragma pack(pop) - -#define ARP_REQUEST 0x0100 //values are big-endian - -#define mac_compare(a, b) (memcmp(&(a), &(b), 6)) -#define ip_compare(a, b) (memcmp(&(a), &(b), 4)) - -//#endif -/* -int pcap_io_init(char *adapter); -int pcap_io_send(void* packet, int plen); -int pcap_io_recv(void* packet, int max_len); -void pcap_io_close(); -int pcap_io_get_dev_num(); -char* pcap_io_get_dev_desc(int num); -char* pcap_io_get_dev_name(int num); -*/ - #ifdef _WIN32 bool load_pcap(); void unload_pcap(); #endif -#ifdef __cplusplus -} -#endif - class PCAPAdapter : public NetAdapter { private: diff --git a/pcsx2/pcsx2core.vcxproj b/pcsx2/pcsx2core.vcxproj index e2dd136743..b1a561bafe 100644 --- a/pcsx2/pcsx2core.vcxproj +++ b/pcsx2/pcsx2core.vcxproj @@ -166,6 +166,8 @@ + + @@ -510,6 +512,8 @@ + + diff --git a/pcsx2/pcsx2core.vcxproj.filters b/pcsx2/pcsx2core.vcxproj.filters index 2128590ee1..a4a8d86862 100644 --- a/pcsx2/pcsx2core.vcxproj.filters +++ b/pcsx2/pcsx2core.vcxproj.filters @@ -908,6 +908,9 @@ System\Ps2\DEV9\PacketReader\ARP + + System\Ps2\DEV9\PacketReader\ARP + System\Ps2\DEV9\PacketReader\IP\ICMP @@ -941,6 +944,9 @@ System\Ps2\DEV9\PacketReader + + System\Ps2\DEV9\PacketReader + System\Ps2\DEV9 @@ -1780,6 +1786,9 @@ System\Ps2\DEV9\PacketReader\ARP + + System\Ps2\DEV9\PacketReader\ARP + System\Ps2\DEV9\PacketReader\IP\ICMP @@ -1822,6 +1831,9 @@ System\Ps2\DEV9\PacketReader + + System\Ps2\DEV9\PacketReader + System\Ps2\DEV9\PacketReader