Move ARP and TFTP to their own namespaces

This commit is contained in:
Sijmen 2020-12-27 22:17:36 +01:00
parent fc39c7a99f
commit 9638a0dc3d
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
7 changed files with 516 additions and 474 deletions

View file

@ -382,14 +382,14 @@ void updateNetwork()
static bool announcementSent = false;
if (!announcementSent)
{
SendArpAnnouncement(GetMacAddress(), Ipv4Address);
Net::Arp::SendAnnouncement(GetMacAddress(), Ipv4Address);
announcementSent = true;
}
switch (ethernetHeader.type)
{
case ETHERTYPE_ARP:
HandleArpFrame(ethernetHeader, ipBuffer + offset);
Net::Arp::HandlePacket(ethernetHeader, ipBuffer + offset);
break;
case ETHERTYPE_IPV4:
HandleIpv4Packet(ethernetHeader, ipBuffer + offset, sizeof(ipBuffer) - offset);

View file

@ -1,5 +1,11 @@
#include "net-arp.h"
#include "net-ethernet.h"
#include "types.h"
#include <uspi.h>
namespace Net::Arp
{
Ipv4ArpPacket::Ipv4ArpPacket()
{}
@ -59,3 +65,70 @@ Ipv4ArpPacket Ipv4ArpPacket::Deserialize(const uint8_t* buffer)
return self;
}
void SendPacket(
ArpOperation operation,
MacAddress targetMac,
MacAddress senderMac,
uint32_t targetIp,
uint32_t senderIp)
{
Ipv4ArpPacket arpPacket(operation);
arpPacket.targetMac = targetMac;
arpPacket.senderMac = senderMac;
arpPacket.targetIp = targetIp;
arpPacket.senderIp = senderIp;
EthernetFrameHeader ethernetHeader(senderMac, targetMac, ETHERTYPE_ARP);
uint8_t buffer[USPI_FRAME_BUFFER_SIZE];
size_t size = 0;
size += ethernetHeader.Serialize(buffer + size);
size += arpPacket.Serialize(buffer + size);
USPiSendFrame(buffer, size);
}
void SendRequest(
MacAddress targetMac, MacAddress senderMac, uint32_t targetIp, uint32_t senderIp)
{
SendPacket(ARP_OPERATION_REQUEST, targetMac, senderMac, targetIp, senderIp);
}
void SendReply(
MacAddress targetMac, MacAddress senderMac, uint32_t targetIp, uint32_t senderIp)
{
SendPacket(ARP_OPERATION_REPLY, targetMac, senderMac, targetIp, senderIp);
}
void SendAnnouncement(MacAddress mac, uint32_t ip)
{
SendReply(MacBroadcast, mac, ip, ip);
}
void HandlePacket(const EthernetFrameHeader ethernetHeader, uint8_t* buffer)
{
const auto macAddress = GetMacAddress();
const auto arpPacket = Ipv4ArpPacket::Deserialize(buffer);
if (
arpPacket.hardwareType == 1 &&
arpPacket.protocolType == ETHERTYPE_IPV4 &&
arpPacket.operation == ARP_OPERATION_REQUEST &&
arpPacket.targetIp == Ipv4Address)
{
SendReply(arpPacket.senderMac, macAddress, arpPacket.senderIp, Ipv4Address);
}
else if (
arpPacket.hardwareType == 1 &&
arpPacket.protocolType == ETHERTYPE_IPV4 &&
arpPacket.operation == ARP_OPERATION_REPLY &&
arpPacket.targetIp == Ipv4Address &&
arpPacket.targetMac == macAddress)
{
ArpTable.insert(std::make_pair(arpPacket.senderIp, arpPacket.senderMac));
}
}
std::unordered_map<std::uint32_t, MacAddress> ArpTable;
}; // namespace Net::Arp

View file

@ -1,6 +1,8 @@
#pragma once
#include "net.h"
namespace Net::Arp
{
struct Ipv4ArpPacket
{
std::uint16_t hardwareType;
@ -35,3 +37,32 @@ struct Ipv4ArpPacket
static Ipv4ArpPacket Deserialize(const uint8_t* buffer);
};
void HandlePacket(EthernetFrameHeader header, uint8_t* buffer);
void SendPacket(
ArpOperation operation,
MacAddress targetMac,
MacAddress senderMac,
uint32_t senderIp,
uint32_t targetIp
);
void SendRequest(
MacAddress targetMac,
MacAddress senderMac,
uint32_t senderIp,
uint32_t targetIp
);
void SendReply(
MacAddress targetMac,
MacAddress senderMac,
uint32_t senderIp,
uint32_t targetIp
);
void SendAnnouncement(MacAddress mac, uint32_t ip);
extern std::unordered_map<std::uint32_t, MacAddress> ArpTable;
}; // namespace Net::Arp

