DEV9: Add code for reading packets

This commit is contained in:
TheLastRar 2021-03-06 20:27:51 +00:00 committed by lightningterror
parent 1221b5c271
commit 26b954fdc6
25 changed files with 2836 additions and 0 deletions

View File

@ -327,6 +327,15 @@ set(pcsx2DEV9Sources
DEV9/ATA/ATA_State.cpp
DEV9/ATA/ATA_Transfer.cpp
DEV9/ATA/HddCreate.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
DEV9/PacketReader/IP/UDP/DNS/DNS_Packet.cpp
DEV9/PacketReader/IP/UDP/UDP_Packet.cpp
DEV9/PacketReader/IP/IP_Options.cpp
DEV9/PacketReader/IP/IP_Packet.cpp
DEV9/PacketReader/EthernetFrame.cpp
DEV9/PacketReader/NetLib.cpp
DEV9/smap.cpp
DEV9/DEV9.cpp
DEV9/flash.cpp
@ -343,6 +352,19 @@ set(pcsx2DEV9Headers
DEV9/ATA/HddCreate.h
DEV9/DEV9.h
DEV9/net.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
DEV9/PacketReader/IP/UDP/DNS/DNS_Enums.h
DEV9/PacketReader/IP/UDP/DNS/DNS_Packet.h
DEV9/PacketReader/IP/UDP/UDP_Packet.h
DEV9/PacketReader/IP/IP_Address.h
DEV9/PacketReader/IP/IP_Options.h
DEV9/PacketReader/IP/IP_Packet.h
DEV9/PacketReader/IP/IP_Payload.h
DEV9/PacketReader/EthernetFrame.h
DEV9/PacketReader/NetLib.h
DEV9/PacketReader/Payload.h
DEV9/pcap_io.h
DEV9/SimpleQueue.h
DEV9/smap.h

View File

@ -0,0 +1,61 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "EthernetFrame.h"
#include "NetLib.h"
namespace PacketReader
{
EthernetFrame::EthernetFrame(Payload* data)
: payload{data}
{
}
EthernetFrame::EthernetFrame(NetPacket* pkt)
{
int offset = 0;
NetLib::ReadByteArray((u8*)pkt->buffer, &offset, 6, destinationMAC);
NetLib::ReadByteArray((u8*)pkt->buffer, &offset, 6, sourceMAC);
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
NetLib::ReadUInt16((u8*)pkt->buffer, &offset, &protocol);
//Note: We don't support tagged frames
payload = std::make_unique<PayloadPtr>((u8*)&pkt->buffer[offset], pkt->size - headerLength);
}
Payload* EthernetFrame::GetPayload()
{
return payload.get();
}
void EthernetFrame::WritePacket(NetPacket* pkt)
{
int counter = 0;
pkt->size = headerLength + payload->GetLength();
NetLib::WriteByteArray((u8*)pkt->buffer, &counter, 6, destinationMAC);
NetLib::WriteByteArray((u8*)pkt->buffer, &counter, 6, sourceMAC);
//
NetLib::WriteUInt16((u8*)pkt->buffer, &counter, protocol);
//
payload->WriteBytes((u8*)pkt->buffer, &counter);
}
} // namespace PacketReader

View File

@ -0,0 +1,55 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "../net.h"
#include "Payload.h"
namespace PacketReader
{
enum struct EtherType : u16
{
null = 0x0000,
IPv4 = 0x0800,
ARP = 0x0806,
//Tags extend the ether header length
VlanQTag = 0x8100,
VlanServiceQTag = 0x88A8,
VlanDoubleQTag = 0x9100
};
class EthernetFrame
{
public:
u8 destinationMAC[6] = {0};
u8 sourceMAC[6] = {0};
u16 protocol = 0;
int headerLength = 14;
//Length
private:
std::unique_ptr<Payload> payload;
public:
//Takes ownership of payload
EthernetFrame(Payload* data);
EthernetFrame(NetPacket* pkt);
Payload* GetPayload();
void WritePacket(NetPacket* pkt);
};
} // namespace PacketReader

View File

@ -0,0 +1,31 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace PacketReader::IP
{
struct IP_Address
{
union
{
u8 bytes[4];
u32 integer;
};
bool operator==(const IP_Address& other) const { return this->integer == other.integer; }
bool operator!=(const IP_Address& other) const { return this->integer != other.integer; }
};
} // namespace PacketReader::IP

View File

@ -0,0 +1,66 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "IP_Options.h"
#include "../NetLib.h"
namespace PacketReader::IP
{
bool IPOption::IsCopyOnFragment()
{
return ((GetCode() & (1 << 0x7)) != 0);
}
u8 IPOption::GetClass()
{
return (GetCode() >> 5) & 0x3;
}
u8 IPOption::GetNumber()
{
return GetCode() & 0x1F;
}
IPopUnk::IPopUnk(u8* data, int offset)
{
NetLib::ReadByte08(data, &offset, &code);
NetLib::ReadByte08(data, &offset, &length);
value.resize(length - 2);
NetLib::ReadByteArray(data, &offset, length - 2, &value[0]);
}
void IPopUnk::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, code);
NetLib::WriteByte08(buffer, offset, length);
NetLib::WriteByteArray(buffer, offset, length - 2, &value[0]);
}
IPopRouterAlert::IPopRouterAlert(u16 parValue)
: value{parValue}
{
}
IPopRouterAlert::IPopRouterAlert(u8* data, int offset)
{
offset += 2;
NetLib::ReadUInt16(data, &offset, &value);
}
void IPopRouterAlert::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength());
NetLib::WriteUInt16(buffer, offset, value);
}
} // namespace PacketReader::IP

View File

@ -0,0 +1,80 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace PacketReader::IP
{
class BaseOption
{
public:
virtual u8 GetLength() = 0;
virtual u8 GetCode() = 0;
virtual void WriteBytes(u8* buffer, int* offset) = 0;
virtual ~BaseOption() {}
};
class IPOption : public BaseOption
{
public:
bool IsCopyOnFragment();
u8 GetClass(); //0 = control, 2 = debugging and measurement
u8 GetNumber();
};
class IPopUnk : public IPOption
{
u8 length;
u8 code;
std::vector<u8> value;
public:
IPopUnk(u8* data, int offset);
virtual u8 GetLength() { return length; }
virtual u8 GetCode() { return code; }
void WriteBytes(u8* buffer, int* offset);
};
class IPopNOP : public IPOption
{
public:
virtual u8 GetLength() { return 1; }
virtual u8 GetCode() { return 1; }
virtual void WriteBytes(u8* buffer, int* offset)
{
buffer[*offset] = GetCode();
(*offset)++;
}
};
class IPopRouterAlert : public IPOption
{
//Should the router intercept packet?
public:
u16 value;
IPopRouterAlert(u16 parValue);
IPopRouterAlert(u8* data, int offset);
virtual u8 GetLength() { return 4; }
virtual u8 GetCode() { return 148; }
virtual void WriteBytes(u8* buffer, int* offset);
};
} // namespace PacketReader::IP

View File

