Namespace ICMP and IPv4, and enum -> enum class

This commit is contained in:
Sijmen 2020-12-28 14:41:27 +01:00
parent de644dc035
commit 40ecbd51f6
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
17 changed files with 368 additions and 372 deletions

View file

@ -4,7 +4,7 @@ OBJS = armc-start.o armc-cstartup.o armc-cstubs.o armc-cppstubs.o \
Drive.o Pi1541.o DiskImage.o iec_bus.o iec_commands.o m6502.o m6522.o \
gcr.o prot.o lz.o emmc.o diskio.o options.o Screen.o SSD1306.o ScreenLCD.o \
Timer.o FileBrowser.o DiskCaddy.o ROMs.o InputMappings.o xga_font_data.o m8520.o wd177x.o Pi1581.o SpinLock.o \
net.o net-tftp.o net-arp.o net-ethernet.o net-icmp.o net-ipv4.o net-udp.o net-dhcp.o net-utils.o
net-tftp.o net-arp.o net-ethernet.o net-icmp.o net-ipv4.o net-udp.o net-dhcp.o net-utils.o
SRCDIR = src
OBJS := $(addprefix $(SRCDIR)/, $(OBJS))

View file

@ -389,11 +389,12 @@ void updateNetwork()
switch (ethernetHeader.type)
{
case Net::Ethernet::ETHERTYPE_ARP:
case Net::Ethernet::EtherType::Arp:
Net::Arp::HandlePacket(ethernetHeader, ipBuffer + offset);
break;
case Net::Ethernet::ETHERTYPE_IPV4:
HandleIpv4Packet(ethernetHeader, ipBuffer + offset, sizeof(ipBuffer) - offset);
case Net::Ethernet::EtherType::Ipv4:
Net::Ipv4::HandlePacket(
ethernetHeader, ipBuffer + offset, sizeof(ipBuffer) - offset);
break;
}
}

View file

