From 18c5bbd29d0e963b51b5b31bb0f3f24bb80e5167 Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Fri, 11 Dec 2020 01:09:29 +0100 Subject: [PATCH] Move a lot of the network logic to net.cpp --- src/main.cpp | 86 +++------------------------------ src/net-ethernet.h | 2 +- src/net-icmp.h | 2 +- src/net-ipv4.h | 2 +- src/net.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++-- src/net.h | 72 ++++++++++++++++++++++++++- 6 files changed, 196 insertions(+), 86 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a7fe109..e3f9375 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include "defs.h" @@ -1943,7 +1943,6 @@ extern "C" const auto ipAddress = 0x0A00000B; uint8_t ipBuffer[USPI_FRAME_BUFFER_SIZE]; - std::unordered_map> arpTable; if (USPiEthernetAvailable()) { std::array macAddress; @@ -1952,24 +1951,8 @@ extern "C" snprintf(tempBuffer, tempBufferSize, "Ethernet found"); screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); - // Send an ARP announcement - { - Ipv4ArpPacket arp(ARP_OPERATION_REPLY); - - arp.senderMac = macAddress; - arp.senderIp = ipAddress; - - arp.targetMac.fill(0); - arp.targetIp = ipAddress; - - EthernetFrame frame(ETHERTYPE_ARP, arp); - frame.header.macDestination.fill(0xFF); // Broadcast - frame.header.macSource = macAddress; - - size_t size = frame.Serialize(ipBuffer); - USPiSendFrame(ipBuffer, size); - } + SendArpAnnouncement(macAddress, ipAddress); while (true) { @@ -1977,41 +1960,17 @@ extern "C" if (!USPiReceiveFrame(ipBuffer, &size)) { const auto targetIp = 0x0A00000A; - const auto targetMacIter = arpTable.find(targetIp); + const auto targetMacIter = ArpTable.find(targetIp); - if (targetMacIter != arpTable.end()) + if (targetMacIter != ArpTable.end()) { const auto targetMac = targetMacIter->second; - - int value = 1337; - IcmpEchoRequest ping(value); - IcmpPacket icmp(8, 0, ping); - Ipv4Packet ip(1, ipAddress, targetIp, icmp); - - EthernetFrame frame(ETHERTYPE_IPV4, ip); - frame.header.macDestination = targetMac; - frame.header.macSource = macAddress; - - size_t size = frame.Serialize(ipBuffer); - USPiSendFrame(ipBuffer, size); + SendIcmpEchoRequest(targetMac, targetIp); } else { - // Send ARP request - Ipv4ArpPacket arp(ARP_OPERATION_REQUEST); - - arp.senderMac = macAddress; - arp.senderIp = ipAddress; - - arp.targetMac.fill(0); - arp.targetIp = 0x0A00000A; - - EthernetFrame frame(ETHERTYPE_ARP, arp); - frame.header.macDestination.fill(0xFF); // Broadcast - frame.header.macSource = macAddress; - - size_t size = frame.Serialize(ipBuffer); - USPiSendFrame(ipBuffer, size); + // Send an ARP request to find the MAC address belonging to this IP. + SendArpRequest(MacBroadcast, macAddress, targetIp, ipAddress); } MsDelay(1000); @@ -2030,36 +1989,7 @@ extern "C" if (header.type == ETHERTYPE_ARP) { - auto frame = EthernetFrame::Deserialize(ipBuffer); - const auto arp = frame.payload; - - if (arp.hardwareType == 1 && - arp.protocolType == ETHERTYPE_IPV4 && - arp.operation == ARP_OPERATION_REQUEST && - arp.targetIp == ipAddress) - { - Ipv4ArpPacket arpReply(ARP_OPERATION_REPLY); - - arpReply.targetMac = arp.senderMac; - arpReply.senderMac = macAddress; - - arpReply.targetIp = arp.senderIp; - arpReply.senderIp = ipAddress; - - EthernetFrame frame(ETHERTYPE_ARP, arpReply); - frame.header.macSource = macAddress; - - size_t size = frame.Serialize(ipBuffer); - USPiSendFrame(ipBuffer, size); - } - else if (arp.hardwareType == 1 && - arp.protocolType == ETHERTYPE_IPV4 && - arp.operation == ARP_OPERATION_REPLY && - arp.targetIp == ipAddress && - arp.targetMac == macAddress) - { - arpTable.insert(std::make_pair(arp.senderIp, arp.senderMac)); - } + HandleArpFrame(ipBuffer); } } } diff --git a/src/net-ethernet.h b/src/net-ethernet.h index 8a19874..c950597 100644 --- a/src/net-ethernet.h +++ b/src/net-ethernet.h @@ -69,7 +69,7 @@ struct EthernetFrame buffer[i++] = 0; } - crc = crc32(buffer, i); + crc = Crc32(buffer, i); buffer[i++] = crc; buffer[i++] = crc >> 8; diff --git a/src/net-icmp.h b/src/net-icmp.h index d42f28d..4308d1a 100644 --- a/src/net-icmp.h +++ b/src/net-icmp.h @@ -42,7 +42,7 @@ struct IcmpPacket i += header.Serialize(buffer); i += payload.Serialize(buffer + i); - uint16_t checksum = internetChecksum(buffer, i); + uint16_t checksum = InternetChecksum(buffer, i); buffer[2] = checksum; buffer[3] = checksum >> 8; diff --git a/src/net-ipv4.h b/src/net-ipv4.h index 7d11518..d93b53e 100644 --- a/src/net-ipv4.h +++ b/src/net-ipv4.h @@ -64,7 +64,7 @@ struct Ipv4Header buffer[i++] = destinationIp >> 8; buffer[i++] = destinationIp; - headerChecksum = internetChecksum(buffer, i); + headerChecksum = InternetChecksum(buffer, i); buffer[10] = headerChecksum; buffer[11] = headerChecksum >> 8; diff --git a/src/net.cpp b/src/net.cpp index ec0583c..d126479 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1,5 +1,102 @@ #include "net.h" -#include +#include "net-ethernet.h" +#include "net-ipv4.h" +#include "net-arp.h" +#include "net-icmp.h" + +#include "types.h" +#include + +const uint32_t Ipv4Address = 0x0A00000B; + +// +// ARP +// +void SendArpPacket(ArpOperation operation, + MacAddress targetMac, + MacAddress senderMac, + uint32_t targetIp, + uint32_t senderIp) +{ + Ipv4ArpPacket arp(operation); + arp.targetMac = targetMac; + arp.senderMac = senderMac; + arp.targetIp = targetIp; + arp.senderIp = senderIp; + + EthernetFrame frame(ETHERTYPE_ARP, arp); + frame.header.macDestination = targetMac; + frame.header.macSource = senderMac; + + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + const auto size = frame.Serialize(buffer); + 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(uint8_t* buffer) +{ + const auto macAddress = GetMacAddress(); + const auto ipAddress = 0x0A00000B; + + const auto frame = EthernetFrame::Deserialize(buffer); + const auto arp = frame.payload; + + if (arp.hardwareType == 1 && + arp.protocolType == ETHERTYPE_IPV4 && + arp.operation == ARP_OPERATION_REQUEST && + arp.targetIp == ipAddress) + { + SendArpReply(arp.senderMac, macAddress, arp.senderIp, ipAddress); + } + else if (arp.hardwareType == 1 && + arp.protocolType == ETHERTYPE_IPV4 && + arp.operation == ARP_OPERATION_REPLY && + arp.targetIp == ipAddress && + arp.targetMac == macAddress) + { + ArpTable.insert(std::make_pair(arp.senderIp, arp.senderMac)); + } +} + + +// +// ICMP +// +void SendIcmpEchoRequest(MacAddress mac, uint32_t ip) +{ + IcmpEchoRequest pingPacket(0); + IcmpPacket icmpPacket(8, 0, pingPacket); + Ipv4Packet ipv4Packet(1, Ipv4Address, ip, icmpPacket); + + EthernetFrame frame(ETHERTYPE_IPV4, ipv4Packet); + frame.header.macDestination = mac; + frame.header.macSource = GetMacAddress(); + + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + size_t size = frame.Serialize(buffer); + USPiSendFrame(buffer, size); +} // // Helpers @@ -71,7 +168,7 @@ static const std::uint32_t crcTab32[256] = { 0xB40BBE37ul, 0xC30C8EA1ul, 0x5A05DF1Bul, 0x2D02EF8Dul }; -std::uint32_t crc32(const std::uint8_t *buffer, std::size_t size) { +std::uint32_t Crc32(const std::uint8_t *buffer, std::size_t size) { std::uint32_t crc = 0xFFFFFFFFul; for (std::size_t a = 0; a < size; a++) @@ -83,7 +180,7 @@ std::uint32_t crc32(const std::uint8_t *buffer, std::size_t size) { return crc ^ 0xFFFFFFFFul; } -std::uint16_t internetChecksum(const void* data, std::size_t size) +std::uint16_t InternetChecksum(const void* data, std::size_t size) { std::uint32_t sum = 0; while (size > 1) { @@ -103,3 +200,18 @@ std::uint16_t internetChecksum(const void* data, std::size_t size) return ~sum; } + +MacAddress GetMacAddress() +{ + static MacAddress macAddress{0}; + + if (macAddress == MacAddress{0}) + { + USPiGetMACAddress(macAddress.data()); + } + + return macAddress; +} + +MacAddress MacBroadcast{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +std::unordered_map ArpTable; diff --git a/src/net.h b/src/net.h index 3b506a0..061618f 100644 --- a/src/net.h +++ b/src/net.h @@ -3,6 +3,7 @@ #include #include #include +#include enum EtherType { ETHERTYPE_IPV4 = 0x0800, @@ -16,8 +17,31 @@ enum ArpOperation { typedef std::array MacAddress; -std::uint32_t crc32(const std::uint8_t* buffer, std::size_t size); -std::uint16_t internetChecksum(const void* data, std::size_t size); + +void HandleArpFrame(std::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); + +void SendIcmpEchoRequest(MacAddress mac, uint32_t ip); + +std::uint32_t Crc32(const std::uint8_t* buffer, std::size_t size); +std::uint16_t InternetChecksum(const void* data, std::size_t size); +MacAddress GetMacAddress(); + +extern MacAddress MacBroadcast; +extern std::unordered_map ArpTable; struct UdpDatagramHeader { @@ -25,4 +49,48 @@ struct UdpDatagramHeader std::uint16_t destinationPort; std::uint16_t length; std::uint16_t checksum; + + UdpDatagramHeader() {} + + UdpDatagramHeader(uint16_t sourcePort, uint16_t destinationPort, uint16_t length) : + sourcePort(sourcePort), destinationPort(destinationPort), length(length) + {} + + size_t Serialize(uint8_t* buffer) + { + size_t i = 0; + buffer[i++] = sourcePort >> 8; + buffer[i++] = sourcePort; + buffer[i++] = destinationPort >> 8; + buffer[i++] = destinationPort; + buffer[i++] = length >> 8; + buffer[i++] = length; + buffer[i++] = checksum >> 8; + buffer[i++] = checksum; + return i; + } + + UdpDatagramHeader Deserialize(const uint8_t* buffer) + { + UdpDatagramHeader self; + self.sourcePort = buffer[0] << 8 | buffer[1]; + self.destinationPort = buffer[2] << 8 | buffer[3]; + self.length = buffer[4] << 8 | buffer[5]; + self.checksum = buffer[6] << 8 | buffer[7]; + return self; + } +}; + +template +struct UdpDatagram +{ + UdpDatagramHeader header; + T payload; + + UdpDatagram() {} + + UdpDatagram(uint16_t sourcePort, uint16_t destinationPort, T payload) : + header(sourcePort, destinationPort, sizeof(UdpDatagram)), + payload(payload) + {} };