@ -0,0 +1,308 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "IP_Packet.h"
#include "../NetLib.h"
namespace PacketReader::IP
{
u8 IP_Packet::GetDscpValue()
{
return (dscp >> 2) & 0x3F;
}
void IP_Packet::GetDscpValue(u8 value)
{
dscp = (dscp & ~(0x3F << 2)) | ((value & 0x3F) << 2);
}
u8 IP_Packet::GetDscpECN()
{
return dscp & 0x3;
}
void IP_Packet::SetDscpECN(u8 value)
{
dscp = (dscp & ~0x3) | (value & 0x3);
}
bool IP_Packet::GetDoNotFragment()
{
return (fragmentFlags1 & (1 << 6)) != 0;
}
void IP_Packet::SetDoNotFragment(bool value)
{
fragmentFlags1 = (fragmentFlags1 & ~(0x1 << 6)) | ((value & 0x1) << 6);
}
bool IP_Packet::GetMoreFragments()
{
return (fragmentFlags1 & (1 << 5)) != 0;
}
void IP_Packet::SetMoreFragments(bool value)
{
fragmentFlags1 = (fragmentFlags1 & ~(0x1 << 5)) | ((value & 0x1) << 5);
}
u16 IP_Packet::GetFragmentOffset()
{
int x = 0;
u8 fF1masked = fragmentFlags1 & 0x1F;
u8 data[2] = {fF1masked, fragmentFlags2};
u16 offset;
NetLib::ReadUInt16(data, &x, &offset);
return offset;
}
IP_Packet::IP_Packet(IP_Payload* data)
: protocol{data->GetProtocol()}
, payload{data}
{
}
IP_Packet::IP_Packet(u8* buffer, int bufferSize, bool fromICMP)
{
int offset = 0;
//Bits 0-31
u8 v_hl;
NetLib::ReadByte08(buffer, &offset, &v_hl);
headerLength = ((v_hl & 0xF) << 2);
NetLib::ReadByte08(buffer, &offset, &dscp);
u16 length;
NetLib::ReadUInt16(buffer, &offset, &length);
if (length > bufferSize)
{
if (!fromICMP)
Console.Error("DEV9: IP_Packet: Unexpected Length");
length = (u16)bufferSize;
}
//Bits 32-63
NetLib::ReadUInt16(buffer, &offset, &id); //Send packets with unique IDs
NetLib::ReadByte08(buffer, &offset, &fragmentFlags1);
NetLib::ReadByte08(buffer, &offset, &fragmentFlags2);
//Bits 64-95
NetLib::ReadByte08(buffer, &offset, &timeToLive);
NetLib::ReadByte08(buffer, &offset, &protocol);
NetLib::ReadUInt16(buffer, &offset, &checksum);
//Bits 96-127
NetLib::ReadByteArray(buffer, &offset, 4, (u8*)&sourceIP);
//Bits 128-159
NetLib::ReadByteArray(buffer, &offset, 4, (u8*)&destinationIP);
//Bits 160+
if (headerLength > 20) //IP options (if any)
{
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 IPopNOP());
offset += 1;
continue;
case 148:
options.push_back(new IPopRouterAlert(buffer, offset));
break;
default:
Console.Error("DEV9: IP_Packet: Got Unknown IP 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<IP_PayloadPtr>(&buffer[offset], length - offset, protocol);
}
IP_Payload* IP_Packet::GetPayload()
{
return payload.get();
}
int IP_Packet::GetLength()
{
ReComputeHeaderLen();
return headerLength + payload->GetLength();
}
void IP_Packet::WriteBytes(u8* buffer, int* offset)
{
int startOff = *offset;
CalculateChecksum(); //ReComputeHeaderLen called in CalculateChecksum
payload->CalculateChecksum(sourceIP, destinationIP);
NetLib::WriteByte08(buffer, offset, (_verHi + (headerLength >> 2)));
NetLib::WriteByte08(buffer, offset, dscp); //DSCP/ECN
NetLib::WriteUInt16(buffer, offset, GetLength());
NetLib::WriteUInt16(buffer, offset, id);
NetLib::WriteByte08(buffer, offset, fragmentFlags1);
NetLib::WriteByte08(buffer, offset, fragmentFlags2);
NetLib::WriteByte08(buffer, offset, timeToLive);
NetLib::WriteByte08(buffer, offset, protocol);
NetLib::WriteUInt16(buffer, offset, checksum); //header csum
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&sourceIP);
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&destinationIP);
//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);
}
void IP_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;
}
void IP_Packet::CalculateChecksum()
{
//if (!(i == 5)) //checksum field is 10-11th byte (5th short), which is skipped
ReComputeHeaderLen();
u8* headerSegment = new u8[headerLength];
int counter = 0;
NetLib::WriteByte08(headerSegment, &counter, (_verHi + (headerLength >> 2)));
NetLib::WriteByte08(headerSegment, &counter, dscp); //DSCP/ECN
NetLib::WriteUInt16(headerSegment, &counter, GetLength());
NetLib::WriteUInt16(headerSegment, &counter, id);
NetLib::WriteByte08(headerSegment, &counter, fragmentFlags1);
NetLib::WriteByte08(headerSegment, &counter, fragmentFlags2);
NetLib::WriteByte08(headerSegment, &counter, timeToLive);
NetLib::WriteByte08(headerSegment, &counter, protocol);
NetLib::WriteUInt16(headerSegment, &counter, 0); //header csum
NetLib::WriteByteArray(headerSegment, &counter, 4, (u8*)&sourceIP);
NetLib::WriteByteArray(headerSegment, &counter, 4, (u8*)&destinationIP);
//options
for (size_t i = 0; i < options.size(); i++)
options[i]->WriteBytes(headerSegment, &counter);
//Zero alignment bytes
if (counter != headerLength)
memset(&headerSegment[counter], 0, headerLength - counter);
counter = headerLength;
checksum = InternetChecksum(headerSegment, headerLength);
delete[] headerSegment;
}
bool IP_Packet::VerifyChecksum()
{
ReComputeHeaderLen();
u8* headerSegment = new u8[headerLength];
int counter = 0;
NetLib::WriteByte08(headerSegment, &counter, (_verHi + (headerLength >> 2)));
NetLib::WriteByte08(headerSegment, &counter, dscp); //DSCP/ECN
NetLib::WriteUInt16(headerSegment, &counter, GetLength());
NetLib::WriteUInt16(headerSegment, &counter, id);
NetLib::WriteByte08(headerSegment, &counter, fragmentFlags1);
NetLib::WriteByte08(headerSegment, &counter, fragmentFlags2);
NetLib::WriteByte08(headerSegment, &counter, timeToLive);
NetLib::WriteByte08(headerSegment, &counter, protocol);
NetLib::WriteUInt16(headerSegment, &counter, checksum); //header csum
NetLib::WriteByteArray(headerSegment, &counter, 4, (u8*)&sourceIP);
NetLib::WriteByteArray(headerSegment, &counter, 4, (u8*)&destinationIP);
//options
for (size_t i = 0; i < options.size(); i++)
options[i]->WriteBytes(headerSegment, &counter);
//Zero alignment bytes
if (counter != headerLength)
memset(&headerSegment[counter], 0, headerLength - counter);
counter = headerLength;
u16 csumCal = InternetChecksum(headerSegment, headerLength);
delete[] headerSegment;
return (csumCal == 0);
}
IP_Packet::~IP_Packet()
{
for (size_t i = 0; i < options.size(); i++)
delete options[i];
}
u16 IP_Packet::InternetChecksum(u8* buffer, int length)
{
//source http://stackoverflow.com/a/2201090
int i = 0;
u32 sum = 0;
while (length > 1)
{
sum += ((u32)(buffer[i]) << 8) | ((u32)(buffer[i + 1]) & 0xFF);
if ((sum & 0xFFFF0000) > 0)
{
sum &= 0xFFFF;
sum += 1;
}
i += 2;
length -= 2;
}
if (length > 0)
{
sum += (u32)(buffer[i] << 8);
if ((sum & 0xFFFF0000) > 0)
{
sum = sum & 0xFFFF;
sum += 1;
}
}
sum = ~sum;
sum = sum & 0xFFFF;
return (u16)sum;
}
} // namespace PacketReader::IP

View File

