Move a lot of the network logic to net.cpp
This commit is contained in:
parent
cff82bbad3
commit
18c5bbd29d
6 changed files with 196 additions and 86 deletions
84
src/main.cpp
84
src/main.cpp
|
@ -1943,7 +1943,6 @@ extern "C"
|
|||
|
||||
const auto ipAddress = 0x0A00000B;
|
||||
uint8_t ipBuffer[USPI_FRAME_BUFFER_SIZE];
|
||||
std::unordered_map<std::uint32_t, std::array<std::uint8_t, 6>> arpTable;
|
||||
|
||||
if (USPiEthernetAvailable()) {
|
||||
std::array<std::uint8_t, 6> 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<decltype(arp)> 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<int> ping(value);
|
||||
IcmpPacket<decltype(ping)> icmp(8, 0, ping);
|
||||
Ipv4Packet<decltype(icmp)> ip(1, ipAddress, targetIp, icmp);
|
||||
|
||||
EthernetFrame<decltype(ip)> 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<decltype(arp)> 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<Ipv4ArpPacket>::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<decltype(arpReply)> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ struct EthernetFrame
|
|||
buffer[i++] = 0;
|
||||
}
|
||||
|
||||
crc = crc32(buffer, i);
|
||||
crc = Crc32(buffer, i);
|
||||
|
||||
buffer[i++] = crc;
|
||||
buffer[i++] = crc >> 8;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
118
src/net.cpp
118
src/net.cpp
|
@ -1,5 +1,102 @@
|
|||
#include "net.h"
|
||||
#include <unordered_map>
|
||||
#include "net-ethernet.h"
|
||||
#include "net-ipv4.h"
|
||||
#include "net-arp.h"
|
||||
#include "net-icmp.h"
|
||||
|
||||
#include "types.h"
|
||||
#include <uspi.h>
|
||||
|
||||
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<decltype(arp)> 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<Ipv4ArpPacket>::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<int> pingPacket(0);
|
||||
IcmpPacket<decltype(pingPacket)> icmpPacket(8, 0, pingPacket);
|
||||
Ipv4Packet<decltype(icmpPacket)> ipv4Packet(1, Ipv4Address, ip, icmpPacket);
|
||||
|
||||
EthernetFrame<decltype(ipv4Packet)> 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<std::uint32_t, MacAddress> ArpTable;
|
||||
|
|
72
src/net.h
72
src/net.h
|
@ -3,6 +3,7 @@
|
|||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
enum EtherType {
|
||||
ETHERTYPE_IPV4 = 0x0800,
|
||||
|
@ -16,8 +17,31 @@ enum ArpOperation {
|
|||
|
||||
typedef std::array<std::uint8_t, 6> 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<std::uint32_t, MacAddress> 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 <class T>
|
||||
struct UdpDatagram
|
||||
{
|
||||
UdpDatagramHeader header;
|
||||
T payload;
|
||||
|
||||
UdpDatagram() {}
|
||||
|
||||
UdpDatagram(uint16_t sourcePort, uint16_t destinationPort, T payload) :
|
||||
header(sourcePort, destinationPort, sizeof(UdpDatagram<T>)),
|
||||
payload(payload)
|
||||
{}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue