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 \ 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 \ 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 \ 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 SRCDIR = src
OBJS := $(addprefix $(SRCDIR)/, $(OBJS)) OBJS := $(addprefix $(SRCDIR)/, $(OBJS))

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,41 +1,48 @@
#include <cstring>
#include "net-icmp.h" #include "net-icmp.h"
// #include "types.h"
// IcmpPacketHeader #include <uspi.h>
//
IcmpPacketHeader::IcmpPacketHeader() {}
IcmpPacketHeader::IcmpPacketHeader(std::uint8_t type, std::uint8_t code) : namespace Net::Icmp
{
//
// PacketHeader
//
PacketHeader::PacketHeader() {}
PacketHeader::PacketHeader(Type type, uint8_t code) :
type(type), code(code), checksum(0) type(type), code(code), checksum(0)
{} {}
std::size_t IcmpPacketHeader::Serialize(uint8_t* buffer) const size_t PacketHeader::Serialize(uint8_t* buffer) const
{ {
size_t i = 0; size_t i = 0;
buffer[i++] = type; buffer[i++] = static_cast<uint8_t>(type);
buffer[i++] = code; buffer[i++] = code;
buffer[i++] = checksum; buffer[i++] = checksum;
buffer[i++] = checksum >> 8; buffer[i++] = checksum >> 8;
return i; return i;
} }
IcmpPacketHeader IcmpPacketHeader::Deserialize(const uint8_t* buffer) PacketHeader PacketHeader::Deserialize(const uint8_t* buffer)
{ {
IcmpPacketHeader self; PacketHeader self;
self.type = buffer[0]; self.type = static_cast<Type>(buffer[0]);
self.code = buffer[1]; self.code = buffer[1];
self.checksum = buffer[2] << 8 | buffer[3]; self.checksum = buffer[2] << 8 | buffer[3];
return self; return self;
} }
// //
// IcmpEchoHeader // EchoHeader
// //
IcmpEchoHeader::IcmpEchoHeader() : IcmpEchoHeader(0, 0) {} EchoHeader::EchoHeader() : EchoHeader(0, 0) {}
IcmpEchoHeader::IcmpEchoHeader(uint16_t identifier, uint16_t sequenceNumber) : EchoHeader::EchoHeader(uint16_t identifier, uint16_t sequenceNumber) :
identifier(identifier), sequenceNumber(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; size_t i = 0;
buffer[i++] = identifier >> 8; buffer[i++] = identifier >> 8;
@ -45,10 +52,87 @@ size_t IcmpEchoHeader::Serialize(uint8_t* buffer) const
return i; return i;
} }
IcmpEchoHeader IcmpEchoHeader::Deserialize(const uint8_t* buffer) EchoHeader EchoHeader::Deserialize(const uint8_t* buffer)
{ {
IcmpEchoHeader self; EchoHeader self;
self.identifier = buffer[0] << 8 | buffer[1]; self.identifier = buffer[0] << 8 | buffer[1];
self.sequenceNumber = buffer[2] << 8 | buffer[3]; self.sequenceNumber = buffer[2] << 8 | buffer[3];
return self; 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 #pragma once
#include "net.h" #include "net.h"
enum IcmpType namespace Net::Icmp
{ {
ICMP_ECHO_REPLY = 0, enum class Type : uint8_t
ICMP_ECHO_REQUEST = 8, {
EchoReply = 0,
EchoRequest = 8,
}; };
struct IcmpPacketHeader struct PacketHeader
{ {
std::uint8_t type; Type type;
std::uint8_t code; uint8_t code;
std::uint16_t checksum; uint16_t checksum;
IcmpPacketHeader(); PacketHeader();
IcmpPacketHeader(std::uint8_t type, std::uint8_t code); PacketHeader(Type type, uint8_t code);
constexpr static std::size_t SerializedLength() constexpr static size_t SerializedLength()
{ {
return sizeof(type) + sizeof(code) + sizeof(checksum); return sizeof(type) + sizeof(code) + sizeof(checksum);
} }
std::size_t Serialize(uint8_t* buffer) const; size_t Serialize(uint8_t* buffer) const;
static IcmpPacketHeader Deserialize(const uint8_t* buffer); static PacketHeader Deserialize(const uint8_t* buffer);
}; };
struct IcmpEchoHeader struct EchoHeader
{ {
uint16_t identifier; uint16_t identifier;
uint16_t sequenceNumber; uint16_t sequenceNumber;
IcmpEchoHeader(); EchoHeader();
IcmpEchoHeader(uint16_t identifier, uint16_t sequenceNumber); EchoHeader(uint16_t identifier, uint16_t sequenceNumber);
constexpr static size_t SerializedLength() constexpr static size_t SerializedLength()
{ {
@ -39,5 +41,9 @@ struct IcmpEchoHeader
} }
size_t Serialize(uint8_t* buffer) const; 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,10 +1,16 @@
#include "net-ipv4.h" #include "net-ipv4.h"
#include "net-ethernet.h"
#include "net-arp.h"
#include "net-icmp.h"
#include "net-udp.h"
#include "net-utils.h" #include "net-utils.h"
Ipv4Header::Ipv4Header() {} namespace Net::Ipv4
{
Header::Header() {}
Ipv4Header::Ipv4Header( Header::Header(
uint8_t protocol, uint32_t sourceIp, uint32_t destinationIp, uint16_t totalLength Protocol protocol, uint32_t sourceIp, uint32_t destinationIp, uint16_t totalLength
) : ) :
version(4), version(4),
ihl(5), ihl(5),
@ -21,7 +27,7 @@ Ipv4Header::Ipv4Header(
destinationIp(destinationIp) destinationIp(destinationIp)
{} {}
size_t Ipv4Header::Serialize(uint8_t* buffer) const size_t Header::Serialize(uint8_t* buffer) const
{ {
size_t i = 0; size_t i = 0;
@ -34,7 +40,7 @@ size_t Ipv4Header::Serialize(uint8_t* buffer) const
buffer[i++] = (flags << 13 | fragmentOffset) >> 8; buffer[i++] = (flags << 13 | fragmentOffset) >> 8;
buffer[i++] = flags << 13 | fragmentOffset; buffer[i++] = flags << 13 | fragmentOffset;
buffer[i++] = ttl; buffer[i++] = ttl;
buffer[i++] = protocol; buffer[i++] = static_cast<uint8_t>(protocol);
// Zero the checksum before calculating it // Zero the checksum before calculating it
buffer[i++] = 0; buffer[i++] = 0;
@ -56,9 +62,9 @@ size_t Ipv4Header::Serialize(uint8_t* buffer) const
return i; return i;
} }
Ipv4Header Ipv4Header::Deserialize(const uint8_t* buffer) Header Header::Deserialize(const uint8_t* buffer)
{ {
Ipv4Header self; Header self;
self.version = buffer[0] >> 4; self.version = buffer[0] >> 4;
self.ihl = buffer[0] & 0x0F; 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.fragmentOffset = (buffer[6] & 0x1F) << 8 | buffer[7];
self.ttl = buffer[8]; self.ttl = buffer[8];
self.protocol = buffer[9]; self.protocol = static_cast<Protocol>(buffer[9]);
self.headerChecksum = buffer[10] << 8 | buffer[11]; self.headerChecksum = buffer[10] << 8 | buffer[11];
self.sourceIp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15]; self.sourceIp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15];
@ -81,3 +87,32 @@ Ipv4Header Ipv4Header::Deserialize(const uint8_t* buffer)
return self; 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,15 +1,18 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
#include "net-ethernet.h"
enum IpProtocols namespace Net::Ipv4
{ {
IP_PROTO_ICMP = 1, enum class Protocol : uint8_t
IP_PROTO_TCP = 6, {
IP_PROTO_UDP = 17, Icmp = 1,
Tcp = 6,
Udp = 17,
}; };
struct Ipv4Header struct Header
{ {
uint8_t version; uint8_t version;
uint8_t ihl; uint8_t ihl;
@ -20,14 +23,14 @@ struct Ipv4Header
uint8_t flags; uint8_t flags;
uint16_t fragmentOffset; uint16_t fragmentOffset;
uint8_t ttl; uint8_t ttl;
uint8_t protocol; Protocol protocol;
uint16_t headerChecksum; uint16_t headerChecksum;
uint32_t sourceIp; uint32_t sourceIp;
uint32_t destinationIp; uint32_t destinationIp;
Ipv4Header(); Header();
Ipv4Header( Header(
uint8_t protocol, Protocol protocol,
uint32_t sourceIp, uint32_t sourceIp,
uint32_t destinationIp, uint32_t destinationIp,
uint16_t totalLength uint16_t totalLength
@ -40,5 +43,12 @@ struct Ipv4Header
} }
size_t Serialize(uint8_t* buffer) const; 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 <memory>
#include <cstring>
#include "ff.h" #include "ff.h"
#include "net-arp.h" #include "net-arp.h"
@ -116,7 +117,7 @@ namespace Net::Tftp
void HandlePacket( void HandlePacket(
const Ethernet::Header ethernetReqHeader, const Ethernet::Header ethernetReqHeader,
const Ipv4Header ipv4ReqHeader, const Ipv4::Header ipv4ReqHeader,
const Udp::Header udpReqHeader, const Udp::Header udpReqHeader,
const uint8_t* data const uint8_t* data
) { ) {
@ -147,16 +148,16 @@ namespace Net::Tftp
udpReqHeader.sourcePort, udpReqHeader.sourcePort,
response->SerializedLength() + Udp::Header::SerializedLength() response->SerializedLength() + Udp::Header::SerializedLength()
); );
Ipv4Header ipv4RespHeader( Ipv4::Header ipv4RespHeader(
IP_PROTO_UDP, Ipv4::Protocol::Udp,
Utils::Ipv4Address, Utils::Ipv4Address,
ipv4ReqHeader.sourceIp, ipv4ReqHeader.sourceIp,
udpRespHeader.length + Ipv4Header::SerializedLength() udpRespHeader.length + Ipv4::Header::SerializedLength()
); );
Ethernet::Header ethernetRespHeader( Ethernet::Header ethernetRespHeader(
Arp::ArpTable[ipv4RespHeader.destinationIp], Arp::ArpTable[ipv4RespHeader.destinationIp],
Utils::GetMacAddress(), Utils::GetMacAddress(),
Ethernet::ETHERTYPE_IPV4 Ethernet::EtherType::Ipv4
); );
size_t i = 0; size_t i = 0;

View file

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

View file

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

View file

@ -39,7 +39,7 @@ namespace Net::Udp
void HandlePacket( void HandlePacket(
const Ethernet::Header ethernetHeader, const Ethernet::Header ethernetHeader,
const Ipv4Header ipv4Header, const Ipv4::Header ipv4Header,
const uint8_t* buffer, const uint8_t* buffer,
const size_t size 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 #pragma once
#include <cstdint>
#include <cstring>
#include <algorithm>
#include <array>
#include <unordered_map>
#include "net-arp.h" #include "net-arp.h"
#include "net-ethernet.h" #include "net-ethernet.h"
#include "net-ipv4.h" #include "net-ipv4.h"
#include "net-utils.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);