@ -0,0 +1,140 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vector>
#include "../Payload.h"
#include "IP_Address.h"
#include "IP_Options.h"
#include "IP_Payload.h"
namespace PacketReader::IP
{
enum struct IP_Type : u8
{
ICMP = 0x01,
IGMP = 0x02,
TCP = 0x06,
UDP = 0x11
};
class IP_Packet : public Payload
{
private:
const u8 _verHi = 4 << 4;
int headerLength = 20;
u8 dscp = 0;
//Flags
//u16 length;
u16 id = 0; //used during reassembly fragmented packets
private:
u8 fragmentFlags1 = 0;
u8 fragmentFlags2 = 0;
//Fragment Flags
public:
u8 timeToLive = 0;
u8 protocol;
private:
u16 checksum;
public:
IP_Address sourceIP{0};
IP_Address destinationIP{0};
std::vector<IPOption*> options;
private:
std::unique_ptr<IP_Payload> payload;
public:
//DSCP/TOS Flags
/* Upper 3 Bits
* DSCP Class is equal to TOS precedence
* DSCP vs TOS
* Default (xxx000), Low Effort (xxx010)
* 0 = Routine Class 0
* Assured Forwarding (xxx000, xxx010, xxx100, xxx110)
* 1 = Priority Class 1
* 2 = Immediate Class 2
* 3 = Flash Class 3
* 4 = Flash Override Class 4
* Expedited Forwarding (xxx110, xxx100)
* 5 = Critical Class 5
* Not Defined (xxx000)
* 6 = Internetwork Control Class 6
* 7 = Network Control Class 7
*
* Lower 3 Bits
* In TOS, defined as follows
* bit 0: Reliability
* bit 1: Throughput
* bit 2: Low Delay
* In DSCP, defined as following (bits 1-2)
* Class 0, Low Effort, 1
* Class 1-4, Assured Forwarding drop probability, Low = 1, Mid = 2, High = 3
* Class 5, Expedited Forwarding, 3
* bit0: Set to zero
*/
u8 GetDscpValue();
void GetDscpValue(u8 value);
/* 2 bits
* In TOS, defined as follows
* Bit 0: Unused
* Bit 1: Low Cost
* In DSCP, defined as follows
* 0 = ECN not supported
* 1,2 ECN Supported
* 3 = Congestion Encountered
*/
u8 GetDscpECN();
void SetDscpECN(u8 value);
//Fragment Flags
//bit 0, reserverd
bool GetDoNotFragment();
void SetDoNotFragment(bool value);
bool GetMoreFragments();
void SetMoreFragments(bool value);
//Untested
u16 GetFragmentOffset();
//Takes ownership of payload
IP_Packet(IP_Payload* data);
IP_Packet(u8* buffer, int bufferSize, bool fromICMP = false);
IP_Payload* GetPayload();
virtual int GetLength();
virtual void WriteBytes(u8* buffer, int* offset);
bool VerifyChecksum();
static u16 InternetChecksum(u8* buffer, int length);
~IP_Packet();
private:
void ReComputeHeaderLen();
void CalculateChecksum();
};
} // namespace PacketReader::IP

View File

@ -0,0 +1,67 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace PacketReader::IP
{
class IP_Payload
{
public: //Nedd GetProtocol
virtual int GetLength() = 0;
virtual void WriteBytes(u8* buffer, int* offset) = 0;
virtual u8 GetProtocol() = 0;
virtual bool VerifyChecksum(IP_Address srcIP, IP_Address dstIP) { return false; }
virtual void CalculateChecksum(IP_Address srcIP, IP_Address dstIP) {}
virtual ~IP_Payload() {}
};
//Pointer to bytes not owned by class
class IP_PayloadPtr : public IP_Payload
{
public:
u8* data;
private:
int length;
u8 protocol;
public:
IP_PayloadPtr(u8* ptr, int len, u8 prot)
{
data = ptr;
length = len;
protocol = prot;
}
virtual int GetLength()
{
return length;
}
virtual void WriteBytes(u8* buffer, int* offset)
{
//If buffer & data point to the same location
//Then no copy is needed
if (data == buffer)
return;
memcpy(buffer, data, length);
*offset += length;
}
virtual u8 GetProtocol()
{
return protocol;
}
};
} // namespace PacketReader::IP

View File

@ -0,0 +1,437 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "DHCP_Options.h"
#include "../../../NetLib.h"
namespace PacketReader::IP::UDP::DHCP
{
DHCPopSubnet::DHCPopSubnet(IP_Address mask)
: subnetMask{mask}
{
}
DHCPopSubnet::DHCPopSubnet(u8* data, int offset)
{
offset += 2;
NetLib::ReadByteArray(data, &offset, 4, (u8*)&subnetMask);
}
void DHCPopSubnet::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&subnetMask);
}
DHCPopRouter::DHCPopRouter(const std::vector<IP_Address>& routerIPs)
: routers{routerIPs}
{
}
DHCPopRouter::DHCPopRouter(u8* data, int offset)
{
offset += 1;
u8 len;
NetLib::ReadByte08(data, &offset, &len);
routers = {(IP_Address*)&data[offset], (IP_Address*)&data[offset + len]};
//offset += len;
}
void DHCPopRouter::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, routers.size() * 4, (u8*)&routers[0]);
}
DHCPopDNS::DHCPopDNS(const std::vector<IP_Address>& dnsIPs)
: dnsServers{dnsIPs}
{
}
DHCPopDNS::DHCPopDNS(u8* data, int offset)
{
offset += 1;
u8 len;
NetLib::ReadByte08(data, &offset, &len);
dnsServers = {(IP_Address*)&data[offset], (IP_Address*)&data[offset + len]};
//offset += len;
}
void DHCPopDNS::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, dnsServers.size() * 4, (u8*)&dnsServers[0]);
}
DHCPopHostName::DHCPopHostName(std::string name)
{
if (name.size() > 255)
{
Console.Error("DEV9: DHCPopHostName: Name too long");
hostName = name.substr(0, 255);
}
else
hostName = name;
}
DHCPopHostName::DHCPopHostName(u8* data, int offset)
{
offset += 1;
u8 len;
NetLib::ReadByte08(data, &offset, &len);
hostName = std::string((char*)&data[offset], len);
//offset += len;
}
void DHCPopHostName::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, hostName.size(), (u8*)hostName.c_str());
}
DHCPopDnsName::DHCPopDnsName(std::string name)
{
if (name.size() > 255)
{
Console.Error("DEV9: DHCPopDnsName: Name too long");
domainName = name.substr(0, 255);
}
else
domainName = name;
}
DHCPopDnsName::DHCPopDnsName(u8* data, int offset)
{
offset += 1;
u8 len;
NetLib::ReadByte08(data, &offset, &len);
domainName = std::string((char*)&data[offset], len);
//offset += len;
}
void DHCPopDnsName::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, domainName.size(), (u8*)domainName.c_str());
}
DHCPopBCIP::DHCPopBCIP(IP_Address data)
: broadcastIP{data}
{
}
DHCPopBCIP::DHCPopBCIP(u8* data, int offset)
{
offset += 2;
NetLib::ReadByteArray(data, &offset, 4, (u8*)&broadcastIP);
}
void DHCPopBCIP::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&broadcastIP);
}
bool DHCPopNBIOSType::GetHNode()
{
return ((type & (1 << 3)) != 0);
}
void DHCPopNBIOSType::SetHNode(bool value)
{
if (value)
{
type |= (1 << 3);
}
else
{
type &= ~(1 << 3);
}
}
bool DHCPopNBIOSType::GetMNode()
{
return ((type & (1 << 2)) != 0);
}
void DHCPopNBIOSType::SetMNode(bool value)
{
if (value)
{
type |= (1 << 2);
}
else
{
type &= ~(1 << 2);
}
}
bool DHCPopNBIOSType::GetPNode()
{
return ((type & (1 << 1)) != 0);
}
void DHCPopNBIOSType::SetPNode(bool value)
{
if (value)
{
type |= (1 << 1);
}
else
{
type &= ~(1 << 1);
}
}
bool DHCPopNBIOSType::GetBNode()
{
return ((type & 1) != 0);
}
void DHCPopNBIOSType::SetBNode(bool value)
{
if (value)
{
type |= 1;
}
else
{
type &= ~1;
}
}
//
DHCPopNBIOSType::DHCPopNBIOSType(u8* data, int offset)
{
offset += 2;
NetLib::ReadByte08(data, &offset, &type);
}
void DHCPopNBIOSType::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByte08(buffer, offset, type);
}
DHCPopREQIP::DHCPopREQIP(IP_Address data)
: requestedIP{data}
{
}
DHCPopREQIP::DHCPopREQIP(u8* data, int offset)
{
offset += 2;
NetLib::ReadByteArray(data, &offset, 4, (u8*)&requestedIP);
}
void DHCPopREQIP::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&requestedIP);
}
DHCPopIPLT::DHCPopIPLT(u32 LeaseTime)
: ipLeaseTime{LeaseTime}
{
}
DHCPopIPLT::DHCPopIPLT(u8* data, int offset)
{
offset += 2;
NetLib::ReadUInt32(data, &offset, &ipLeaseTime);
}
void DHCPopIPLT::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteUInt32(buffer, offset, ipLeaseTime);
}
DHCPopMSG::DHCPopMSG(u8 msg)
: message{msg}
{
}
DHCPopMSG::DHCPopMSG(u8* data, int offset)
{
offset += 2;
NetLib::ReadByte08(data, &offset, &message);
}
void DHCPopMSG::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByte08(buffer, offset, message);
}
DHCPopSERVIP::DHCPopSERVIP(IP_Address data)
: serverIP{data}
{
}
DHCPopSERVIP::DHCPopSERVIP(u8* data, int offset)
{
offset += 2;
NetLib::ReadByteArray(data, &offset, 4, (u8*)&serverIP);
}
void DHCPopSERVIP::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&serverIP);
}
DHCPopREQLIST::DHCPopREQLIST(const std::vector<u8>& requestList)
: requests{requestList}
{
}
DHCPopREQLIST::DHCPopREQLIST(u8* data, int offset)
{
offset += 1;
u8 len;
NetLib::ReadByte08(data, &offset, &len);
requests = {&data[offset], &data[offset + len]};
//offset += len;
}
void DHCPopREQLIST::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, requests.size(), &requests[0]);
}
DHCPopMSGStr::DHCPopMSGStr(std::string msg)
{
if (msg.size() > 255)
{
Console.Error("DEV9: DHCPopMSGStr: String too long");
message = msg.substr(0, 255);
}
else
message = msg;
}
DHCPopMSGStr::DHCPopMSGStr(u8* data, int offset)
{
offset += 1;
u8 len;
NetLib::ReadByte08(data, &offset, &len);
message = std::string((char*)&data[offset], len);
//offset += len;
}
void DHCPopMSGStr::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, message.size(), (u8*)message.c_str());
}
DHCPopMMSGS::DHCPopMMSGS(u16 mms)
: maxMessageSize{mms}
{
}
DHCPopMMSGS::DHCPopMMSGS(u8* data, int offset)
{
offset += 2;
NetLib::ReadUInt16(data, &offset, &maxMessageSize);
}
void DHCPopMMSGS::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteUInt16(buffer, offset, maxMessageSize);
}
DHCPopT1::DHCPopT1(u32 t1)
: ipRenewalTimeT1{t1}
{
}
DHCPopT1::DHCPopT1(u8* data, int offset)
{
offset += 2;
NetLib::ReadUInt32(data, &offset, &ipRenewalTimeT1);
}
void DHCPopT1::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteUInt32(buffer, offset, ipRenewalTimeT1);
}
DHCPopT2::DHCPopT2(u32 t2)
: ipRebindingTimeT2{t2}
{
}
DHCPopT2::DHCPopT2(u8* data, int offset)
{
offset += 2;
NetLib::ReadUInt32(data, &offset, &ipRebindingTimeT2);
}
void DHCPopT2::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteUInt32(buffer, offset, ipRebindingTimeT2);
}
DHCPopClassID::DHCPopClassID(std::string id)
{
if (id.size() > 255)
{
Console.Error("DEV9: DHCPopClassID: Class ID too long");
classID = id.substr(0, 255);
}
else
classID = id;
}
DHCPopClassID::DHCPopClassID(u8* data, int offset)
{
offset += 1;
u8 len;
NetLib::ReadByte08(data, &offset, &len);
classID = std::string((char*)&data[offset], len);
//offset += len;
}
void DHCPopClassID::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, classID.size(), (u8*)classID.c_str());
}
DHCPopClientID::DHCPopClientID(const std::vector<u8>& value)
: clientID{value}
{
}
DHCPopClientID::DHCPopClientID(u8* data, int offset)
{
offset += 1;
u8 len;
NetLib::ReadByte08(data, &offset, &len);
clientID = {&data[offset], &data[offset + len]};
//offset += len;
}
void DHCPopClientID::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteByte08(buffer, offset, GetCode());
NetLib::WriteByte08(buffer, offset, GetLength() - 2);
NetLib::WriteByteArray(buffer, offset, clientID.size(), &clientID[0]);
}
} // namespace PacketReader::IP::UDP::DHCP

