From 40ecbd51f6c93185f28fdd7f55245d0ed31f335b Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Mon, 28 Dec 2020 14:41:27 +0100 Subject: [PATCH] Namespace ICMP and IPv4, and enum -> enum class --- Makefile | 2 +- src/main.cpp | 7 +- src/net-arp.cpp | 15 ++-- src/net-arp.h | 2 +- src/net-dhcp.cpp | 24 +++--- src/net-ethernet.cpp | 12 +-- src/net-ethernet.h | 14 ++-- src/net-icmp.cpp | 176 ++++++++++++++++++++++++++++++++----------- src/net-icmp.h | 76 ++++++++++--------- src/net-ipv4.cpp | 169 +++++++++++++++++++++++++---------------- src/net-ipv4.h | 84 ++++++++++++--------- src/net-tftp.cpp | 11 +-- src/net-tftp.h | 2 +- src/net-udp.cpp | 2 +- src/net-udp.h | 2 +- src/net.cpp | 121 ----------------------------- src/net.h | 21 ------ 17 files changed, 368 insertions(+), 372 deletions(-) delete mode 100644 src/net.cpp diff --git a/Makefile b/Makefile index 9b15aa4..88e1e97 100644 --- a/Makefile +++ b/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 \ 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)) diff --git a/src/main.cpp b/src/main.cpp index 7514554..01fc52f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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; } } diff --git a/src/net-arp.cpp b/src/net-arp.cpp index 83a87c4..49ea2d5 100644 --- a/src/net-arp.cpp +++ b/src/net-arp.cpp @@ -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(protocolType) >> 8; + buffer[3] = static_cast(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(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) diff --git a/src/net-arp.h b/src/net-arp.h index 05bbb3d..8dd4b25 100644 --- a/src/net-arp.h +++ b/src/net-arp.h @@ -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; diff --git a/src/net-dhcp.cpp b/src/net-dhcp.cpp index c8d0ba9..b06d1cd 100644 --- a/src/net-dhcp.cpp +++ b/src/net-dhcp.cpp @@ -1,9 +1,12 @@ +#include +#include +#include + #include "net-dhcp.h" #include "net-udp.h" #include "net-ipv4.h" #include "net-ethernet.h" -#include -#include + #include "types.h" #include #include @@ -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; diff --git a/src/net-ethernet.cpp b/src/net-ethernet.cpp index 4c6266f..22084e2 100644 --- a/src/net-ethernet.cpp +++ b/src/net-ethernet.cpp @@ -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(type) >> 8; + buffer[i++] = static_cast(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(buffer[12] << 8 | buffer[13]); return self; } } // namespace Net::Ethernet diff --git a/src/net-ethernet.h b/src/net-ethernet.h index 2f86103..c85a9bb 100644 --- a/src/net-ethernet.h +++ b/src/net-ethernet.h @@ -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() { diff --git a/src/net-icmp.cpp b/src/net-icmp.cpp index d23f2c5..f1be8c7 100644 --- a/src/net-icmp.cpp +++ b/src/net-icmp.cpp @@ -1,54 +1,138 @@ +#include + #include "net-icmp.h" -// -// IcmpPacketHeader -// -IcmpPacketHeader::IcmpPacketHeader() {} +#include "types.h" +#include -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 { - size_t i = 0; - buffer[i++] = type; - buffer[i++] = code; - buffer[i++] = checksum; - buffer[i++] = checksum >> 8; - return i; -} + // + // PacketHeader + // + PacketHeader::PacketHeader() {} -IcmpPacketHeader IcmpPacketHeader::Deserialize(const uint8_t* buffer) -{ - IcmpPacketHeader self; - self.type = buffer[0]; - self.code = buffer[1]; - self.checksum = buffer[2] << 8 | buffer[3]; - return self; -} + PacketHeader::PacketHeader(Type type, uint8_t code) : + type(type), code(code), checksum(0) + {} -// -// IcmpEchoHeader -// -IcmpEchoHeader::IcmpEchoHeader() : IcmpEchoHeader(0, 0) {} -IcmpEchoHeader::IcmpEchoHeader(uint16_t identifier, uint16_t sequenceNumber) : - identifier(identifier), sequenceNumber(sequenceNumber) {} + size_t PacketHeader::Serialize(uint8_t* buffer) const + { + size_t i = 0; + buffer[i++] = static_cast(type); + buffer[i++] = code; + buffer[i++] = checksum; + buffer[i++] = checksum >> 8; + return i; + } -size_t IcmpEchoHeader::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; -} + PacketHeader PacketHeader::Deserialize(const uint8_t* buffer) + { + PacketHeader self; + self.type = static_cast(buffer[0]); + self.code = buffer[1]; + self.checksum = buffer[2] << 8 | buffer[3]; + return self; + } -IcmpEchoHeader IcmpEchoHeader::Deserialize(const uint8_t* buffer) -{ - IcmpEchoHeader self; - self.identifier = buffer[0] << 8 | buffer[1]; - self.sequenceNumber = buffer[2] << 8 | buffer[3]; - return self; -} + // + // EchoHeader + // + EchoHeader::EchoHeader() : EchoHeader(0, 0) {} + EchoHeader::EchoHeader(uint16_t identifier, uint16_t sequenceNumber) : + identifier(identifier), sequenceNumber(sequenceNumber) {} + + 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; + } + + 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 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 diff --git a/src/net-icmp.h b/src/net-icmp.h index c8ecf94..57d5c4e 100644 --- a/src/net-icmp.h +++ b/src/net-icmp.h @@ -1,43 +1,49 @@ #pragma once #include "net.h" -enum IcmpType +namespace Net::Icmp { - ICMP_ECHO_REPLY = 0, - ICMP_ECHO_REQUEST = 8, -}; - -struct IcmpPacketHeader -{ - std::uint8_t type; - std::uint8_t code; - std::uint16_t checksum; - - IcmpPacketHeader(); - IcmpPacketHeader(std::uint8_t type, std::uint8_t code); - - constexpr static std::size_t SerializedLength() + enum class Type : uint8_t { - return sizeof(type) + sizeof(code) + sizeof(checksum); - } + EchoReply = 0, + EchoRequest = 8, + }; - std::size_t Serialize(uint8_t* buffer) const; - static IcmpPacketHeader Deserialize(const uint8_t* buffer); -}; - -struct IcmpEchoHeader -{ - uint16_t identifier; - uint16_t sequenceNumber; - - IcmpEchoHeader(); - IcmpEchoHeader(uint16_t identifier, uint16_t sequenceNumber); - - constexpr static size_t SerializedLength() + struct PacketHeader { - return sizeof(identifier) + sizeof(sequenceNumber); - } + Type type; + uint8_t code; + uint16_t checksum; - size_t Serialize(uint8_t* buffer) const; - static IcmpEchoHeader Deserialize(const uint8_t* buffer); -}; + PacketHeader(); + PacketHeader(Type type, uint8_t code); + + constexpr static size_t SerializedLength() + { + return sizeof(type) + sizeof(code) + sizeof(checksum); + } + + size_t Serialize(uint8_t* buffer) const; + static PacketHeader Deserialize(const uint8_t* buffer); + }; + + struct EchoHeader + { + uint16_t identifier; + uint16_t sequenceNumber; + + EchoHeader(); + EchoHeader(uint16_t identifier, uint16_t sequenceNumber); + + constexpr static size_t SerializedLength() + { + return sizeof(identifier) + sizeof(sequenceNumber); + } + + size_t Serialize(uint8_t* buffer) const; + static EchoHeader Deserialize(const uint8_t* buffer); + }; + + void SendEchoRequest(Utils::MacAddress mac, uint32_t ip); + void HandlePacket(const uint8_t* buffer); +} // namespace Net::Icmp diff --git a/src/net-ipv4.cpp b/src/net-ipv4.cpp index 39752a6..266f442 100644 --- a/src/net-ipv4.cpp +++ b/src/net-ipv4.cpp @@ -1,83 +1,118 @@ #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() {} - -Ipv4Header::Ipv4Header( - uint8_t protocol, uint32_t sourceIp, uint32_t destinationIp, uint16_t totalLength -) : - version(4), - ihl(5), - dscp(0), - ecn(0), - totalLength(totalLength), - identification(0), - flags(0), - fragmentOffset(0), - ttl(64), - protocol(protocol), - headerChecksum(0), - sourceIp(sourceIp), - destinationIp(destinationIp) -{} - -size_t Ipv4Header::Serialize(uint8_t* buffer) const +namespace Net::Ipv4 { - size_t i = 0; + Header::Header() {} - buffer[i++] = version << 4 | ihl; - buffer[i++] = dscp << 2 | ecn; - buffer[i++] = totalLength >> 8; - buffer[i++] = totalLength; - buffer[i++] = identification >> 8; - buffer[i++] = identification; - buffer[i++] = (flags << 13 | fragmentOffset) >> 8; - buffer[i++] = flags << 13 | fragmentOffset; - buffer[i++] = ttl; - buffer[i++] = protocol; + Header::Header( + Protocol protocol, uint32_t sourceIp, uint32_t destinationIp, uint16_t totalLength + ) : + version(4), + ihl(5), + dscp(0), + ecn(0), + totalLength(totalLength), + identification(0), + flags(0), + fragmentOffset(0), + ttl(64), + protocol(protocol), + headerChecksum(0), + sourceIp(sourceIp), + destinationIp(destinationIp) + {} - // Zero the checksum before calculating it - buffer[i++] = 0; - buffer[i++] = 0 >> 8; + size_t Header::Serialize(uint8_t* buffer) const + { + size_t i = 0; - buffer[i++] = sourceIp >> 24; - buffer[i++] = sourceIp >> 16; - buffer[i++] = sourceIp >> 8; - buffer[i++] = sourceIp; - buffer[i++] = destinationIp >> 24; - buffer[i++] = destinationIp >> 16; - buffer[i++] = destinationIp >> 8; - buffer[i++] = destinationIp; + buffer[i++] = version << 4 | ihl; + buffer[i++] = dscp << 2 | ecn; + buffer[i++] = totalLength >> 8; + buffer[i++] = totalLength; + buffer[i++] = identification >> 8; + buffer[i++] = identification; + buffer[i++] = (flags << 13 | fragmentOffset) >> 8; + buffer[i++] = flags << 13 | fragmentOffset; + buffer[i++] = ttl; + buffer[i++] = static_cast(protocol); - uint16_t checksum = Net::Utils::InternetChecksum(buffer, i); - buffer[10] = checksum; - buffer[11] = checksum >> 8; + // Zero the checksum before calculating it + buffer[i++] = 0; + buffer[i++] = 0 >> 8; - return i; -} + buffer[i++] = sourceIp >> 24; + buffer[i++] = sourceIp >> 16; + buffer[i++] = sourceIp >> 8; + buffer[i++] = sourceIp; + buffer[i++] = destinationIp >> 24; + buffer[i++] = destinationIp >> 16; + buffer[i++] = destinationIp >> 8; + buffer[i++] = destinationIp; -Ipv4Header Ipv4Header::Deserialize(const uint8_t* buffer) -{ - Ipv4Header self; - self.version = buffer[0] >> 4; - self.ihl = buffer[0] & 0x0F; + uint16_t checksum = Net::Utils::InternetChecksum(buffer, i); + buffer[10] = checksum; + buffer[11] = checksum >> 8; - self.dscp = buffer[1] >> 2; - self.ecn = buffer[1] & 0x03; + return i; + } - self.totalLength = buffer[2] << 8 | buffer[3]; - self.identification = buffer[4] << 8 | buffer[5]; + Header Header::Deserialize(const uint8_t* buffer) + { + Header self; + self.version = buffer[0] >> 4; + self.ihl = buffer[0] & 0x0F; - self.flags = buffer[6] >> 5; - self.fragmentOffset = (buffer[6] & 0x1F) << 8 | buffer[7]; + self.dscp = buffer[1] >> 2; + self.ecn = buffer[1] & 0x03; - self.ttl = buffer[8]; - self.protocol = buffer[9]; - self.headerChecksum = buffer[10] << 8 | buffer[11]; + self.totalLength = buffer[2] << 8 | buffer[3]; + self.identification = buffer[4] << 8 | buffer[5]; - self.sourceIp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15]; - self.destinationIp = - buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19]; + self.flags = buffer[6] >> 5; + self.fragmentOffset = (buffer[6] & 0x1F) << 8 | buffer[7]; - return self; -} + self.ttl = buffer[8]; + self.protocol = static_cast(buffer[9]); + self.headerChecksum = buffer[10] << 8 | buffer[11]; + + self.sourceIp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15]; + self.destinationIp = + 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 diff --git a/src/net-ipv4.h b/src/net-ipv4.h index 5733a5c..2089b82 100644 --- a/src/net-ipv4.h +++ b/src/net-ipv4.h @@ -1,44 +1,54 @@ #pragma once #include #include +#include "net-ethernet.h" -enum IpProtocols +namespace Net::Ipv4 { - IP_PROTO_ICMP = 1, - IP_PROTO_TCP = 6, - IP_PROTO_UDP = 17, -}; - -struct Ipv4Header -{ - uint8_t version; - uint8_t ihl; - uint8_t dscp; - uint8_t ecn; - uint16_t totalLength; - uint16_t identification; - uint8_t flags; - uint16_t fragmentOffset; - uint8_t ttl; - uint8_t protocol; - uint16_t headerChecksum; - uint32_t sourceIp; - uint32_t destinationIp; - - Ipv4Header(); - Ipv4Header( - uint8_t protocol, - uint32_t sourceIp, - uint32_t destinationIp, - uint16_t totalLength - ); - - static constexpr size_t SerializedLength() + enum class Protocol : uint8_t { - // Hardcoded because of bitfields. - return 20; - } + Icmp = 1, + Tcp = 6, + Udp = 17, + }; - size_t Serialize(uint8_t* buffer) const; - static Ipv4Header Deserialize(const uint8_t* buffer); -}; + struct Header + { + uint8_t version; + uint8_t ihl; + uint8_t dscp; + uint8_t ecn; + uint16_t totalLength; + uint16_t identification; + uint8_t flags; + uint16_t fragmentOffset; + uint8_t ttl; + Protocol protocol; + uint16_t headerChecksum; + uint32_t sourceIp; + uint32_t destinationIp; + + Header(); + Header( + Protocol protocol, + uint32_t sourceIp, + uint32_t destinationIp, + uint16_t totalLength + ); + + static constexpr size_t SerializedLength() + { + // Hardcoded because of bitfields. + return 20; + } + + size_t Serialize(uint8_t* buffer) const; + static Header Deserialize(const uint8_t* buffer); + }; + + void HandlePacket( + const Ethernet::Header& ethernetHeader, + const uint8_t* buffer, + const size_t size + ); +} // namespace Net::Ipv4 diff --git a/src/net-tftp.cpp b/src/net-tftp.cpp index d097f92..4e24971 100644 --- a/src/net-tftp.cpp +++ b/src/net-tftp.cpp @@ -1,4 +1,5 @@ #include +#include #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; diff --git a/src/net-tftp.h b/src/net-tftp.h index 1f48f9d..f1a8682 100644 --- a/src/net-tftp.h +++ b/src/net-tftp.h @@ -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 ); diff --git a/src/net-udp.cpp b/src/net-udp.cpp index 3b47d03..777ac5b 100644 --- a/src/net-udp.cpp +++ b/src/net-udp.cpp @@ -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 ) { diff --git a/src/net-udp.h b/src/net-udp.h index 42337bf..b0941c4 100644 --- a/src/net-udp.h +++ b/src/net-udp.h @@ -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 ); diff --git a/src/net.cpp b/src/net.cpp deleted file mode 100644 index 8c33a20..0000000 --- a/src/net.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include - -#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 -#include - -// -// 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 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); - } -} diff --git a/src/net.h b/src/net.h index f7559ef..321b87d 100644 --- a/src/net.h +++ b/src/net.h @@ -1,26 +1,5 @@ #pragma once -#include -#include -#include -#include -#include - #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);