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
86
src/main.cpp
86
src/main.cpp
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
@ -1943,7 +1943,6 @@ extern "C"
|
||||||
|
|
||||||
const auto ipAddress = 0x0A00000B;
|
const auto ipAddress = 0x0A00000B;
|
||||||
uint8_t ipBuffer[USPI_FRAME_BUFFER_SIZE];
|
uint8_t ipBuffer[USPI_FRAME_BUFFER_SIZE];
|
||||||
std::unordered_map<std::uint32_t, std::array<std::uint8_t, 6>> arpTable;
|
|
||||||
|
|
||||||
if (USPiEthernetAvailable()) {
|
if (USPiEthernetAvailable()) {
|
||||||
std::array<std::uint8_t, 6> macAddress;
|
std::array<std::uint8_t, 6> macAddress;
|
||||||
|
@ -1952,24 +1951,8 @@ extern "C"
|
||||||
snprintf(tempBuffer, tempBufferSize, "Ethernet found");
|
snprintf(tempBuffer, tempBufferSize, "Ethernet found");
|
||||||
screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
||||||
|
|
||||||
|
|
||||||
// Send an ARP announcement
|
// Send an ARP announcement
|
||||||
{
|
SendArpAnnouncement(macAddress, ipAddress);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -1977,41 +1960,17 @@ extern "C"
|
||||||
if (!USPiReceiveFrame(ipBuffer, &size))
|
if (!USPiReceiveFrame(ipBuffer, &size))
|
||||||
{
|
{
|
||||||
const auto targetIp = 0x0A00000A;
|
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;
|
const auto targetMac = targetMacIter->second;
|
||||||
|
SendIcmpEchoRequest(targetMac, targetIp);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Send ARP request
|
// Send an ARP request to find the MAC address belonging to this IP.
|
||||||
Ipv4ArpPacket arp(ARP_OPERATION_REQUEST);
|
SendArpRequest(MacBroadcast, macAddress, targetIp, ipAddress);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MsDelay(1000);
|
MsDelay(1000);
|
||||||
|
@ -2030,36 +1989,7 @@ extern "C"
|
||||||
|
|
||||||
if (header.type == ETHERTYPE_ARP)
|
if (header.type == ETHERTYPE_ARP)
|
||||||
{
|
{
|
||||||
auto frame = EthernetFrame<Ipv4ArpPacket>::Deserialize(ipBuffer);
|
HandleArpFrame(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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ struct EthernetFrame
|
||||||
buffer[i++] = 0;
|
buffer[i++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
crc = crc32(buffer, i);
|
crc = Crc32(buffer, i);
|
||||||
|
|
||||||
buffer[i++] = crc;
|
buffer[i++] = crc;
|
||||||
buffer[i++] = crc >> 8;
|
buffer[i++] = crc >> 8;
|
||||||
|
|
|
@ -42,7 +42,7 @@ struct IcmpPacket
|
||||||
i += header.Serialize(buffer);
|
i += header.Serialize(buffer);
|
||||||
i += payload.Serialize(buffer + i);
|
i += payload.Serialize(buffer + i);
|
||||||
|
|
||||||
uint16_t checksum = internetChecksum(buffer, i);
|
uint16_t checksum = InternetChecksum(buffer, i);
|
||||||
buffer[2] = checksum;
|
buffer[2] = checksum;
|
||||||
buffer[3] = checksum >> 8;
|
buffer[3] = checksum >> 8;
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ struct Ipv4Header
|
||||||
buffer[i++] = destinationIp >> 8;
|
buffer[i++] = destinationIp >> 8;
|
||||||
buffer[i++] = destinationIp;
|
buffer[i++] = destinationIp;
|
||||||
|
|
||||||
headerChecksum = internetChecksum(buffer, i);
|
headerChecksum = InternetChecksum(buffer, i);
|
||||||
buffer[10] = headerChecksum;
|
buffer[10] = headerChecksum;
|
||||||
buffer[11] = headerChecksum >> 8;
|
buffer[11] = headerChecksum >> 8;
|
||||||
|
|
||||||
|
|
118
src/net.cpp
118
src/net.cpp
|
@ -1,5 +1,102 @@
|
||||||
#include "net.h"
|
#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
|
// Helpers
|
||||||
|
@ -71,7 +168,7 @@ static const std::uint32_t crcTab32[256] = {
|
||||||
0xB40BBE37ul, 0xC30C8EA1ul, 0x5A05DF1Bul, 0x2D02EF8Dul
|
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;
|
std::uint32_t crc = 0xFFFFFFFFul;
|
||||||
|
|
||||||
for (std::size_t a = 0; a < size; a++)
|
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;
|
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;
|
std::uint32_t sum = 0;
|
||||||
while (size > 1) {
|
while (size > 1) {
|
||||||
|
@ -103,3 +200,18 @@ std::uint16_t internetChecksum(const void* data, std::size_t size)
|
||||||
|
|
||||||
return ~sum;
|
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 <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
enum EtherType {
|
enum EtherType {
|
||||||
ETHERTYPE_IPV4 = 0x0800,
|
ETHERTYPE_IPV4 = 0x0800,
|
||||||
|
@ -16,8 +17,31 @@ enum ArpOperation {
|
||||||
|
|
||||||
typedef std::array<std::uint8_t, 6> MacAddress;
|
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
|
struct UdpDatagramHeader
|
||||||
{
|
{
|
||||||
|
@ -25,4 +49,48 @@ struct UdpDatagramHeader
|
||||||
std::uint16_t destinationPort;
|
std::uint16_t destinationPort;
|
||||||
std::uint16_t length;
|
std::uint16_t length;
|
||||||
std::uint16_t checksum;
|
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