View File

@ -0,0 +1,320 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <vector>
#include "../../IP_Packet.h"
#include "../../IP_Options.h"
namespace PacketReader::IP::UDP::DHCP
{
//Unlike IPOptions, DCHP length field does not count the option header
//GetLength(), howver, includes the option header
class DHCPopNOP : public BaseOption
{
virtual u8 GetLength() { return 1; }
virtual u8 GetCode() { return 0; }
virtual void WriteBytes(u8* buffer, int* offset)
{
buffer[*offset] = GetCode();
(*offset)++;
}
};
class DHCPopSubnet : public BaseOption
{
public:
IP_Address subnetMask{0};
DHCPopSubnet(IP_Address mask);
DHCPopSubnet(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 6; }
virtual u8 GetCode() { return 1; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopRouter : public BaseOption //can be longer then 1 address
{
public:
std::vector<IP_Address> routers;
DHCPopRouter(const std::vector<IP_Address>& routerIPs);
DHCPopRouter(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 2 + 4 * routers.size(); }
virtual u8 GetCode() { return 3; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopDNS : public BaseOption //can be longer then 1 address
{
public:
std::vector<IP_Address> dnsServers;
DHCPopDNS(const std::vector<IP_Address>& dnsIPs);
DHCPopDNS(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 2 + 4 * dnsServers.size(); }
virtual u8 GetCode() { return 6; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopHostName : public BaseOption
{
public:
//ASCII encoding
std::string hostName;
DHCPopHostName(std::string name);
DHCPopHostName(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 2 + hostName.size(); }
virtual u8 GetCode() { return 12; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopDnsName : public BaseOption
{
public:
//ASCII encoding
std::string domainName;
DHCPopDnsName(std::string name);
DHCPopDnsName(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 2 + domainName.size(); }
virtual u8 GetCode() { return 15; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopBCIP : public BaseOption //The IP to send broadcasts to
{
public:
IP_Address broadcastIP{0};
DHCPopBCIP(IP_Address data);
DHCPopBCIP(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 6; }
virtual u8 GetCode() { return 28; }
virtual void WriteBytes(u8* buffer, int* offset);
};
//What even sent this?
class DHCPopNBIOSType : public BaseOption
{
private:
u8 type = 0;
public:
//Getters/Setters
bool GetHNode();
void SetHNode(bool value);
bool GetMNode();
void SetMNode(bool value);
bool GetPNode();
void SetPNode(bool value);
bool GetBNode();
void SetBNode(bool value);
DHCPopNBIOSType(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 3; }
virtual u8 GetCode() { return 46; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopREQIP : public BaseOption //The IP to send broadcasts to
{
public:
IP_Address requestedIP{0};
DHCPopREQIP(IP_Address data);
DHCPopREQIP(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 6; }
virtual u8 GetCode() { return 50; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopIPLT : public BaseOption
{
public:
u32 ipLeaseTime;
DHCPopIPLT(u32 LeaseTime);
DHCPopIPLT(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 6; }
virtual u8 GetCode() { return 51; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopMSG : public BaseOption
{
public:
u8 message;
DHCPopMSG(u8 msg);
DHCPopMSG(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 3; }
virtual u8 GetCode() { return 53; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopSERVIP : public BaseOption //DHCP server ip
{
public:
IP_Address serverIP{0};
DHCPopSERVIP(IP_Address data);
DHCPopSERVIP(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 6; }
virtual u8 GetCode() { return 54; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopREQLIST : public BaseOption
{
public:
std::vector<u8> requests;
DHCPopREQLIST(const std::vector<u8>& requestList);
DHCPopREQLIST(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 2 + requests.size(); }
virtual u8 GetCode() { return 55; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopMSGStr : public BaseOption
{
public:
//ASCII encoding
std::string message;
DHCPopMSGStr(std::string msg);
DHCPopMSGStr(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 2 + message.size(); }
virtual u8 GetCode() { return 56; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopMMSGS : public BaseOption
{
public:
u16 maxMessageSize;
DHCPopMMSGS(u16 mms);
DHCPopMMSGS(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 4; }
virtual u8 GetCode() { return 57; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopT1 : public BaseOption
{
public:
u32 ipRenewalTimeT1;
DHCPopT1(u32 t1);
DHCPopT1(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 6; }
virtual u8 GetCode() { return 58; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopT2 : public BaseOption
{
public:
u32 ipRebindingTimeT2;
DHCPopT2(u32 t2);
DHCPopT2(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 6; }
virtual u8 GetCode() { return 59; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopClassID : public BaseOption
{
public:
//ASCII encoding
std::string classID;
DHCPopClassID(std::string id);
DHCPopClassID(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 2 + classID.size(); }
virtual u8 GetCode() { return 60; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopClientID final : public BaseOption
{
public:
std::vector<u8> clientID;
DHCPopClientID(const std::vector<u8>& value);
DHCPopClientID(u8* data, int offset); //Offset will include Kind and Len
virtual u8 GetLength() { return 2 + clientID.size(); }
virtual u8 GetCode() { return 61; }
virtual void WriteBytes(u8* buffer, int* offset);
};
class DHCPopEND : public BaseOption
{
public:
DHCPopEND() {}
virtual u8 GetLength() { return 1; }
virtual u8 GetCode() { return 255; }
virtual void WriteBytes(u8* buffer, int* offset)
{
buffer[*offset] = GetCode();
(*offset)++;
}
};
} // namespace PacketReader::IP::UDP::DHCP

View File

@ -0,0 +1,223 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "DHCP_Packet.h"
#include "../../../NetLib.h"
namespace PacketReader::IP::UDP::DHCP
{
DHCP_Packet::DHCP_Packet(u8* buffer, int bufferSize)
{
int offset = 0;
//Bits 0-31 //Bytes 0-3
NetLib::ReadByte08(buffer, &offset, &op);
NetLib::ReadByte08(buffer, &offset, &hardwareType);
NetLib::ReadByte08(buffer, &offset, &hardwareAddressLength);
NetLib::ReadByte08(buffer, &offset, &hops);
//Bits 32-63 //Bytes 4-7
NetLib::ReadUInt32(buffer, &offset, &transactionID);
//Bits 64-95 //Bytes 8-11
NetLib::ReadUInt16(buffer, &offset, &seconds);
NetLib::ReadUInt16(buffer, &offset, &flags);
//Bits 96-127 //Bytes 12-15
NetLib::ReadByteArray(buffer, &offset, 4, (u8*)&clientIP);
//Bits 128-159 //Bytes 16-19
NetLib::ReadByteArray(buffer, &offset, 4, (u8*)&yourIP);
//Bits 160-191 //Bytes 20-23
NetLib::ReadByteArray(buffer, &offset, 4, (u8*)&serverIP);
//Bits 192-223 //Bytes 24-27
NetLib::ReadByteArray(buffer, &offset, 4, (u8*)&gatewayIP);
//Bits 192+ //Bytes 28-43
NetLib::ReadByteArray(buffer, &offset, 16, clientHardwareAddress);
//Bytes 44-235
//Assume BOOTP unused
offset += 192;
//Bytes 236-239
NetLib::ReadUInt32(buffer, &offset, &magicCookie);
bool opReadFin = false;
do
{
u8 opKind = buffer[offset];
if (opKind == 255)
{
options.push_back(new DHCPopEND());
opReadFin = true;
offset += 1;
continue;
}
if ((offset + 1) >= bufferSize)
{
Console.Error("DEV9: DHCP_Packet: Unexpected end of packet");
options.push_back(new DHCPopEND());
opReadFin = true;
continue;
}
u8 opLen = buffer[offset + 1];
switch (opKind)
{
case 0:
options.push_back(new DHCPopNOP());
offset += 1;
continue;
case 1:
options.push_back(new DHCPopSubnet(buffer, offset));
break;
case 3:
options.push_back(new DHCPopRouter(buffer, offset));
break;
case 6:
options.push_back(new DHCPopDNS(buffer, offset));
break;
case 12:
options.push_back(new DHCPopHostName(buffer, offset));
break;
case 15:
options.push_back(new DHCPopDnsName(buffer, offset));
break;
case 28:
options.push_back(new DHCPopBCIP(buffer, offset));
break;
case 46:
//Do we actually care about this?
options.push_back(new DHCPopNBIOSType(buffer, offset));
break;
case 50:
options.push_back(new DHCPopREQIP(buffer, offset));
break;
case 51:
options.push_back(new DHCPopIPLT(buffer, offset));
break;
case 53:
options.push_back(new DHCPopMSG(buffer, offset));
break;
case 54:
options.push_back(new DHCPopSERVIP(buffer, offset));
break;
case 55:
options.push_back(new DHCPopREQLIST(buffer, offset));
break;
case 56:
options.push_back(new DHCPopMSGStr(buffer, offset));
break;
case 57:
options.push_back(new DHCPopMMSGS(buffer, offset));
break;
case 58:
options.push_back(new DHCPopT1(buffer, offset));
break;
case 59:
options.push_back(new DHCPopT2(buffer, offset));
break;
case 60:
options.push_back(new DHCPopClassID(buffer, offset));
break;
case 61:
//Do we actully care about this?
options.push_back(new DHCPopClientID(buffer, offset));
break;
default:
Console.Error("DEV9: DHCP_Packet: Got Unknown Option %d with len %d", opKind, opLen);
break;
}
offset += opLen + 2;
if (offset >= bufferSize)
{
Console.Error("DEV9: DHCP_Packet: Unexpected end of packet");
options.push_back(new DHCPopNOP());
opReadFin = true;
}
} while (opReadFin == false);
}
int DHCP_Packet::GetLength()
{
return maxLenth - (8 + 20);
}
void DHCP_Packet::WriteBytes(u8* buffer, int* offset)
{
int start = *offset;
NetLib::WriteByte08(buffer, offset, op);
NetLib::WriteByte08(buffer, offset, hardwareType);
NetLib::WriteByte08(buffer, offset, hardwareAddressLength);
NetLib::WriteByte08(buffer, offset, hops);
NetLib::WriteUInt32(buffer, offset, transactionID);
NetLib::WriteUInt16(buffer, offset, seconds);
NetLib::WriteUInt16(buffer, offset, flags);
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&clientIP);
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&yourIP);
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&serverIP);
NetLib::WriteByteArray(buffer, offset, 4, (u8*)&gatewayIP);
NetLib::WriteByteArray(buffer, offset, 16, clientHardwareAddress);
//empty bytes
memset(buffer + *offset, 0, 64 + 128);
*offset += 64 + 128;
NetLib::WriteUInt32(buffer, offset, magicCookie);
int len = 240;
for (size_t i = 0; i < options.size(); i++)
{
if (len + options[i]->GetLength() < maxLenth)
{
len += options[i]->GetLength();
options[i]->WriteBytes(buffer, offset);
}
else
{
Console.Error("DEV9: DHCP_Packet: Oversized DHCP packet not handled");
//We need space for DHCP End
if (len == maxLenth)
{
i -= 1;
int pastLength = options[i]->GetLength();
len -= pastLength;
*offset -= pastLength;
}
DHCPopEND end;
end.WriteBytes(buffer, offset);
break;
}
}
int end = start + GetLength();
int delta = end - *offset;
memset(&buffer[*offset], 0, delta);
*offset = start + GetLength();
}
DHCP_Packet::~DHCP_Packet()
{
for (size_t i = 0; i < options.size(); i++)
delete options[i];
}
} // namespace PacketReader::IP::UDP::DHCP

View File

@ -0,0 +1,55 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vector>
#include "DHCP_Options.h"
#include "../../IP_Packet.h"
namespace PacketReader::IP::UDP::DHCP
{
class DHCP_Packet : public Payload
{
public:
u8 op;
u8 hardwareType;
u8 hardwareAddressLength;
u8 hops;
u32 transactionID; //xid
u16 seconds;
u16 flags;
IP_Address clientIP{0};
IP_Address yourIP{0};
IP_Address serverIP{0};
IP_Address gatewayIP{0};
u8 clientHardwareAddress[16]{0}; //always 16 bytes, regardless of HardwareAddressLength
//192 bytes of padding
u32 magicCookie;
//Assumes ownership of ptrs assigned to it
std::vector<BaseOption*> options;
//used by GetLength & WriteBytes
int maxLenth = 576;
DHCP_Packet() {}
DHCP_Packet(u8* buffer, int bufferSize);
virtual int GetLength();
virtual void WriteBytes(u8* buffer, int* offset);
virtual ~DHCP_Packet();
};
} // namespace PacketReader::IP::UDP::DHCP

View File

@ -0,0 +1,145 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "DNS_Classes.h"
#include "../../../NetLib.h"
namespace PacketReader::IP::UDP::DNS
{
DNS_QuestionEntry::DNS_QuestionEntry(const std::string& qName, u16 qType, u16 qClass)
: name{qName}
, entryType{qType}
, entryClass{qClass}
{
}
DNS_QuestionEntry::DNS_QuestionEntry(u8* buffer, int* offset)
{
ReadDNS_String(buffer, offset, &name);
NetLib::ReadUInt16(buffer, offset, &entryType);
NetLib::ReadUInt16(buffer, offset, &entryClass);
}
void DNS_QuestionEntry::ReadDNS_String(u8* buffer, int* offset, std::string* value)
{
*value = "";
while (buffer[*offset] != 0)
{
int len = buffer[*offset];
if (len >= 192)
{
//len instead contains a pointer to the rest of the string
u8 addrB[2];
NetLib::ReadByteArray(buffer, offset, 2, addrB);
addrB[0] &= ~0xC0;
u16 addr;
int tmp = 0;
NetLib::ReadUInt16(addrB, &tmp, &addr);
tmp = addr;
std::string o;
ReadDNS_String(buffer, &tmp, &o);
*value += o;
//Ends with the pointer, no null char
return;
}
else
{
*offset += 1;
*value += std::string((char*)&buffer[*offset], len);
*offset += len;
if (buffer[*offset] != 0)
*value += ".";
}
}
//null char
*offset += 1;
}
void DNS_QuestionEntry::WriteDNS_String(u8* buffer, int* offset, std::string value)
{
int segmentLength = 0;
int segmentStart = 0;
for (size_t i = 0; i < value.size(); i++)
{
if (value[i] == '.')
{
if (segmentLength == 0)
continue;
NetLib::WriteByte08(buffer, offset, segmentLength);
NetLib::WriteByteArray(buffer, offset, segmentLength, (u8*)&value.c_str()[segmentStart]);
segmentLength = 0;
segmentStart = i + 1;
}
else
segmentLength++;
continue;
}
if (segmentLength != 0)
{
NetLib::WriteByte08(buffer, offset, segmentLength);
NetLib::WriteByteArray(buffer, offset, segmentLength, (u8*)&value.c_str()[segmentStart]);
}
//null char
NetLib::WriteByte08(buffer, offset, 0);
}
int DNS_QuestionEntry::GetLength()
{
return 1 + name.size() + 1 + 4;
}
void DNS_QuestionEntry::WriteBytes(u8* buffer, int* offset)
{
WriteDNS_String(buffer, offset, name);
NetLib::WriteUInt16(buffer, offset, entryType);
NetLib::WriteUInt16(buffer, offset, entryClass);
}
DNS_ResponseEntry::DNS_ResponseEntry(const std::string& rName, u16 rType, u16 rClass, const std::vector<u8>& rData, u32 rTTL)
: DNS_QuestionEntry(rName, rType, rClass)
, timeToLive{rTTL}
, data{rData}
{
}
DNS_ResponseEntry::DNS_ResponseEntry(u8* buffer, int* offset)
: DNS_QuestionEntry(buffer, offset)
{
u16 dataLen;
NetLib::ReadUInt32(buffer, offset, &timeToLive);
NetLib::ReadUInt16(buffer, offset, &dataLen);
data = {&buffer[*offset], &buffer[*offset + dataLen]};
*offset += dataLen;
}
int DNS_ResponseEntry::GetLength()
{
return DNS_QuestionEntry::GetLength() + 4 + 2 + data.size();
}
void DNS_ResponseEntry::WriteBytes(u8* buffer, int* offset)
{
DNS_QuestionEntry::WriteBytes(buffer, offset);
NetLib::WriteUInt32(buffer, offset, timeToLive);
NetLib::WriteUInt16(buffer, offset, data.size());
NetLib::WriteByteArray(buffer, offset, data.size(), &data[0]);
}
} // namespace PacketReader::IP::UDP::DNS

View File

@ -0,0 +1,60 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <vector>
namespace PacketReader::IP::UDP::DNS
{
class DNS_QuestionEntry
{
public:
std::string name;
u16 entryType;
u16 entryClass;
DNS_QuestionEntry(const std::string& qName, u16 qType, u16 qClass);
DNS_QuestionEntry(u8* buffer, int* offset);
virtual int GetLength();
virtual void WriteBytes(u8* buffer, int* offset);
virtual ~DNS_QuestionEntry(){};
private:
void ReadDNS_String(u8* buffer, int* offset, std::string* value);
void WriteDNS_String(u8* buffer, int* offset, std::string value);
};
class DNS_ResponseEntry : public DNS_QuestionEntry
{
public:
u32 timeToLive;
std::vector<u8> data;
DNS_ResponseEntry(const std::string& rName, u16 rType, u16 rClass, const std::vector<u8>& rData, u32 rTTL);
DNS_ResponseEntry(u8* buffer, int* offset);
virtual int GetLength();
virtual void WriteBytes(u8* buffer, int* offset);
virtual ~DNS_ResponseEntry(){};
private:
void ReadDNSString(u8* buffer, int* offset, std::string* value);
void WriteDNSString(u8* buffer, int* offset, std::string value);
};
} // namespace PacketReader::IP::UDP::DNS

View File

@ -0,0 +1,43 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace PacketReader::IP::UDP
{
enum struct DNS_OPCode : u8
{
Query = 0,
IQuery = 1,
Status = 2,
Reserved = 3,
Notify = 4,
Update = 5
};
enum struct DNS_RCode : u8
{
NoError = 0,
FormatError = 1,
ServerFailure = 2,
NameError = 3,
NotImplemented = 4,
Refused = 5,
YXDomain = 6,
YXRRSet = 7,
NXRRSet = 8,
NotAuth = 9,
NotZone = 10,
};
} // namespace PacketReader::IP::UDP

View File

@ -0,0 +1,194 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "DNS_Packet.h"
#include "../../../NetLib.h"
namespace PacketReader::IP::UDP::DNS
{
bool DNS_Packet::GetQR()
{
return (flags1 & (1 << 7)) != 0;
}
void DNS_Packet::SetQR(bool value)
{
flags1 = (flags1 & ~(0x1 << 7)) | ((value & 0x1) << 7);
}
u8 DNS_Packet::GetOpCode()
{
return (flags1 >> 3) & 0xF;
}
void DNS_Packet::SetOpCode(u8 value)
{
flags1 = (flags1 & ~(0xF << 3)) | ((value & 0xF) << 3);
}
bool DNS_Packet::GetAA()
{
return (flags1 & (1 << 2)) != 0;
}
void DNS_Packet::SetAA(bool value)
{
flags1 = (flags1 & ~(0x1 << 2)) | ((value & 0x1) << 2);
}
bool DNS_Packet::GetTC()
{
return (flags1 & (1 << 1)) != 0;
}
void DNS_Packet::SetTC(bool value)
{
flags1 = (flags1 & ~(0x1 << 1)) | ((value & 0x1) << 1);
}
bool DNS_Packet::GetRD()
{
return (flags1 & 1) != 0;
}
void DNS_Packet::SetRD(bool value)
{
flags1 = (flags1 & ~0x1) | (value & 0x1);
}
bool DNS_Packet::GetRA()
{
return (flags2 & (1 << 7)) != 0;
}
void DNS_Packet::SetRA(bool value)
{
flags2 = (flags2 & ~(0x1 << 7)) | ((value & 0x1) << 7);
}
u8 DNS_Packet::GetZ0()
{
return (flags2 & (1 << 6)) != 0;
}
void DNS_Packet::SetZ0(u8 value)
{
flags1 = (flags2 & ~(0x1 << 6)) | ((value & 0x1) << 6);
}
bool DNS_Packet::GetAD()
{
return (flags2 & (1 << 5)) != 0;
}
void DNS_Packet::SetAD(bool value)
{
flags2 = (flags2 & ~(0x1 << 5)) | ((value & 0x1) << 5);
}
bool DNS_Packet::GetCD()
{
return (flags2 & (1 << 4)) != 0;
}
void DNS_Packet::SetCD(bool value)
{
flags2 = (flags2 & ~(0x1 << 4)) | ((value & 0x1) << 4);
}
u8 DNS_Packet::GetRCode()
{
return flags2 & 0xF;
}
void DNS_Packet::SetRCode(u8 value)
{
flags2 = (flags2 & ~(0xF << 3)) | ((value & 0xF) << 3);
}
DNS_Packet::DNS_Packet(u8* buffer, int bufferSize)
{
int offset = 0;
//Bits 0-31 //Bytes 0-3
NetLib::ReadUInt16(buffer, &offset, &id);
NetLib::ReadByte08(buffer, &offset, &flags1);
NetLib::ReadByte08(buffer, &offset, &flags2);
//Bits 32-63 //Bytes 4-7
u16 qCount;
u16 aCount;
u16 auCount;
u16 adCount;
NetLib::ReadUInt16(buffer, &offset, &qCount);
NetLib::ReadUInt16(buffer, &offset, &aCount);
//Bits 64-95 //Bytes 8-11
NetLib::ReadUInt16(buffer, &offset, &auCount);
NetLib::ReadUInt16(buffer, &offset, &adCount);
//Bits 96+ //Bytes 8+
for (int i = 0; i < qCount; i++)
{
DNS_QuestionEntry entry(buffer, &offset);
questions.push_back(entry);
}
for (int i = 0; i < aCount; i++)
{
DNS_ResponseEntry entry(buffer, &offset);
answers.push_back(entry);
}
for (int i = 0; i < auCount; i++)
{
DNS_ResponseEntry entry(buffer, &offset);
authorities.push_back(entry);
}
for (int i = 0; i < adCount; i++)
{
DNS_ResponseEntry entry(buffer, &offset);
additional.push_back(entry);
}
}
int DNS_Packet::GetLength()
{
int length = 2 * 2 + 4 * 2;
for (size_t i = 0; i < questions.size(); i++)
length += questions[i].GetLength();
for (size_t i = 0; i < answers.size(); i++)
length += answers[i].GetLength();
for (size_t i = 0; i < authorities.size(); i++)
length += authorities[i].GetLength();
for (size_t i = 0; i < additional.size(); i++)
length += additional[i].GetLength();
return length;
}
void DNS_Packet::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteUInt16(buffer, offset, id);
NetLib::WriteByte08(buffer, offset, flags1);
NetLib::WriteByte08(buffer, offset, flags2);
NetLib::WriteUInt16(buffer, offset, questions.size());
NetLib::WriteUInt16(buffer, offset, answers.size());
NetLib::WriteUInt16(buffer, offset, authorities.size());
NetLib::WriteUInt16(buffer, offset, additional.size());
for (size_t i = 0; i < questions.size(); i++)
questions[i].WriteBytes(buffer, offset);
for (size_t i = 0; i < answers.size(); i++)
answers[i].WriteBytes(buffer, offset);
for (size_t i = 0; i < authorities.size(); i++)
authorities[i].WriteBytes(buffer, offset);
for (size_t i = 0; i < additional.size(); i++)
additional[i].WriteBytes(buffer, offset);
}
} // namespace PacketReader::IP::UDP::DNS

View File

@ -0,0 +1,81 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vector>
#include "DNS_Classes.h"
#include "DNS_Enums.h"
#include "../../../Payload.h"
namespace PacketReader::IP::UDP::DNS
{
class DNS_Packet : public Payload
{
public:
u16 id = 0;
private:
u8 flags1 = 0;
u8 flags2 = 0;
//QuestionCount
//AnswerCount
//Authorities
//Additional
public:
std::vector<DNS_QuestionEntry> questions;
std::vector<DNS_ResponseEntry> answers;
std::vector<DNS_ResponseEntry> authorities;
std::vector<DNS_ResponseEntry> additional;
bool GetQR();
void SetQR(bool value);
u8 GetOpCode();
void SetOpCode(u8 value);
bool GetAA();
void SetAA(bool value);
bool GetTC();
void SetTC(bool value);
bool GetRD();
void SetRD(bool value);
bool GetRA();
void SetRA(bool value);
u8 GetZ0();
void SetZ0(u8 value);
bool GetAD();
void SetAD(bool value);
bool GetCD();
void SetCD(bool value);
u8 GetRCode();
void SetRCode(u8 value);
DNS_Packet() {}
DNS_Packet(u8* buffer, int bufferSize);
virtual int GetLength();
virtual void WriteBytes(u8* buffer, int* offset);
};
} // namespace PacketReader::IP::UDP::DNS

View File

@ -0,0 +1,130 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "UDP_Packet.h"
#include "../../NetLib.h"
namespace PacketReader::IP::UDP
{
UDP_Packet::UDP_Packet(Payload* data)
: payload{data}
{
}
UDP_Packet::UDP_Packet(u8* buffer, int bufferSize)
{
int offset = 0;
//Bits 0-31
NetLib::ReadUInt16(buffer, &offset, &sourcePort);
NetLib::ReadUInt16(buffer, &offset, &destinationPort);
//Bits 32-63
u16 length;
NetLib::ReadUInt16(buffer, &offset, &length); //includes header length
NetLib::ReadUInt16(buffer, &offset, &checksum);
if (length > bufferSize)
{
Console.Error("DEV9: UDP_Packet: Unexpected Length");
length = (u16)bufferSize;
}
//Bits 64+
payload = std::make_unique<PayloadPtr>(&buffer[offset], length - offset);
//AllDone
}
Payload* UDP_Packet::GetPayload()
{
return payload.get();
}
int UDP_Packet::GetLength()
{
return headerLength + payload->GetLength();
}
void UDP_Packet::WriteBytes(u8* buffer, int* offset)
{
NetLib::WriteUInt16(buffer, offset, sourcePort);
NetLib::WriteUInt16(buffer, offset, destinationPort);
NetLib::WriteUInt16(buffer, offset, GetLength());
NetLib::WriteUInt16(buffer, offset, checksum);
payload->WriteBytes(buffer, offset);
}
u8 UDP_Packet::GetProtocol()
{
return (u8)protocol;
}
void UDP_Packet::CalculateChecksum(IP_Address srcIP, IP_Address dstIP)
{
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 UDP_Packet::VerifyChecksum(IP_Address srcIP, IP_Address dstIP)
{
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::UDP

View File

@ -0,0 +1,51 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "../IP_Packet.h"
namespace PacketReader::IP::UDP
{
class UDP_Packet : public IP_Payload
{
public:
u16 sourcePort;
u16 destinationPort;
private:
//u16 length;
u16 checksum;
const static int headerLength = 8;
const static IP_Type protocol = IP_Type::UDP;
std::unique_ptr<Payload> payload;
public:
//Takes ownership of payload
UDP_Packet(Payload* data);
UDP_Packet(u8* buffer, int bufferSize);
Payload* GetPayload();
virtual int GetLength();
virtual void WriteBytes(u8* buffer, int* offset);
virtual u8 GetProtocol();
virtual bool VerifyChecksum(IP_Address srcIP, IP_Address dstIP);
virtual void CalculateChecksum(IP_Address srcIP, IP_Address dstIP);
};
} // namespace PacketReader::IP::UDP

View File

@ -0,0 +1,75 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "NetLib.h"
#ifdef _WIN32
#include "winsock.h"
#else
#include <arpa/inet.h>
#endif
namespace PacketReader::NetLib
{
void WriteByte08(u8* data, int* index, u8 value)
{
data[*index] = value;
*index += sizeof(u8);
}
void WriteUInt16(u8* data, int* index, u16 value)
{
*(u16*)&data[*index] = htons(value);
*index += sizeof(u16);
}
void WriteUInt32(u8* data, int* index, u32 value)
{
*(u32*)&data[*index] = htonl(value);
*index += sizeof(u32);
}
//Special
void WriteByteArray(u8* data, int* index, int length, u8* value)
{
memcpy(&data[*index], value, length);
*index += length;
}
//Read
void ReadByte08(u8* data, int* index, u8* value)
{
*value = data[*index];
*index += sizeof(u8);
}
void ReadUInt16(u8* data, int* index, u16* value)
{
*value = ntohs(*(u16*)&data[*index]);
*index += sizeof(u16);
}
void ReadUInt32(u8* data, int* index, u32* value)
{
*value = ntohl(*(u32*)&data[*index]);
*index += sizeof(u32);
}
//Special
void ReadByteArray(u8* data, int* index, int length, u8* value)
{
memcpy(value, &data[*index], length);
*index += length;
}
} // namespace PacketReader::NetLib

View File

@ -0,0 +1,31 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace PacketReader::NetLib
{
void WriteByte08(u8* data, int* index, u8 value);
void WriteUInt16(u8* data, int* index, u16 value);
void WriteUInt32(u8* data, int* index, u32 value);
void WriteByteArray(u8* data, int* index, int length, u8* value);
void ReadByte08(u8* data, int* index, u8* value);
void ReadUInt16(u8* data, int* index, u16* value);
void ReadUInt32(u8* data, int* index, u32* value);
void ReadByteArray(u8* data, int* index, int length, u8* value);
} // namespace PacketReader::NetLib

View File

@ -0,0 +1,58 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace PacketReader
{
class Payload
{
public:
virtual int GetLength() = 0;
virtual void WriteBytes(u8* buffer, int* offset) = 0;
virtual ~Payload() {}
};
//Pointer to bytes not owned by class
class PayloadPtr : public Payload
{
public:
u8* data;
private:
int length;
public:
PayloadPtr(u8* ptr, int len)
{
data = ptr;
length = len;
}
virtual int GetLength()
{
return length;
}
virtual void WriteBytes(u8* buffer, int* offset)
{
//If buffer & data point to the same location
//Then no copy is needed
if (data == buffer)
return;
memcpy(buffer, data, length);
*offset += length;
}
};
} // namespace PacketReader

View File

@ -286,6 +286,15 @@
<ClCompile Include="..\..\DEV9\ATA\HddCreate.cpp" />
<ClCompile Include="..\..\DEV9\DEV9.cpp" />
<ClCompile Include="..\..\DEV9\flash.cpp" />
<ClCompile Include="..\..\DEV9\PacketReader\EthernetFrame.cpp" />
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\DHCP\DHCP_Options.cpp" />
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\DHCP\DHCP_Packet.cpp" />
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Classes.cpp" />
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Packet.cpp" />
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\UDP_Packet.cpp" />
<ClCompile Include="..\..\DEV9\PacketReader\IP\IP_Options.cpp" />
<ClCompile Include="..\..\DEV9\PacketReader\IP\IP_Packet.cpp" />
<ClCompile Include="..\..\DEV9\PacketReader\NetLib.cpp" />
<ClCompile Include="..\..\DEV9\pcap_io.cpp" />
<ClCompile Include="..\..\DEV9\Win32\pcap_io_win32.cpp" />
<ClCompile Include="..\..\DEV9\smap.cpp" />
@ -649,6 +658,19 @@
<ClInclude Include="..\..\DEV9\Config.h" />
<ClInclude Include="..\..\DEV9\DEV9.h" />
<ClInclude Include="..\..\DEV9\net.h" />
<ClInclude Include="..\..\DEV9\PacketReader\EthernetFrame.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DHCP\DHCP_Options.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DHCP\DHCP_Packet.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Classes.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Enums.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Packet.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\UDP_Packet.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\IP_Address.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\IP_Options.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\IP_Packet.h" />
<ClInclude Include="..\..\DEV9\PacketReader\IP\IP_Payload.h" />
<ClInclude Include="..\..\DEV9\PacketReader\NetLib.h" />
<ClInclude Include="..\..\DEV9\PacketReader\Payload.h" />
<ClInclude Include="..\..\DEV9\pcap_io.h" />
<ClInclude Include="..\..\DEV9\SimpleQueue.h" />
<ClInclude Include="..\..\DEV9\smap.h" />

View File

@ -178,6 +178,21 @@
<Filter Include="System\Ps2\DEV9\ATA\Commands">
<UniqueIdentifier>{9e9b52d7-7b1c-44b2-82d8-1e0d8085e7e0}</UniqueIdentifier>
</Filter>
<Filter Include="System\Ps2\DEV9\PacketReader">
<UniqueIdentifier>{57c4be94-9a2c-469b-9b02-b3b324857fc5}</UniqueIdentifier>
</Filter>
<Filter Include="System\Ps2\DEV9\PacketReader\IP">
<UniqueIdentifier>{a0723e13-c839-464d-8cfa-6c440ae03537}</UniqueIdentifier>
</Filter>
<Filter Include="System\Ps2\DEV9\PacketReader\IP\UDP">
<UniqueIdentifier>{db2fc75d-6552-4991-9155-885abd8796e4}</UniqueIdentifier>
</Filter>
<Filter Include="System\Ps2\DEV9\PacketReader\IP\UDP\DHCP">
<UniqueIdentifier>{d426ae2b-9ad6-473d-adba-57b7bdac87db}</UniqueIdentifier>
</Filter>
<Filter Include="System\Ps2\DEV9\PacketReader\IP\UDP\DNS">
<UniqueIdentifier>{229bf045-e378-4ec5-bdf8-43938762511e}</UniqueIdentifier>
</Filter>
<Filter Include="System\Ps2\USB">
<UniqueIdentifier>{df9de75c-2272-4f73-b2a0-4f9f492ba1e9}</UniqueIdentifier>
</Filter>
@ -1090,6 +1105,33 @@
<ClCompile Include="..\..\DEV9\flash.cpp">
<Filter>System\Ps2\DEV9</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\DHCP\DHCP_Options.cpp">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DHCP</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\DHCP\DHCP_Packet.cpp">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DHCP</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Classes.cpp">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DNS</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Packet.cpp">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DNS</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\PacketReader\IP\UDP\UDP_Packet.cpp">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\PacketReader\IP\IP_Options.cpp">
<Filter>System\Ps2\DEV9\PacketReader\IP</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\PacketReader\IP\IP_Packet.cpp">
<Filter>System\Ps2\DEV9\PacketReader\IP</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\PacketReader\EthernetFrame.cpp">
<Filter>System\Ps2\DEV9\PacketReader</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\PacketReader\NetLib.cpp">
<Filter>System\Ps2\DEV9\PacketReader</Filter>
</ClCompile>
<ClCompile Include="..\..\DEV9\pcap_io.cpp">
<Filter>System\Ps2\DEV9</Filter>
</ClCompile>
@ -1848,6 +1890,45 @@
<ClInclude Include="..\..\DEV9\net.h">
<Filter>System\Ps2\DEV9</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DHCP\DHCP_Options.h">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DHCP</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DHCP\DHCP_Packet.h">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DHCP</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Classes.h">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DNS</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Enums.h">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DNS</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\DNS\DNS_Packet.h">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DNS</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\UDP\UDP_Packet.h">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\IP_Address.h">
<Filter>System\Ps2\DEV9\PacketReader\IP</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\IP_Options.h">
<Filter>System\Ps2\DEV9\PacketReader\IP</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\IP_Packet.h">
<Filter>System\Ps2\DEV9\PacketReader\IP</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\IP\IP_Payload.h">
<Filter>System\Ps2\DEV9\PacketReader\IP</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\EthernetFrame.h">
<Filter>System\Ps2\DEV9\PacketReader</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\NetLib.h">
<Filter>System\Ps2\DEV9\PacketReader</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\PacketReader\Payload.h">
<Filter>System\Ps2\DEV9\PacketReader</Filter>
</ClInclude>
<ClInclude Include="..\..\DEV9\pcap_io.h">
<Filter>System\Ps2\DEV9</Filter>
</ClInclude>