@ -13,7 +13,7 @@ namespace Net::Arp
Packet::Packet(uint16_t operation) :
hardwareType(1), // Ethernet
protocolType(Ethernet::ETHERTYPE_IPV4),
protocolType(Ethernet::EtherType::Ipv4),
hardwareAddressLength(6),
protocolAddressLength(4),
operation(operation)
@ -23,8 +23,8 @@ namespace Net::Arp
{
buffer[0] = hardwareType >> 8;
buffer[1] = hardwareType;
buffer[2] = protocolType >> 8;
buffer[3] = protocolType;
buffer[2] = static_cast<uint16_t>(protocolType) >> 8;
buffer[3] = static_cast<uint16_t>(protocolType);
buffer[4] = hardwareAddressLength;
buffer[5] = protocolAddressLength;
buffer[6] = operation >> 8;
@ -53,7 +53,8 @@ namespace Net::Arp
Packet self;
self.hardwareType = buffer[0] << 8 | buffer[1];
self.protocolType = buffer[2] << 8 | buffer[3];
self.protocolType =
static_cast<Ethernet::EtherType>(buffer[2] << 8 | buffer[3]);
self.hardwareAddressLength = buffer[4];
self.protocolAddressLength = buffer[5];
self.operation = buffer[6] << 8 | buffer[7];
@ -82,7 +83,7 @@ namespace Net::Arp
arpPacket.senderIp = senderIp;
Ethernet::Header ethernetHeader(
senderMac, targetMac, Ethernet::ETHERTYPE_ARP);
senderMac, targetMac, Ethernet::EtherType::Arp);
uint8_t buffer[USPI_FRAME_BUFFER_SIZE];
size_t size = 0;
@ -122,7 +123,7 @@ namespace Net::Arp
if (
arpPacket.hardwareType == 1 &&
arpPacket.protocolType == Ethernet::ETHERTYPE_IPV4 &&
arpPacket.protocolType == Ethernet::EtherType::Ipv4 &&
arpPacket.operation == ARP_OPERATION_REQUEST &&
arpPacket.targetIp == Utils::Ipv4Address)
{
@ -136,7 +137,7 @@ namespace Net::Arp
else if (
arpPacket.hardwareType == 1 &&
arpPacket.protocolType == Ethernet::ETHERTYPE_IPV4 &&
arpPacket.protocolType == Ethernet::EtherType::Ipv4 &&
arpPacket.operation == ARP_OPERATION_REPLY &&
arpPacket.targetIp == Utils::Ipv4Address &&
arpPacket.targetMac == macAddress)

View file

@ -14,7 +14,7 @@ namespace Net::Arp
struct Packet
{
uint16_t hardwareType;
uint16_t protocolType;
Ethernet::EtherType protocolType;
uint8_t hardwareAddressLength;
uint8_t protocolAddressLength;
uint16_t operation;

View file

@ -1,9 +1,12 @@
#include <random>
#include <cassert>
#include <cstring>
#include "net-dhcp.h"
#include "net-udp.h"
#include "net-ipv4.h"
#include "net-ethernet.h"
#include <random>
#include <cassert>
#include "types.h"
#include <uspi.h>
#include <uspios.h>
@ -138,14 +141,11 @@ namespace Net::Dhcp
const Udp::Header udpHeader(
Udp::Port::DhcpClient, Udp::Port::DhcpServer, udpLength);
size_t ipv4Length = udpLength + Ipv4Header::SerializedLength();
const Ipv4Header ipv4Header(
IP_PROTO_UDP, clientIpAddress, serverIpAddress, ipv4Length);
size_t ipv4Length = udpLength + Ipv4::Header::SerializedLength();
const Ipv4::Header ipv4Header(
Ipv4::Protocol::Udp, clientIpAddress, serverIpAddress, ipv4Length);
const Ethernet::Header ethernetHeader(
serverMacAddress,
Utils::GetMacAddress(),
Ethernet::ETHERTYPE_IPV4
);
serverMacAddress, Utils::GetMacAddress(), Ethernet::EtherType::Ipv4);
uint8_t buffer[USPI_FRAME_BUFFER_SIZE];
size_t size = 0;
@ -197,10 +197,10 @@ namespace Net::Dhcp
const Udp::Header udpHeader(
Udp::Port::DhcpClient, Udp::Port::DhcpServer, udpLength);
size_t ipv4Length = udpLength + Ipv4Header::SerializedLength();
const Ipv4Header ipv4Header(IP_PROTO_UDP, 0, 0xFFFFFFFF, ipv4Length);
size_t ipv4Length = udpLength + Ipv4::Header::SerializedLength();
const Ipv4::Header ipv4Header(Ipv4::Protocol::Udp, 0, 0xFFFFFFFF, ipv4Length);
const Ethernet::Header ethernetHeader(
Utils::GetMacAddress(), Ethernet::ETHERTYPE_IPV4);
Utils::GetMacAddress(), Ethernet::EtherType::Ipv4);
uint8_t buffer[USPI_FRAME_BUFFER_SIZE];
size_t size = 0;

View file

@ -6,14 +6,14 @@ namespace Net::Ethernet
Header::Header()
{}
Header::Header(uint16_t type) :
Header::Header(EtherType type) :
macDestination(Utils::MacBroadcast),
macSource{0, 0, 0, 0, 0, 0},
type(type)
{}
Header::Header(
MacAddress macSource, uint16_t type
MacAddress macSource, EtherType type
) :
macDestination(Utils::MacBroadcast),
macSource(macSource),
@ -21,7 +21,7 @@ namespace Net::Ethernet
{}
Header::Header(
MacAddress macDestination, MacAddress macSource, uint16_t type
MacAddress macDestination, MacAddress macSource, EtherType type
) :
macDestination(macDestination),
macSource(macSource),
@ -38,8 +38,8 @@ namespace Net::Ethernet
std::memcpy(buffer + i, macSource.data(), macSource.size());
i += sizeof(macSource);
buffer[i++] = type >> 8;
buffer[i++] = type;
buffer[i++] = static_cast<uint16_t>(type) >> 8;
buffer[i++] = static_cast<uint16_t>(type);
return i;
}
@ -49,7 +49,7 @@ namespace Net::Ethernet
Header self;
std::memcpy(self.macDestination.data(), buffer + 0, self.macDestination.size());
std::memcpy(self.macSource.data(), buffer + 6, self.macSource.size());
self.type = buffer[12] << 8 | buffer[13];
self.type = static_cast<EtherType>(buffer[12] << 8 | buffer[13]);
return self;
}
} // namespace Net::Ethernet

