diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index cdedf6eb19..012ddd56b0 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -356,6 +356,10 @@ set(pcsx2DEV9Sources DEV9/InternalServers/DHCP_Server.cpp DEV9/InternalServers/DNS_Logger.cpp DEV9/InternalServers/DNS_Server.cpp + DEV9/PacketReader/ARP/ARP_Packet.cpp + DEV9/PacketReader/IP/ICMP/ICMP_Packet.cpp + DEV9/PacketReader/IP/TCP/TCP_Options.cpp + DEV9/PacketReader/IP/TCP/TCP_Packet.cpp DEV9/PacketReader/IP/UDP/DHCP/DHCP_Options.cpp DEV9/PacketReader/IP/UDP/DHCP/DHCP_Packet.cpp DEV9/PacketReader/IP/UDP/DNS/DNS_Classes.cpp @@ -381,6 +385,10 @@ set(pcsx2DEV9Headers DEV9/InternalServers/DNS_Logger.h DEV9/InternalServers/DNS_Server.h DEV9/net.h + DEV9/PacketReader/ARP/ARP_Packet.h + DEV9/PacketReader/IP/ICMP/ICMP_Packet.h + DEV9/PacketReader/IP/TCP/TCP_Options.h + DEV9/PacketReader/IP/TCP/TCP_Packet.h DEV9/PacketReader/IP/UDP/DHCP/DHCP_Options.h DEV9/PacketReader/IP/UDP/DHCP/DHCP_Packet.h DEV9/PacketReader/IP/UDP/DNS/DNS_Classes.h diff --git a/pcsx2/DEV9/PacketReader/ARP/ARP_Packet.cpp b/pcsx2/DEV9/PacketReader/ARP/ARP_Packet.cpp new file mode 100644 index 0000000000..818687bd91 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/ARP/ARP_Packet.cpp @@ -0,0 +1,98 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2021 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_Packet.h" +#include "DEV9/PacketReader/NetLib.h" + +namespace PacketReader::ARP +{ + ARP_Packet::ARP_Packet(u8 hwAddrLen, u8 procAddrLen) + : hardwareAddressLength{hwAddrLen} + , protocolAddressLength{procAddrLen} + , senderHardwareAddress{std::make_unique(hwAddrLen)} + , senderProtocolAddress{std::make_unique(procAddrLen)} + , targetHardwareAddress{std::make_unique(hwAddrLen)} + , targetProtocolAddress{std::make_unique(procAddrLen)} + { + } + + ARP_Packet::ARP_Packet(u8* buffer, int bufferSize) + { + int offset = 0; + + NetLib::ReadUInt16(buffer, &offset, &hardwareType); + NetLib::ReadUInt16(buffer, &offset, &protocol); + // + NetLib::ReadByte08(buffer, &offset, &hardwareAddressLength); + NetLib::ReadByte08(buffer, &offset, &protocolAddressLength); + + NetLib::ReadUInt16(buffer, &offset, &op); + + //Allocate arrays + senderHardwareAddress = std::make_unique(hardwareAddressLength); + senderProtocolAddress = std::make_unique(protocolAddressLength); + targetHardwareAddress = std::make_unique(hardwareAddressLength); + targetProtocolAddress = std::make_unique(protocolAddressLength); + + //Assume normal MAC/IP address lengths for logging + + NetLib::ReadByteArray(buffer, &offset, hardwareAddressLength, senderHardwareAddress.get()); + NetLib::ReadByteArray(buffer, &offset, protocolAddressLength, senderProtocolAddress.get()); + + NetLib::ReadByteArray(buffer, &offset, hardwareAddressLength, targetHardwareAddress.get()); + NetLib::ReadByteArray(buffer, &offset, protocolAddressLength, targetProtocolAddress.get()); + } + ARP_Packet::ARP_Packet(const ARP_Packet& original) + : hardwareType{original.hardwareType} + , protocol{original.protocol} + , hardwareAddressLength{original.hardwareAddressLength} + , protocolAddressLength{original.protocolAddressLength} + , op{original.protocol} + , senderHardwareAddress{std::make_unique(original.hardwareAddressLength)} + , senderProtocolAddress{std::make_unique(original.protocolAddressLength)} + , targetHardwareAddress{std::make_unique(original.hardwareAddressLength)} + , targetProtocolAddress{std::make_unique(original.protocolAddressLength)} + { + memcpy(senderHardwareAddress.get(), original.senderHardwareAddress.get(), hardwareAddressLength); + memcpy(senderProtocolAddress.get(), original.senderProtocolAddress.get(), protocolAddressLength); + memcpy(targetHardwareAddress.get(), original.targetHardwareAddress.get(), hardwareAddressLength); + memcpy(targetProtocolAddress.get(), original.targetProtocolAddress.get(), protocolAddressLength); + } + + int ARP_Packet::GetLength() + { + return 8 + 2 * hardwareAddressLength + 2 * protocolAddressLength; + } + + void ARP_Packet::WriteBytes(u8* buffer, int* offset) + { + NetLib::WriteUInt16(buffer, offset, hardwareType); + NetLib::WriteUInt16(buffer, offset, protocol); + NetLib::WriteByte08(buffer, offset, hardwareAddressLength); + NetLib::WriteByte08(buffer, offset, protocolAddressLength); + NetLib::WriteUInt16(buffer, offset, op); + NetLib::WriteByteArray(buffer, offset, hardwareAddressLength, senderHardwareAddress.get()); + NetLib::WriteByteArray(buffer, offset, protocolAddressLength, senderProtocolAddress.get()); + NetLib::WriteByteArray(buffer, offset, hardwareAddressLength, targetHardwareAddress.get()); + NetLib::WriteByteArray(buffer, offset, protocolAddressLength, targetProtocolAddress.get()); + } + + ARP_Packet* ARP_Packet::Clone() const + { + return new ARP_Packet(*this); + } +} // namespace PacketReader::ARP diff --git a/pcsx2/DEV9/PacketReader/ARP/ARP_Packet.h b/pcsx2/DEV9/PacketReader/ARP/ARP_Packet.h new file mode 100644 index 0000000000..64517f66f1 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/ARP/ARP_Packet.h @@ -0,0 +1,44 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2021 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 + +#include "DEV9/PacketReader/Payload.h" + +namespace PacketReader::ARP +{ + class ARP_Packet : public Payload + { + public: + u16 hardwareType; + u16 protocol; + u8 hardwareAddressLength = 6; + u8 protocolAddressLength = 4; + u16 op; + std::unique_ptr senderHardwareAddress; + std::unique_ptr senderProtocolAddress; + std::unique_ptr targetHardwareAddress; + std::unique_ptr targetProtocolAddress; + + ARP_Packet(u8 hwAddrLen, u8 procAddrLen); + ARP_Packet(u8* buffer, int bufferSize); + ARP_Packet(const ARP_Packet&); + + virtual int GetLength(); + virtual void WriteBytes(u8* buffer, int* offset); + virtual ARP_Packet* Clone() const; + }; +} // namespace PacketReader::ARP diff --git a/pcsx2/DEV9/PacketReader/IP/ICMP/ICMP_Packet.cpp b/pcsx2/DEV9/PacketReader/IP/ICMP/ICMP_Packet.cpp new file mode 100644 index 0000000000..44aa35cab6 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/IP/ICMP/ICMP_Packet.cpp @@ -0,0 +1,124 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2021 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 "ICMP_Packet.h" +#include "DEV9/PacketReader/NetLib.h" + +namespace PacketReader::IP::ICMP +{ + ICMP_Packet::ICMP_Packet(Payload* data) + : payload{data} + { + } + ICMP_Packet::ICMP_Packet(u8* buffer, int bufferSize) + { + int offset = 0; + //Bits 0-31 + NetLib::ReadByte08(buffer, &offset, &type); + NetLib::ReadByte08(buffer, &offset, &code); + NetLib::ReadUInt16(buffer, &offset, &checksum); + + //Bits 32-63 + NetLib::ReadByteArray(buffer, &offset, 4, headerData); + + //Bits 64+ + payload = std::make_unique(&buffer[offset], bufferSize - offset); + //AllDone + } + ICMP_Packet::ICMP_Packet(const ICMP_Packet& original) + : type{original.type} + , code{original.code} + , checksum{original.checksum} + , payload{original.payload->Clone()} + { + memcpy(headerData, original.headerData, 4); + } + + Payload* ICMP_Packet::GetPayload() + { + return payload.get(); + } + + int ICMP_Packet::GetLength() + { + return headerLength + payload->GetLength(); + } + + void ICMP_Packet::WriteBytes(u8* buffer, int* offset) + { + NetLib::WriteByte08(buffer, offset, type); + NetLib::WriteByte08(buffer, offset, code); + NetLib::WriteUInt16(buffer, offset, checksum); + NetLib::WriteByteArray(buffer, offset, 4, headerData); + + payload->WriteBytes(buffer, offset); + } + + ICMP_Packet* ICMP_Packet::Clone() const + { + return new ICMP_Packet(*this); + } + + u8 ICMP_Packet::GetProtocol() + { + return (u8)protocol; + } + + void ICMP_Packet::CalculateChecksum(IP_Address srcIP, IP_Address dstIP) + { + int pHeaderLen = headerLength + payload->GetLength(); + if ((pHeaderLen & 1) != 0) + { + pHeaderLen += 1; + } + + u8* segment = new u8[pHeaderLen]; + int counter = 0; + + checksum = 0; + WriteBytes(segment, &counter); + + //Zero alignment byte + if (counter != pHeaderLen) + NetLib::WriteByte08(segment, &counter, 0); + + checksum = IP_Packet::InternetChecksum(segment, pHeaderLen); + delete[] segment; + } + bool ICMP_Packet::VerifyChecksum(IP_Address srcIP, IP_Address dstIP) + { + int pHeaderLen = headerLength + payload->GetLength(); + if ((pHeaderLen & 1) != 0) + { + pHeaderLen += 1; + } + + u8* segment = new u8[pHeaderLen]; + int counter = 0; + + WriteBytes(segment, &counter); + + //Zero alignment byte + if (counter != pHeaderLen) + NetLib::WriteByte08(segment, &counter, 0); + + u16 csumCal = IP_Packet::InternetChecksum(segment, pHeaderLen); + delete[] segment; + + return (csumCal == 0); + } +} // namespace PacketReader::IP::ICMP diff --git a/pcsx2/DEV9/PacketReader/IP/ICMP/ICMP_Packet.h b/pcsx2/DEV9/PacketReader/IP/ICMP/ICMP_Packet.h new file mode 100644 index 0000000000..bb1b0641e3 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/IP/ICMP/ICMP_Packet.h @@ -0,0 +1,56 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2021 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/IP/IP_Packet.h" + +namespace PacketReader::IP::ICMP +{ + class ICMP_Packet : public IP_Payload + { + public: + u8 type; + u8 code; + + private: + u16 checksum; + + public: + u8 headerData[4]; + + private: + const static int headerLength = 8; + const static IP_Type protocol = IP_Type::ICMP; + + std::unique_ptr payload; + + public: + //Takes ownership of payload + ICMP_Packet(Payload* data); + ICMP_Packet(u8* buffer, int bufferSize); + ICMP_Packet(const ICMP_Packet&); + + Payload* GetPayload(); + + virtual int GetLength(); + virtual void WriteBytes(u8* buffer, int* offset); + virtual ICMP_Packet* Clone() const; + + virtual u8 GetProtocol(); + + virtual bool VerifyChecksum(IP_Address srcIP, IP_Address dstIP); + virtual void CalculateChecksum(IP_Address srcIP, IP_Address dstIP); + }; +} // namespace PacketReader::IP::ICMP diff --git a/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Options.cpp b/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Options.cpp new file mode 100644 index 0000000000..069ab42bd4 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Options.cpp @@ -0,0 +1,76 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2021 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 "TCP_Options.h" +#include "DEV9/PacketReader/NetLib.h" + +namespace PacketReader::IP::TCP +{ + TCPopMSS::TCPopMSS(u16 mss) + : maxSegmentSize{mss} + { + } + TCPopMSS::TCPopMSS(u8* data, int offset) + { + offset += 2; + NetLib::ReadUInt16(data, &offset, &maxSegmentSize); + } + void TCPopMSS::WriteBytes(u8* buffer, int* offset) + { + NetLib::WriteByte08(buffer, offset, GetCode()); + NetLib::WriteByte08(buffer, offset, GetLength()); + + NetLib::WriteUInt16(buffer, offset, maxSegmentSize); + } + + TCPopWS::TCPopWS(u8 ws) + : windowScale{ws} + { + } + TCPopWS::TCPopWS(u8* data, int offset) + { + offset += 2; + NetLib::ReadByte08(data, &offset, &windowScale); + } + void TCPopWS::WriteBytes(u8* buffer, int* offset) + { + NetLib::WriteByte08(buffer, offset, GetCode()); + NetLib::WriteByte08(buffer, offset, GetLength()); + + NetLib::WriteByte08(buffer, offset, windowScale); + } + + TCPopTS::TCPopTS(u32 senderTS, u32 echoTS) + : senderTimeStamp{senderTS} + , echoTimeStamp{echoTS} + { + } + TCPopTS::TCPopTS(u8* data, int offset) + { + offset += 2; + NetLib::ReadUInt32(data, &offset, &senderTimeStamp); + NetLib::ReadUInt32(data, &offset, &echoTimeStamp); + } + void TCPopTS::WriteBytes(u8* buffer, int* offset) + { + NetLib::WriteByte08(buffer, offset, GetCode()); + NetLib::WriteByte08(buffer, offset, GetLength()); + + NetLib::WriteUInt32(buffer, offset, senderTimeStamp); + NetLib::WriteUInt32(buffer, offset, echoTimeStamp); + } +} // namespace PacketReader::IP::TCP diff --git a/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Options.h b/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Options.h new file mode 100644 index 0000000000..0b93f02d93 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Options.h @@ -0,0 +1,96 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2021 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/IP/IP_Options.h" + +namespace PacketReader::IP::TCP +{ + class TCPopNOP : public BaseOption + { + virtual u8 GetLength() { return 1; } + virtual u8 GetCode() { return 1; } + + virtual void WriteBytes(u8* buffer, int* offset) + { + buffer[*offset] = GetCode(); + (*offset)++; + } + + virtual TCPopNOP* Clone() const + { + return new TCPopNOP(*this); + } + }; + + class TCPopMSS : public BaseOption + { + public: + u16 maxSegmentSize; + + TCPopMSS(u16 mss); + TCPopMSS(u8* data, int offset); //Offset will include Kind and Len + + virtual u8 GetLength() { return 4; } + virtual u8 GetCode() { return 2; } + + virtual void WriteBytes(u8* buffer, int* offset); + + virtual TCPopMSS* Clone() const + { + return new TCPopMSS(*this); + } + }; + + class TCPopWS : public BaseOption + { + public: + u8 windowScale; + + TCPopWS(u8 ws); + TCPopWS(u8* data, int offset); //Offset will include Kind and Len + + virtual u8 GetLength() { return 3; } + virtual u8 GetCode() { return 3; } + + virtual void WriteBytes(u8* buffer, int* offset); + + virtual TCPopWS* Clone() const + { + return new TCPopWS(*this); + } + }; + + class TCPopTS : public BaseOption + { + public: + u32 senderTimeStamp; + u32 echoTimeStamp; + + TCPopTS(u32 senderTS, u32 echoTS); + TCPopTS(u8* data, int offset); //Offset will include Kind and Len + + virtual u8 GetLength() { return 10; } + virtual u8 GetCode() { return 8; } + + virtual void WriteBytes(u8* buffer, int* offset); + + virtual TCPopTS* Clone() const + { + return new TCPopTS(*this); + } + }; +} // namespace PacketReader::IP::TCP diff --git a/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Packet.cpp b/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Packet.cpp new file mode 100644 index 0000000000..ba7651b1be --- /dev/null +++ b/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Packet.cpp @@ -0,0 +1,313 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2021 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 "TCP_Packet.h" +#include "DEV9/PacketReader/NetLib.h" + +namespace PacketReader::IP::TCP +{ + //Need flags + bool TCP_Packet::GetNS() + { + return (dataOffsetAndNS_Flag & 1); + } + void TCP_Packet::SetNS(bool value) + { + dataOffsetAndNS_Flag = (dataOffsetAndNS_Flag & ~0x1) | (value & 0x1); + } + + bool TCP_Packet::GetCWR() + { + return (flags & (1 << 7)); + } + void TCP_Packet::SetCWR(bool value) + { + flags = (flags & ~(0x1 << 7)) | ((value & 0x1) << 7); + } + + bool TCP_Packet::GetECE() + { + return (flags & (1 << 6)); + } + void TCP_Packet::SetECE(bool value) + { + flags = (flags & ~(0x1 << 6)) | ((value & 0x1) << 6); + } + + bool TCP_Packet::GetURG() + { + return (flags & (1 << 5)); + } + void TCP_Packet::SetURG(bool value) + { + flags = (flags & ~(0x1 << 5)) | ((value & 0x1) << 5); + } + + bool TCP_Packet::GetACK() + { + return (flags & (1 << 4)); + } + void TCP_Packet::SetACK(bool value) + { + flags = (flags & ~(0x1 << 4)) | ((value & 0x1) << 4); + } + + bool TCP_Packet::GetPSH() + { + return (flags & (1 << 3)); + } + void TCP_Packet::SetPSH(bool value) + { + flags = (flags & ~(0x1 << 3)) | ((value & 0x1) << 3); + } + + bool TCP_Packet::GetRST() + { + return (flags & (1 << 2)); + } + void TCP_Packet::SetRST(bool value) + { + flags = (flags & ~(0x1 << 2)) | ((value & 0x1) << 2); + } + + bool TCP_Packet::GetSYN() + { + return (flags & (1 << 1)); + } + void TCP_Packet::SetSYN(bool value) + { + flags = (flags & ~(0x1 << 1)) | ((value & 0x1) << 1); + } + + bool TCP_Packet::GetFIN() + { + return (flags & 1); + } + void TCP_Packet::SetFIN(bool value) + { + flags = (flags & ~0x1) | (value & 0x1); + } + + TCP_Packet::TCP_Packet(Payload* data) + : headerLength{20} + , payload{data} + { + } + TCP_Packet::TCP_Packet(u8* buffer, int bufferSize) + { + int offset = 0; + //Bits 0-31 + NetLib::ReadUInt16(buffer, &offset, &sourcePort); + NetLib::ReadUInt16(buffer, &offset, &destinationPort); + + //Bits 32-63 + NetLib::ReadUInt32(buffer, &offset, &sequenceNumber); + + //Bits 64-95 + NetLib::ReadUInt32(buffer, &offset, &acknowledgementNumber); + + //Bits 96-127 + NetLib::ReadByte08(buffer, &offset, &dataOffsetAndNS_Flag); + headerLength = (dataOffsetAndNS_Flag >> 4) << 2; + NetLib::ReadByte08(buffer, &offset, &flags); + NetLib::ReadUInt16(buffer, &offset, &windowSize); + + //Bits 127-159 + NetLib::ReadUInt16(buffer, &offset, &checksum); + NetLib::ReadUInt16(buffer, &offset, &urgentPointer); + + //Bits 160+ + if (headerLength > 20) //TCP options + { + bool opReadFin = false; + do + { + u8 opKind = buffer[offset]; + u8 opLen = buffer[offset + 1]; + switch (opKind) + { + case 0: + opReadFin = true; + break; + case 1: + options.push_back(new TCPopNOP()); + offset += 1; + continue; + case 2: + options.push_back(new TCPopMSS(buffer, offset)); + break; + case 3: + options.push_back(new TCPopWS(buffer, offset)); + break; + case 8: + options.push_back(new TCPopTS(buffer, offset)); + break; + default: + Console.Error("Got Unknown TCP Option %d with len %d", opKind, opLen); + options.push_back(new IPopUnk(buffer, offset)); + break; + } + offset += opLen; + if (offset == headerLength) + opReadFin = true; + } while (opReadFin == false); + } + offset = headerLength; + + payload = std::make_unique(&buffer[offset], bufferSize - offset); + //AllDone + } + + TCP_Packet::TCP_Packet(const TCP_Packet& original) + : sourcePort{original.sourcePort} + , destinationPort{original.destinationPort} + , sequenceNumber{original.sequenceNumber} + , acknowledgementNumber{original.acknowledgementNumber} + , dataOffsetAndNS_Flag{original.dataOffsetAndNS_Flag} + , headerLength{original.headerLength} + , flags{original.flags} + , windowSize{original.windowSize} + , checksum{original.checksum} + , urgentPointer{original.urgentPointer} + , payload{original.payload->Clone()} + { + //Clone options + options.reserve(original.options.size()); + for (size_t i = 0; i < options.size(); i++) + options.push_back(original.options[i]->Clone()); + } + + Payload* TCP_Packet::GetPayload() + { + return payload.get(); + } + + int TCP_Packet::GetLength() + { + ReComputeHeaderLen(); + return headerLength + payload->GetLength(); + } + + void TCP_Packet::WriteBytes(u8* buffer, int* offset) + { + int startOff = *offset; + NetLib::WriteUInt16(buffer, offset, sourcePort); + NetLib::WriteUInt16(buffer, offset, destinationPort); + NetLib::WriteUInt32(buffer, offset, sequenceNumber); + NetLib::WriteUInt32(buffer, offset, acknowledgementNumber); + NetLib::WriteByte08(buffer, offset, dataOffsetAndNS_Flag); + NetLib::WriteByte08(buffer, offset, flags); + NetLib::WriteUInt16(buffer, offset, windowSize); + NetLib::WriteUInt16(buffer, offset, checksum); + NetLib::WriteUInt16(buffer, offset, urgentPointer); + + //options + for (size_t i = 0; i < options.size(); i++) + options[i]->WriteBytes(buffer, offset); + + //Zero alignment bytes + if (*offset != startOff + headerLength) + memset(&buffer[*offset], 0, startOff + headerLength - *offset); + + *offset = startOff + headerLength; + + payload->WriteBytes(buffer, offset); + } + + TCP_Packet* TCP_Packet::Clone() const + { + return new TCP_Packet(*this); + } + + u8 TCP_Packet::GetProtocol() + { + return (u8)protocol; + } + + void TCP_Packet::ReComputeHeaderLen() + { + int opOffset = 20; + for (size_t i = 0; i < options.size(); i++) + opOffset += options[i]->GetLength(); + + opOffset += opOffset % 4; //needs to be a whole number of 32bits + headerLength = opOffset; + + //Also write into dataOffsetAndNS_Flag + u8 ns = dataOffsetAndNS_Flag & 1; + dataOffsetAndNS_Flag = (headerLength >> 2) << 4; + dataOffsetAndNS_Flag |= ns; + } + + void TCP_Packet::CalculateChecksum(IP_Address srcIP, IP_Address dstIP) + { + ReComputeHeaderLen(); + int pHeaderLen = (12) + headerLength + payload->GetLength(); + if ((pHeaderLen & 1) != 0) + pHeaderLen += 1; + + u8* headerSegment = new u8[pHeaderLen]; + int counter = 0; + + NetLib::WriteByteArray(headerSegment, &counter, 4, (u8*)&srcIP); + NetLib::WriteByteArray(headerSegment, &counter, 4, (u8*)&dstIP); + NetLib::WriteByte08(headerSegment, &counter, 0); + NetLib::WriteByte08(headerSegment, &counter, (u8)protocol); + NetLib::WriteUInt16(headerSegment, &counter, GetLength()); + + //Pseudo Header added + //Rest of data is normal Header+data (with zerored checksum feild) + checksum = 0; + WriteBytes(headerSegment, &counter); + + //Zero alignment byte + if (counter != pHeaderLen) + NetLib::WriteByte08(headerSegment, &counter, 0); + + checksum = IP_Packet::InternetChecksum(headerSegment, pHeaderLen); + delete[] headerSegment; + } + bool TCP_Packet::VerifyChecksum(IP_Address srcIP, IP_Address dstIP) + { + ReComputeHeaderLen(); + int pHeaderLen = (12) + headerLength + payload->GetLength(); + if ((pHeaderLen & 1) != 0) + pHeaderLen += 1; + + u8* headerSegment = new u8[pHeaderLen]; + int counter = 0; + + NetLib::WriteByteArray(headerSegment, &counter, 4, (u8*)&srcIP); + NetLib::WriteByteArray(headerSegment, &counter, 4, (u8*)&dstIP); + NetLib::WriteByte08(headerSegment, &counter, 0); + NetLib::WriteByte08(headerSegment, &counter, (u8)protocol); + NetLib::WriteUInt16(headerSegment, &counter, GetLength()); + + //Pseudo Header added + //Rest of data is normal Header+data + WriteBytes(headerSegment, &counter); + + //Zero alignment byte + if (counter != pHeaderLen) + NetLib::WriteByte08(headerSegment, &counter, 0); + + u16 csumCal = IP_Packet::InternetChecksum(headerSegment, pHeaderLen); + delete[] headerSegment; + + return (csumCal == 0); + } +} // namespace PacketReader::IP::TCP diff --git a/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Packet.h b/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Packet.h new file mode 100644 index 0000000000..ebc82470e1 --- /dev/null +++ b/pcsx2/DEV9/PacketReader/IP/TCP/TCP_Packet.h @@ -0,0 +1,99 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2021 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 "TCP_Options.h" +#include "DEV9/PacketReader/IP/IP_Packet.h" + +namespace PacketReader::IP::TCP +{ + class TCP_Packet : public IP_Payload + { + public: + u16 sourcePort; + u16 destinationPort; + u32 sequenceNumber; + u32 acknowledgementNumber; + + private: + u8 dataOffsetAndNS_Flag = 0; + int headerLength; //Can have varying Header Len + u8 flags = 0; + + public: + u16 windowSize; + + private: + u16 checksum; + u16 urgentPointer = 0; + + public: + std::vector options; + + private: + const static IP_Type protocol = IP_Type::TCP; + + std::unique_ptr payload; + + public: + //Flags + bool GetNS(); + void SetNS(bool value); + + bool GetCWR(); + void SetCWR(bool value); + + bool GetECE(); + void SetECE(bool value); + + bool GetURG(); + void SetURG(bool value); + + bool GetACK(); + void SetACK(bool value); + + bool GetPSH(); + void SetPSH(bool value); + + bool GetRST(); + void SetRST(bool value); + + bool GetSYN(); + void SetSYN(bool value); + + bool GetFIN(); + void SetFIN(bool value); + + //Takes ownership of payload + TCP_Packet(Payload* data); + TCP_Packet(u8* buffer, int bufferSize); + TCP_Packet(const TCP_Packet&); + + Payload* GetPayload(); + + virtual int GetLength(); + virtual void WriteBytes(u8* buffer, int* offset); + virtual TCP_Packet* Clone() const; + + virtual u8 GetProtocol(); + + virtual bool VerifyChecksum(IP_Address srcIP, IP_Address dstIP); + virtual void CalculateChecksum(IP_Address srcIP, IP_Address dstIP); + + private: + void ReComputeHeaderLen(); + }; +} // namespace PacketReader::IP::TCP diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj index de8dbb9398..7abaeac36b 100644 --- a/pcsx2/pcsx2.vcxproj +++ b/pcsx2/pcsx2.vcxproj @@ -293,7 +293,11 @@ + + + + @@ -739,7 +743,11 @@ + + + + diff --git a/pcsx2/pcsx2.vcxproj.filters b/pcsx2/pcsx2.vcxproj.filters index d39f65ef8b..32e968e1c1 100644 --- a/pcsx2/pcsx2.vcxproj.filters +++ b/pcsx2/pcsx2.vcxproj.filters @@ -184,9 +184,18 @@ {57c4be94-9a2c-469b-9b02-b3b324857fc5} + + {12c15e0b-4647-4ce2-9bc4-89e6e9e8f531} + {a0723e13-c839-464d-8cfa-6c440ae03537} + + {928400ad-4db4-44ca-9a6d-c65e489c8ea0} + + + {7c01f24d-2141-4054-b3f9-1d9c67ae7ad6} + {db2fc75d-6552-4991-9155-885abd8796e4} @@ -1223,6 +1232,18 @@ System\Ps2\DEV9\InternalServers + + System\Ps2\DEV9\PacketReader\ARP + + + System\Ps2\DEV9\PacketReader\IP\ICMP + + + System\Ps2\DEV9\PacketReader\IP\TCP + + + System\Ps2\DEV9\PacketReader\IP\TCP + System\Ps2\DEV9\PacketReader\IP\UDP\DHCP @@ -2290,6 +2311,18 @@ System\Ps2\DEV9 + + System\Ps2\DEV9\PacketReader\ARP + + + System\Ps2\DEV9\PacketReader\IP\ICMP + + + System\Ps2\DEV9\PacketReader\IP\TCP + + + System\Ps2\DEV9\PacketReader\IP\TCP + System\Ps2\DEV9\PacketReader\IP\UDP\DHCP diff --git a/pcsx2/pcsx2core.vcxproj b/pcsx2/pcsx2core.vcxproj index 7c2b6736fa..67c683a82b 100644 --- a/pcsx2/pcsx2core.vcxproj +++ b/pcsx2/pcsx2core.vcxproj @@ -156,7 +156,11 @@ + + + + @@ -456,7 +460,11 @@ + + + + diff --git a/pcsx2/pcsx2core.vcxproj.filters b/pcsx2/pcsx2core.vcxproj.filters index 4b946e09dc..eb7167f705 100644 --- a/pcsx2/pcsx2core.vcxproj.filters +++ b/pcsx2/pcsx2core.vcxproj.filters @@ -142,9 +142,18 @@ {57c4be94-9a2c-469b-9b02-b3b324857fc5} + + {12c15e0b-4647-4ce2-9bc4-89e6e9e8f531} + {a0723e13-c839-464d-8cfa-6c440ae03537} + + {928400ad-4db4-44ca-9a6d-c65e489c8ea0} + + + {7c01f24d-2141-4054-b3f9-1d9c67ae7ad6} + {db2fc75d-6552-4991-9155-885abd8796e4} @@ -878,6 +887,18 @@ System\Ps2\DEV9\InternalServers + + System\Ps2\DEV9\PacketReader\ARP + + + System\Ps2\DEV9\PacketReader\IP\ICMP + + + System\Ps2\DEV9\PacketReader\IP\TCP + + + System\Ps2\DEV9\PacketReader\IP\TCP + System\Ps2\DEV9\PacketReader\IP\UDP\DHCP @@ -1619,6 +1640,18 @@ System\Ps2\DEV9 + + System\Ps2\DEV9\PacketReader\ARP + + + System\Ps2\DEV9\PacketReader\IP\ICMP + + + System\Ps2\DEV9\PacketReader\IP\TCP + + + System\Ps2\DEV9\PacketReader\IP\TCP + System\Ps2\DEV9\PacketReader\IP\UDP\DHCP