Namespace ICMP and IPv4, and enum -> enum class
This commit is contained in:
parent
de644dc035
commit
40ecbd51f6
17 changed files with 368 additions and 372 deletions
2
Makefile
2
Makefile
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
116
src/net-icmp.cpp
116
src/net-icmp.cpp
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
|
@ -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
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
121
src/net.cpp
121
src/net.cpp
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
21
src/net.h
21
src/net.h
|
@ -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);
|
|
||||||
|
|
Loading…
Reference in a new issue