View file

@ -6,22 +6,22 @@ namespace Net::Ethernet
{
using Utils::MacAddress;
enum EtherType
enum class EtherType : uint16_t
{
ETHERTYPE_IPV4 = 0x0800,
ETHERTYPE_ARP = 0x0806,
Ipv4 = 0x0800,
Arp = 0x0806,
};
struct Header
{
MacAddress macDestination;
MacAddress macSource;
uint16_t type;
EtherType type;
Header();
Header(uint16_t type);
Header(MacAddress macSource, uint16_t type);
Header(MacAddress macDestination, MacAddress macSource, uint16_t type);
Header(EtherType type);
Header(MacAddress macSource, EtherType type);
Header(MacAddress macDestination, MacAddress macSource, EtherType type);
constexpr static size_t SerializedLength()
{

View file

@ -1,54 +1,138 @@
#include <cstring>
#include "net-icmp.h"
//
// IcmpPacketHeader
//
IcmpPacketHeader::IcmpPacketHeader() {}
#include "types.h"
#include <uspi.h>
IcmpPacketHeader::IcmpPacketHeader(std::uint8_t type, std::uint8_t code) :
type(type), code(code), checksum(0)
{}
std::size_t IcmpPacketHeader::Serialize(uint8_t* buffer) const
namespace Net::Icmp
{
//
// PacketHeader
//
PacketHeader::PacketHeader() {}
PacketHeader::PacketHeader(Type type, uint8_t code) :
type(type), code(code), checksum(0)
{}
size_t PacketHeader::Serialize(uint8_t* buffer) const
{
size_t i = 0;
buffer[i++] = type;
buffer[i++] = static_cast<uint8_t>(type);
buffer[i++] = code;
buffer[i++] = checksum;
buffer[i++] = checksum >> 8;
return i;
}
}
IcmpPacketHeader IcmpPacketHeader::Deserialize(const uint8_t* buffer)
{
IcmpPacketHeader self;
self.type = buffer[0];
PacketHeader PacketHeader::Deserialize(const uint8_t* buffer)
{
PacketHeader self;
self.type = static_cast<Type>(buffer[0]);
self.code = buffer[1];
self.checksum = buffer[2] << 8 | buffer[3];
return self;
}
}
//
// IcmpEchoHeader
//
IcmpEchoHeader::IcmpEchoHeader() : IcmpEchoHeader(0, 0) {}
IcmpEchoHeader::IcmpEchoHeader(uint16_t identifier, uint16_t sequenceNumber) :
//
// EchoHeader
//
EchoHeader::EchoHeader() : EchoHeader(0, 0) {}
EchoHeader::EchoHeader(uint16_t identifier, uint16_t sequenceNumber) :
identifier(identifier), sequenceNumber(sequenceNumber) {}
size_t IcmpEchoHeader::Serialize(uint8_t* buffer) const
{
size_t EchoHeader::Serialize(uint8_t* buffer) const
{
size_t i = 0;
buffer[i++] = identifier >> 8;
buffer[i++] = identifier;
buffer[i++] = sequenceNumber >> 8;
buffer[i++] = sequenceNumber;
return i;
}
}
IcmpEchoHeader IcmpEchoHeader::Deserialize(const uint8_t* buffer)
{
IcmpEchoHeader self;
EchoHeader EchoHeader::Deserialize(const uint8_t* buffer)
{
EchoHeader self;
self.identifier = buffer[0] << 8 | buffer[1];
self.sequenceNumber = buffer[2] << 8 | buffer[3];
return self;
}
}
void SendEchoRequest(Utils::MacAddress mac, uint32_t ip)
{
Icmp::PacketHeader icmpHeader(Icmp::Type::EchoRequest, 0);
Icmp::EchoHeader pingHeader(0, 0);
size_t ipv4TotalSize = Icmp::PacketHeader::SerializedLength() +
Icmp::EchoHeader::SerializedLength() +
Ipv4::Header::SerializedLength();
Ipv4::Header ipv4Header(
Ipv4::Protocol::Icmp, Utils::Ipv4Address, ip, ipv4TotalSize);
Ethernet::Header ethernetHeader(
mac, Utils::GetMacAddress(), Ethernet::EtherType::Ipv4);
uint8_t buffer[USPI_FRAME_BUFFER_SIZE];
size_t i = 0;
i += ethernetHeader.Serialize(buffer + i);
i += ipv4Header.Serialize(buffer + i);
i += pingHeader.Serialize(buffer + i);
i += icmpHeader.Serialize(buffer + 1);
USPiSendFrame(buffer, i);
}
void HandlePacket(const uint8_t* buffer)
{
// TODO Don't re-parse the upper layers
size_t requestSize = 0;
const auto requestEthernetHeader =
Ethernet::Header::Deserialize(buffer + requestSize);
requestSize += requestEthernetHeader.SerializedLength();
const auto requestIpv4Header = Ipv4::Header::Deserialize(buffer + requestSize);
requestSize += requestIpv4Header.SerializedLength();
const auto requestIcmpHeader =
Icmp::PacketHeader::Deserialize(buffer + requestSize);
requestSize += requestIcmpHeader.SerializedLength();
if (requestIcmpHeader.type == Icmp::Type::EchoRequest)
{
const auto requestEchoHeader =
Icmp::EchoHeader::Deserialize(buffer + requestSize);
requestSize += requestEchoHeader.SerializedLength();
const Icmp::PacketHeader responseIcmpHeader(
Icmp::Type::EchoReply, 0);
const Ipv4::Header responseIpv4Header(
Ipv4::Protocol::Icmp,
Utils::Ipv4Address,
requestIpv4Header.sourceIp,
requestIpv4Header.totalLength
);
const Ethernet::Header responseEthernetHeader(
requestEthernetHeader.macSource,
Utils::GetMacAddress(),
Ethernet::EtherType::Ipv4
);
const auto payloadLength =
requestIpv4Header.totalLength -
requestIpv4Header.SerializedLength() -
requestIcmpHeader.SerializedLength() -
requestEchoHeader.SerializedLength();
std::array<uint8_t, USPI_FRAME_BUFFER_SIZE> bufferResp;
size_t respSize = 0;
respSize += responseEthernetHeader.Serialize(bufferResp.data() + respSize);
respSize += responseIpv4Header.Serialize(bufferResp.data() + respSize);
respSize += responseIcmpHeader.Serialize(bufferResp.data() + respSize);
std::memcpy(
bufferResp.data() + respSize, buffer + requestSize, payloadLength);
respSize += payloadLength;
USPiSendFrame(bufferResp.data(), respSize);
}
}
} // namespace Net::Icmp

View file

@ -1,37 +1,39 @@
#pragma once
#include "net.h"
enum IcmpType
namespace Net::Icmp
{
ICMP_ECHO_REPLY = 0,
ICMP_ECHO_REQUEST = 8,
};
enum class Type : uint8_t
{
EchoReply = 0,
EchoRequest = 8,
};
struct IcmpPacketHeader
{
std::uint8_t type;
std::uint8_t code;
std::uint16_t checksum;
struct PacketHeader
{
Type type;
uint8_t code;
uint16_t checksum;
IcmpPacketHeader();
IcmpPacketHeader(std::uint8_t type, std::uint8_t code);
PacketHeader();
PacketHeader(Type type, uint8_t code);
constexpr static std::size_t SerializedLength()
constexpr static size_t SerializedLength()
{
return sizeof(type) + sizeof(code) + sizeof(checksum);
}
std::size_t Serialize(uint8_t* buffer) const;
static IcmpPacketHeader Deserialize(const uint8_t* buffer);
};
size_t Serialize(uint8_t* buffer) const;
static PacketHeader Deserialize(const uint8_t* buffer);
};
struct IcmpEchoHeader
{
struct EchoHeader
{
uint16_t identifier;
uint16_t sequenceNumber;
IcmpEchoHeader();
IcmpEchoHeader(uint16_t identifier, uint16_t sequenceNumber);
EchoHeader();
EchoHeader(uint16_t identifier, uint16_t sequenceNumber);
constexpr static size_t SerializedLength()
{
@ -39,5 +41,9 @@ struct IcmpEchoHeader
}
size_t Serialize(uint8_t* buffer) const;
static IcmpEchoHeader Deserialize(const uint8_t* buffer);
};
static EchoHeader Deserialize(const uint8_t* buffer);
};
void SendEchoRequest(Utils::MacAddress mac, uint32_t ip);
void HandlePacket(const uint8_t* buffer);
} // namespace Net::Icmp

View file

@ -1,11 +1,17 @@
#include "net-ipv4.h"
#include "net-ethernet.h"
#include "net-arp.h"
#include "net-icmp.h"
#include "net-udp.h"
#include "net-utils.h"
Ipv4Header::Ipv4Header() {}
namespace Net::Ipv4
{
Header::Header() {}
Ipv4Header::Ipv4Header(
uint8_t protocol, uint32_t sourceIp, uint32_t destinationIp, uint16_t totalLength
) :
Header::Header(
Protocol protocol, uint32_t sourceIp, uint32_t destinationIp, uint16_t totalLength
) :
version(4),
ihl(5),
dscp(0),
@ -19,10 +25,10 @@ Ipv4Header::Ipv4Header(
headerChecksum(0),
sourceIp(sourceIp),
destinationIp(destinationIp)
{}
{}
size_t Ipv4Header::Serialize(uint8_t* buffer) const
{
size_t Header::Serialize(uint8_t* buffer) const
{
size_t i = 0;
buffer[i++] = version << 4 | ihl;
@ -34,7 +40,7 @@ size_t Ipv4Header::Serialize(uint8_t* buffer) const
buffer[i++] = (flags << 13 | fragmentOffset) >> 8;
buffer[i++] = flags << 13 | fragmentOffset;
buffer[i++] = ttl;
buffer[i++] = protocol;
buffer[i++] = static_cast<uint8_t>(protocol);
// Zero the checksum before calculating it
buffer[i++] = 0;
@ -54,11 +60,11 @@ size_t Ipv4Header::Serialize(uint8_t* buffer) const
buffer[11] = checksum >> 8;
return i;
}
}
Ipv4Header Ipv4Header::Deserialize(const uint8_t* buffer)
{
Ipv4Header self;
Header Header::Deserialize(const uint8_t* buffer)
{
Header self;
self.version = buffer[0] >> 4;
self.ihl = buffer[0] & 0x0F;
@ -72,7 +78,7 @@ Ipv4Header Ipv4Header::Deserialize(const uint8_t* buffer)
self.fragmentOffset = (buffer[6] & 0x1F) << 8 | buffer[7];
self.ttl = buffer[8];
self.protocol = buffer[9];
self.protocol = static_cast<Protocol>(buffer[9]);
self.headerChecksum = buffer[10] << 8 | buffer[11];
self.sourceIp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15];
@ -80,4 +86,33 @@ Ipv4Header Ipv4Header::Deserialize(const uint8_t* buffer)
buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19];
return self;
}
}
void HandlePacket(
const Ethernet::Header& ethernetHeader,
const uint8_t* buffer,
const size_t size
) {
const auto ipv4Header = Header::Deserialize(buffer);
const auto offset = Header::SerializedLength();
// Update ARP table
Arp::ArpTable.insert(
std::make_pair(ipv4Header.sourceIp, ethernetHeader.macSource));
if (ipv4Header.version != 4) return;
if (ipv4Header.ihl != 5) return; // Not supported
if (ipv4Header.destinationIp != Utils::Ipv4Address) return;
if (ipv4Header.fragmentOffset != 0) return; // TODO Support this
if (ipv4Header.protocol == Ipv4::Protocol::Icmp)
{
Icmp::HandlePacket(buffer);
}
else if (ipv4Header.protocol == Ipv4::Protocol::Udp)
{
Udp::HandlePacket(
ethernetHeader, ipv4Header, buffer + offset, size - offset);
}
}
} // namespace Net::Ipv4