View file

@ -1,15 +1,18 @@
#include <memory>
#include "ff.h"
#include "net-arp.h"
#include "net-ethernet.h"
#include "net-ipv4.h"
#include "net-tftp.h"
#include "net-udp.h"
#include "net.h"
#include "types.h"
#include "types.h"
#include <uspi.h>
namespace Net::Tftp
{
// TODO Allow multiple files open
static FIL outFile;
static bool shouldReboot = false;
@ -117,15 +120,15 @@ void HandleTftpDatagram(
const UdpDatagramHeader udpReqHeader,
const uint8_t* data
) {
const auto opcode = data[0] << 8 | data[1];
const auto opcode = static_cast<Opcode>(data[0] << 8 | data[1]);
std::unique_ptr<TftpPacket> response;
bool last = false;
if (opcode == TFTP_OP_WRITE_REQUEST)
if (opcode == Opcode::WriteRequest)
{
response = handleTftpWriteRequest(data);
}
else if (opcode == TFTP_OP_DATA)
else if (opcode == Opcode::Data)
{
const auto length = udpReqHeader.length - UdpDatagramHeader::SerializedLength();
response = handleTftpData(data, length);
@ -151,7 +154,7 @@ void HandleTftpDatagram(
udpRespHeader.length + Ipv4Header::SerializedLength()
);
EthernetFrameHeader ethernetRespHeader(
ArpTable[ipv4RespHeader.destinationIp],
Net::Arp::ArpTable[ipv4RespHeader.destinationIp],
GetMacAddress(),
ETHERTYPE_IPV4
);
@ -176,7 +179,7 @@ void HandleTftpDatagram(
//
// TftpWriteReadRequestPacket
//
TftpWriteReadRequestPacket::TftpWriteReadRequestPacket(uint16_t opcode) :
TftpWriteReadRequestPacket::TftpWriteReadRequestPacket(const Opcode opcode) :
TftpPacket(opcode)
{}
@ -188,8 +191,8 @@ size_t TftpWriteReadRequestPacket::SerializedLength() const
size_t TftpWriteReadRequestPacket::Serialize(uint8_t* buffer) const
{
size_t i = 0;
buffer[i++] = opcode >> 8;
buffer[i++] = opcode;
buffer[i++] = static_cast<uint16_t>(opcode) >> 8;
buffer[i++] = static_cast<uint16_t>(opcode);
i += filename.copy(reinterpret_cast<char*>(buffer + i), filename.size());
buffer[i++] = 0;
@ -204,7 +207,8 @@ TftpWriteReadRequestPacket TftpWriteReadRequestPacket::Deserialize(const uint8_t
{
size_t i = 0;
TftpWriteReadRequestPacket self(buffer[i] << 8 | buffer[i + 1]);
const auto opcode = static_cast<Opcode>(buffer[i] << 8 | buffer[i + 1]);
TftpWriteReadRequestPacket self(opcode);
i += 2;
self.filename = reinterpret_cast<const char*>(buffer + i);
@ -219,9 +223,9 @@ TftpWriteReadRequestPacket TftpWriteReadRequestPacket::Deserialize(const uint8_t
//
// TftpErrorPacket
//
TftpErrorPacket::TftpErrorPacket() : TftpPacket(TFTP_OP_ERROR) {}
TftpErrorPacket::TftpErrorPacket() : TftpPacket(Opcode::Error) {}
TftpErrorPacket::TftpErrorPacket(uint16_t errorCode, std::string message) :
TftpPacket(TFTP_OP_ERROR), errorCode(errorCode), message(message)
TftpPacket(Opcode::Error), errorCode(errorCode), message(message)
{}
size_t TftpErrorPacket::SerializedLength() const
@ -232,8 +236,8 @@ size_t TftpErrorPacket::SerializedLength() const
size_t TftpErrorPacket::Serialize(uint8_t* buffer) const
{
size_t i = 0;
buffer[i++] = opcode >> 8;
buffer[i++] = opcode;
buffer[i++] = static_cast<uint16_t>(opcode) >> 8;
buffer[i++] = static_cast<uint16_t>(opcode);
buffer[i++] = errorCode >> 8;
buffer[i++] = errorCode;
@ -247,11 +251,11 @@ size_t TftpErrorPacket::Serialize(uint8_t* buffer) const
// TftpAcknowledgementPacket
//
TftpAcknowledgementPacket::TftpAcknowledgementPacket() :
TftpPacket(TFTP_OP_ACKNOWLEDGEMENT)
TftpPacket(Opcode::Acknowledgement)
{}
TftpAcknowledgementPacket::TftpAcknowledgementPacket(uint16_t blockNumber) :
TftpPacket(TFTP_OP_ACKNOWLEDGEMENT), blockNumber(blockNumber)
TftpPacket(Opcode::Acknowledgement), blockNumber(blockNumber)
{}
size_t TftpAcknowledgementPacket::SerializedLength() const
@ -262,8 +266,8 @@ size_t TftpAcknowledgementPacket::SerializedLength() const
size_t TftpAcknowledgementPacket::Serialize(uint8_t* buffer) const
{
size_t i = 0;
buffer[i++] = opcode >> 8;
buffer[i++] = opcode;
buffer[i++] = static_cast<uint16_t>(opcode) >> 8;
buffer[i++] = static_cast<uint16_t>(opcode);
buffer[i++] = blockNumber >> 8;
buffer[i++] = blockNumber;
return i;
@ -272,7 +276,22 @@ size_t TftpAcknowledgementPacket::Serialize(uint8_t* buffer) const
//
// TftpDataPacket
//
TftpDataPacket::TftpDataPacket() : opcode(TFTP_OP_DATA) {}
TftpDataPacket::TftpDataPacket() : TftpPacket(Opcode::Data), blockNumber(0)
{}
size_t TftpDataPacket::Serialize(uint8_t* buffer) const
{
size_t i = 0;
buffer[i++] = static_cast<uint16_t>(opcode) >> 8;
buffer[i++] = static_cast<uint16_t>(opcode);
buffer[i++] = blockNumber >> 8;
buffer[i++] = blockNumber;
std::memcpy(buffer + i, data.data(), data.size());
i += data.size();
return i;
}
size_t TftpDataPacket::Deserialize(
TftpDataPacket& out, const uint8_t* buffer, size_t size
@ -281,8 +300,9 @@ size_t TftpDataPacket::Deserialize(
return 0;
}
out.opcode = buffer[0] << 8 | buffer[1];
out.opcode = static_cast<Opcode>(buffer[0] << 8 | buffer[1]);
out.blockNumber = buffer[2] << 8 | buffer[3];
out.data = std::vector<uint8_t>(buffer + 4, buffer + size);
return size;
}
}; // namespace Net::Tftp

View file

@ -1,22 +1,23 @@
#pragma once
#include <vector>
namespace Net::Tftp {
const size_t TFTP_BLOCK_SIZE = 512;
enum TftpOperation
enum class Opcode : uint16_t
{
TFTP_OP_READ_REQUEST = 1,
TFTP_OP_WRITE_REQUEST = 2,
TFTP_OP_DATA = 3,
TFTP_OP_ACKNOWLEDGEMENT = 4,
TFTP_OP_ERROR = 5,
ReadRequest = 1,
WriteRequest = 2,
Data = 3,
Acknowledgement = 4,
Error = 5,
};
struct TftpPacket
{
uint16_t opcode;
Opcode opcode;
TftpPacket(uint16_t opcode) : opcode(opcode) {}
TftpPacket(Opcode opcode) : opcode(opcode) {}
virtual size_t SerializedLength() const {
return sizeof(opcode);
@ -30,7 +31,7 @@ struct TftpWriteReadRequestPacket : public TftpPacket
std::string filename;
std::string mode;
TftpWriteReadRequestPacket(uint16_t opcode);
TftpWriteReadRequestPacket(const Opcode opcode);
size_t SerializedLength() const override;
size_t Serialize(uint8_t* buffer) const override;
static TftpWriteReadRequestPacket Deserialize(const uint8_t* buffer);
@ -57,13 +58,21 @@ struct TftpAcknowledgementPacket : public TftpPacket
size_t Serialize(uint8_t* buffer) const override;
};
struct TftpDataPacket
struct TftpDataPacket : public TftpPacket
{
uint16_t opcode;
uint16_t blockNumber;
std::vector<uint8_t> data;
TftpDataPacket();
size_t Serialize(uint8_t* buffer) const override;
static size_t Deserialize(
TftpDataPacket& out, const uint8_t* buffer, size_t length);
};
void HandleTftpDatagram(
const EthernetFrameHeader ethernetReqHeader,
const Ipv4Header ipv4ReqHeader,
const UdpDatagramHeader udpReqHeader,
const uint8_t* buffer
);
}; // namespace Net::Tftp

View file

@ -7,79 +7,13 @@
#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>
//
// ARP
//
void SendArpPacket(
ArpOperation operation,
MacAddress targetMac,
MacAddress senderMac,
uint32_t targetIp,
uint32_t senderIp)
{
Ipv4ArpPacket arpPacket(operation);
arpPacket.targetMac = targetMac;
arpPacket.senderMac = senderMac;
arpPacket.targetIp = targetIp;
arpPacket.senderIp = senderIp;
EthernetFrameHeader ethernetHeader(senderMac, targetMac, ETHERTYPE_ARP);
uint8_t buffer[USPI_FRAME_BUFFER_SIZE];
size_t size = 0;
size += ethernetHeader.Serialize(buffer + size);
size += arpPacket.Serialize(buffer + size);
USPiSendFrame(buffer, size);
}
void SendArpRequest(
MacAddress targetMac, MacAddress senderMac, uint32_t targetIp, uint32_t senderIp)
{
SendArpPacket(ARP_OPERATION_REQUEST, targetMac, senderMac, targetIp, senderIp);
}
void SendArpReply(
MacAddress targetMac, MacAddress senderMac, uint32_t targetIp, uint32_t senderIp)
{
SendArpPacket(ARP_OPERATION_REPLY, targetMac, senderMac, targetIp, senderIp);
}
void SendArpAnnouncement(MacAddress mac, uint32_t ip)
{
SendArpReply(MacBroadcast, mac, ip, ip);
}
void HandleArpFrame(const EthernetFrameHeader ethernetHeader, uint8_t* buffer)
{
const auto macAddress = GetMacAddress();
const auto arpPacket = Ipv4ArpPacket::Deserialize(buffer);
if (
arpPacket.hardwareType == 1 &&
arpPacket.protocolType == ETHERTYPE_IPV4 &&
arpPacket.operation == ARP_OPERATION_REQUEST &&
arpPacket.targetIp == Ipv4Address)
{
SendArpReply(arpPacket.senderMac, macAddress, arpPacket.senderIp, Ipv4Address);
}
else if (
arpPacket.hardwareType == 1 &&
arpPacket.protocolType == ETHERTYPE_IPV4 &&
arpPacket.operation == ARP_OPERATION_REPLY &&
arpPacket.targetIp == Ipv4Address &&
arpPacket.targetMac == macAddress)
{
ArpTable.insert(std::make_pair(arpPacket.senderIp, arpPacket.senderMac));
}
}
//
// IPv4
//
@ -90,7 +24,8 @@ void HandleIpv4Packet(
const auto offset = Ipv4Header::SerializedLength();
// Update ARP table
ArpTable.insert(std::make_pair(ipv4Header.sourceIp, ethernetHeader.macSource));
Net::Arp::ArpTable.insert(
std::make_pair(ipv4Header.sourceIp, ethernetHeader.macSource));
if (ipv4Header.version != 4) return;
if (ipv4Header.ihl != 5) return; // Not supported
@ -128,7 +63,7 @@ void HandleUdpDatagram(
}
else if (udpHeader.destinationPort == UDP_PORT_TFTP)
{
HandleTftpDatagram(
Net::Tftp::HandleTftpDatagram(
ethernetHeader,
ipv4Header,
udpHeader,
@ -326,4 +261,3 @@ uint32_t Ipv4Address = 0xC0A80164;
const MacAddress MacBroadcast{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
bool FileUploaded = false;
std::unordered_map<std::uint32_t, MacAddress> ArpTable;

View file

@ -27,23 +27,6 @@ struct EthernetFrameHeader;
struct UdpDatagramHeader;
struct Ipv4Header;
//
// ARP
//
void HandleArpFrame(EthernetFrameHeader header, uint8_t* buffer);
void SendArpPacket(
ArpOperation operation,
MacAddress targetMac,
MacAddress senderMac,
uint32_t senderIp,
uint32_t targetIp
);
void SendArpRequest(
MacAddress targetMac, MacAddress senderMac, uint32_t senderIp, uint32_t targetIp);
void SendArpReply(
MacAddress targetMac, MacAddress senderMac, uint32_t senderIp, uint32_t targetIp);
void SendArpAnnouncement(MacAddress mac, uint32_t ip);
//
// IPv4
//
@ -60,13 +43,6 @@ void HandleUdpDatagram(
const size_t size
);
void HandleTftpDatagram(
const EthernetFrameHeader ethernetReqHeader,
const Ipv4Header ipv4ReqHeader,
const UdpDatagramHeader udpReqHeader,
const uint8_t* buffer
);
//
// ICMP
//
@ -84,4 +60,3 @@ extern const MacAddress MacBroadcast;
extern uint32_t Ipv4Address;
extern bool FileUploaded;
extern std::unordered_map<std::uint32_t, MacAddress> ArpTable;