View file

@ -1,16 +1,19 @@
#pragma once
#include <cstdint>
#include <cstddef>
#include "net-ethernet.h"
enum IpProtocols
namespace Net::Ipv4
{
IP_PROTO_ICMP = 1,
IP_PROTO_TCP = 6,
IP_PROTO_UDP = 17,
};
enum class Protocol : uint8_t
{
Icmp = 1,
Tcp = 6,
Udp = 17,
};
struct Ipv4Header
{
struct Header
{
uint8_t version;
uint8_t ihl;
uint8_t dscp;
@ -20,14 +23,14 @@ struct Ipv4Header
uint8_t flags;
uint16_t fragmentOffset;
uint8_t ttl;
uint8_t protocol;
Protocol protocol;
uint16_t headerChecksum;
uint32_t sourceIp;
uint32_t destinationIp;
Ipv4Header();
Ipv4Header(
uint8_t protocol,
Header();
Header(
Protocol protocol,
uint32_t sourceIp,
uint32_t destinationIp,
uint16_t totalLength
@ -40,5 +43,12 @@ struct Ipv4Header
}
size_t Serialize(uint8_t* buffer) const;
static Ipv4Header Deserialize(const uint8_t* buffer);
};
static Header Deserialize(const uint8_t* buffer);
};
void HandlePacket(
const Ethernet::Header& ethernetHeader,
const uint8_t* buffer,
const size_t size
);
} // namespace Net::Ipv4

View file

@ -1,4 +1,5 @@
#include <memory>
#include <cstring>
#include "ff.h"
#include "net-arp.h"
@ -116,7 +117,7 @@ namespace Net::Tftp
void HandlePacket(
const Ethernet::Header ethernetReqHeader,
const Ipv4Header ipv4ReqHeader,
const Ipv4::Header ipv4ReqHeader,
const Udp::Header udpReqHeader,
const uint8_t* data
) {
@ -147,16 +148,16 @@ namespace Net::Tftp
udpReqHeader.sourcePort,
response->SerializedLength() + Udp::Header::SerializedLength()
);
Ipv4Header ipv4RespHeader(
IP_PROTO_UDP,
Ipv4::Header ipv4RespHeader(
Ipv4::Protocol::Udp,
Utils::Ipv4Address,
ipv4ReqHeader.sourceIp,
udpRespHeader.length + Ipv4Header::SerializedLength()
udpRespHeader.length + Ipv4::Header::SerializedLength()
);
Ethernet::Header ethernetRespHeader(
Arp::ArpTable[ipv4RespHeader.destinationIp],
Utils::GetMacAddress(),
Ethernet::ETHERTYPE_IPV4
Ethernet::EtherType::Ipv4
);
size_t i = 0;

View file

@ -77,7 +77,7 @@ namespace Net::Tftp
void HandlePacket(
const Ethernet::Header ethernetReqHeader,
const Ipv4Header ipv4ReqHeader,
const Ipv4::Header ipv4ReqHeader,
const Udp::Header udpReqHeader,
const uint8_t* buffer
);

View file

@ -44,7 +44,7 @@ namespace Net::Udp
void HandlePacket(
const Ethernet::Header ethernetHeader,
const Ipv4Header ipv4Header,
const Ipv4::Header ipv4Header,
const uint8_t* buffer,
const size_t size
) {

View file

@ -39,7 +39,7 @@ namespace Net::Udp
void HandlePacket(
const Ethernet::Header ethernetHeader,
const Ipv4Header ipv4Header,
const Ipv4::Header ipv4Header,
const uint8_t* buffer,
const size_t size
);

View file

@ -1,121 +0,0 @@
#include <memory>
#include "ff.h"
#include "net-arp.h"
#include "net-ethernet.h"
#include "net-icmp.h"
#include "net-ipv4.h"
#include "net-udp.h"
#include "net-dhcp.h"
#include "net-tftp.h"
#include "net.h"
#include "types.h"
#include <uspi.h>
#include <uspios.h>
//
// IPv4
//
void HandleIpv4Packet(
const Net::Ethernet::Header ethernetHeader,
const uint8_t* buffer,
const size_t size
) {
const auto ipv4Header = Ipv4Header::Deserialize(buffer);
const auto offset = Ipv4Header::SerializedLength();
// Update ARP table
Net::Arp::ArpTable.insert(
std::make_pair(ipv4Header.sourceIp, ethernetHeader.macSource));
if (ipv4Header.version != 4) return;
if (ipv4Header.ihl != 5) return; // Not supported
if (ipv4Header.destinationIp != Net::Utils::Ipv4Address) return;
if (ipv4Header.fragmentOffset != 0) return; // TODO Support this
if (ipv4Header.protocol == IP_PROTO_ICMP)
{
HandleIcmpFrame(buffer);
}
else if (ipv4Header.protocol == IP_PROTO_UDP)
{
Net::Udp::HandlePacket(
ethernetHeader, ipv4Header, buffer + offset, size - offset);
}
}
//
// ICMP
//
void SendIcmpEchoRequest(Net::Utils::MacAddress mac, uint32_t ip)
{
IcmpPacketHeader icmpHeader(8, 0);
IcmpEchoHeader pingHeader(0, 0);
size_t ipv4TotalSize = IcmpPacketHeader::SerializedLength() +
IcmpEchoHeader::SerializedLength() +
Ipv4Header::SerializedLength();
Ipv4Header ipv4Header(1, Net::Utils::Ipv4Address, ip, ipv4TotalSize);
Net::Ethernet::Header ethernetHeader(
mac, Net::Utils::GetMacAddress(), Net::Ethernet::ETHERTYPE_IPV4);
uint8_t buffer[USPI_FRAME_BUFFER_SIZE];
size_t i = 0;
i += ethernetHeader.Serialize(buffer + i);
i += ipv4Header.Serialize(buffer + i);
i += pingHeader.Serialize(buffer + i);
i += icmpHeader.Serialize(buffer + 1);
USPiSendFrame(buffer, i);
}
void HandleIcmpFrame(const uint8_t* buffer)
{
// TODO Don't re-parse the upper layers
size_t requestSize = 0;
const auto requestEthernetHeader =
Net::Ethernet::Header::Deserialize(buffer + requestSize);
requestSize += requestEthernetHeader.SerializedLength();
const auto requestIpv4Header = Ipv4Header::Deserialize(buffer + requestSize);
requestSize += requestIpv4Header.SerializedLength();
const auto requestIcmpHeader = IcmpPacketHeader::Deserialize(buffer + requestSize);
requestSize += requestIcmpHeader.SerializedLength();
if (requestIcmpHeader.type == ICMP_ECHO_REQUEST)
{
const auto requestEchoHeader =
IcmpEchoHeader::Deserialize(buffer + requestSize);
requestSize += requestEchoHeader.SerializedLength();
const IcmpPacketHeader responseIcmpHeader(ICMP_ECHO_REPLY, 0);
const Ipv4Header responseIpv4Header(
IP_PROTO_ICMP,
Net::Utils::Ipv4Address,
requestIpv4Header.sourceIp,
requestIpv4Header.totalLength
);
const Net::Ethernet::Header responseEthernetHeader(
requestEthernetHeader.macSource,
Net::Utils::GetMacAddress(),
Net::Ethernet::ETHERTYPE_IPV4
);
const auto payloadLength =
requestIpv4Header.totalLength -
requestIpv4Header.SerializedLength() -
requestIcmpHeader.SerializedLength() -
requestEchoHeader.SerializedLength();
std::array<uint8_t, USPI_FRAME_BUFFER_SIZE> bufferResp;
size_t respSize = 0;
respSize += responseEthernetHeader.Serialize(bufferResp.data() + respSize);
respSize += responseIpv4Header.Serialize(bufferResp.data() + respSize);
respSize += responseIcmpHeader.Serialize(bufferResp.data() + respSize);
memcpy(bufferResp.data() + respSize, buffer + requestSize, payloadLength);
respSize += payloadLength;
USPiSendFrame(bufferResp.data(), respSize);
}
}

View file

@ -1,26 +1,5 @@
#pragma once
#include <cstdint>
#include <cstring>
#include <algorithm>
#include <array>
#include <unordered_map>
#include "net-arp.h"
#include "net-ethernet.h"
#include "net-ipv4.h"
#include "net-utils.h"
//
// IPv4
//
void HandleIpv4Packet(
const Net::Ethernet::Header ethernetHeader,
const uint8_t* buffer,
const size_t size
);
//
// ICMP
//
void SendIcmpEchoRequest(Net::Utils::MacAddress mac, uint32_t ip);
void HandleIcmpFrame(const uint8_t* buffer);