From 6e6feee88ce1d8fad0d27ccbb36f9928c887534f Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Mon, 18 Jan 2021 15:56:36 +0100 Subject: [PATCH] Un-nest namespaces, because that's a C++17 feature For some reason gcc doesn't tell us this --- src/net-arp.cpp | 289 ++++++++++---------- src/net-arp.h | 105 ++++---- src/net-dhcp.cpp | 464 ++++++++++++++++---------------- src/net-dhcp.h | 149 ++++++----- src/net-ethernet.cpp | 91 ++++--- src/net-ethernet.h | 53 ++-- src/net-icmp.cpp | 327 ++++++++++++----------- src/net-ipv4.cpp | 299 +++++++++++---------- src/net-ipv4.h | 76 +++--- src/net-tftp.cpp | 618 ++++++++++++++++++++++--------------------- src/net-udp.cpp | 161 +++++------ src/net-udp.h | 62 +++-- src/net-utils.cpp | 173 ++++++------ src/net-utils.h | 19 +- src/net.cpp | 1 - 15 files changed, 1473 insertions(+), 1414 deletions(-) diff --git a/src/net-arp.cpp b/src/net-arp.cpp index 7fabb6d..8ee17e5 100644 --- a/src/net-arp.cpp +++ b/src/net-arp.cpp @@ -8,163 +8,168 @@ #include "types.h" #include -namespace Net::Arp +namespace Net { - Packet::Packet() {} - - Packet::Packet(const uint16_t operation) : - hardwareType(1), // Ethernet - protocolType(Ethernet::EtherType::Ipv4), - hardwareAddressLength(6), - protocolAddressLength(4), - operation(operation) + namespace Arp { - } + Packet::Packet() {} - size_t Packet::Serialize(uint8_t* buffer, const size_t bufferSize) const - { - if (bufferSize < SerializedLength()) + Packet::Packet(const uint16_t operation) : + hardwareType(1), // Ethernet + protocolType(Ethernet::EtherType::Ipv4), + hardwareAddressLength(6), + protocolAddressLength(4), + operation(operation) { - return 0; } - buffer[0] = hardwareType >> 8; - buffer[1] = hardwareType; - buffer[2] = static_cast(protocolType) >> 8; - buffer[3] = static_cast(protocolType); - buffer[4] = hardwareAddressLength; - buffer[5] = protocolAddressLength; - buffer[6] = operation >> 8; - buffer[7] = operation; - - memcpy(buffer + 8, senderMac.data(), 6); - - buffer[14] = senderIp >> 24; - buffer[15] = senderIp >> 16; - buffer[16] = senderIp >> 8; - buffer[17] = senderIp; - - memcpy(buffer + 18, targetMac.data(), 6); - - buffer[24] = targetIp >> 24; - buffer[25] = targetIp >> 16; - buffer[26] = targetIp >> 8; - buffer[27] = targetIp; - - return 28; - } - - // Static - size_t Packet::Deserialize(const uint8_t* buffer, const size_t bufferSize) - { - if (bufferSize < SerializedLength()) + size_t Packet::Serialize(uint8_t* buffer, const size_t bufferSize) const { - return 0; + if (bufferSize < SerializedLength()) + { + return 0; + } + + buffer[0] = hardwareType >> 8; + buffer[1] = hardwareType; + buffer[2] = static_cast(protocolType) >> 8; + buffer[3] = static_cast(protocolType); + buffer[4] = hardwareAddressLength; + buffer[5] = protocolAddressLength; + buffer[6] = operation >> 8; + buffer[7] = operation; + + memcpy(buffer + 8, senderMac.data(), 6); + + buffer[14] = senderIp >> 24; + buffer[15] = senderIp >> 16; + buffer[16] = senderIp >> 8; + buffer[17] = senderIp; + + memcpy(buffer + 18, targetMac.data(), 6); + + buffer[24] = targetIp >> 24; + buffer[25] = targetIp >> 16; + buffer[26] = targetIp >> 8; + buffer[27] = targetIp; + + return 28; } - hardwareType = buffer[0] << 8 | buffer[1]; - protocolType = static_cast(buffer[2] << 8 | buffer[3]); - hardwareAddressLength = buffer[4]; - protocolAddressLength = buffer[5]; - operation = buffer[6] << 8 | buffer[7]; - - memcpy(senderMac.data(), buffer + 8, 6); - senderIp = buffer[14] << 24 | buffer[15] << 16 | buffer[16] << 8 | buffer[17]; - memcpy(targetMac.data(), buffer + 18, 6); - targetIp = buffer[24] << 24 | buffer[25] << 16 | buffer[26] << 8 | buffer[27]; - - return 28; - } - - void SendPacket( - const Operation operation, - const Utils::MacAddress targetMac, - const Utils::MacAddress senderMac, - const uint32_t targetIp, - const uint32_t senderIp) - { - Packet arpPacket(operation); - arpPacket.targetMac = targetMac; - arpPacket.senderMac = senderMac; - arpPacket.targetIp = targetIp; - arpPacket.senderIp = senderIp; - - Ethernet::Header ethernetHeader(targetMac, senderMac, Ethernet::EtherType::Arp); - - uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; - size_t size = 0; - size += ethernetHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += arpPacket.Serialize(buffer + size, sizeof(buffer) - size); - - const auto expectedSize = ethernetHeader.SerializedLength() + arpPacket.SerializedLength(); - assert(size == expectedSize); - assert(size <= sizeof(buffer)); - - USPiSendFrame(buffer, size); - } - - void SendRequest( - const Utils::MacAddress targetMac, - const Utils::MacAddress senderMac, - const uint32_t targetIp, - const uint32_t senderIp) - { - SendPacket(ARP_OPERATION_REQUEST, targetMac, senderMac, targetIp, senderIp); - } - - void SendReply( - const Utils::MacAddress targetMac, - const Utils::MacAddress senderMac, - const uint32_t targetIp, - const uint32_t senderIp) - { - SendPacket(ARP_OPERATION_REPLY, targetMac, senderMac, targetIp, senderIp); - } - - void SendAnnouncement(const Utils::MacAddress mac, const uint32_t ip) - { - SendReply(Utils::MacBroadcast, mac, ip, ip); - } - - void HandlePacket( - const Ethernet::Header ethernetHeader, const uint8_t* buffer, const size_t bufferSize) - { - const auto macAddress = Utils::GetMacAddress(); - - Packet arpPacket; - const auto arpSize = arpPacket.Deserialize(buffer, bufferSize); - if (arpSize == 0) + // Static + size_t Packet::Deserialize(const uint8_t* buffer, const size_t bufferSize) { - DEBUG_LOG( - "Dropped ARP packet (invalid buffer size %u, expected %u)\r\n", - bufferSize, - arpPacket.SerializedLength()); - return; + if (bufferSize < SerializedLength()) + { + return 0; + } + + hardwareType = buffer[0] << 8 | buffer[1]; + protocolType = static_cast(buffer[2] << 8 | buffer[3]); + hardwareAddressLength = buffer[4]; + protocolAddressLength = buffer[5]; + operation = buffer[6] << 8 | buffer[7]; + + memcpy(senderMac.data(), buffer + 8, 6); + senderIp = buffer[14] << 24 | buffer[15] << 16 | buffer[16] << 8 | buffer[17]; + memcpy(targetMac.data(), buffer + 18, 6); + targetIp = buffer[24] << 24 | buffer[25] << 16 | buffer[26] << 8 | buffer[27]; + + return 28; } - if (arpPacket.hardwareType != 1 || arpPacket.protocolType != Ethernet::EtherType::Ipv4 || - arpPacket.targetIp != Utils::Ipv4Address) + void SendPacket( + const Operation operation, + const Utils::MacAddress targetMac, + const Utils::MacAddress senderMac, + const uint32_t targetIp, + const uint32_t senderIp) { - // Might want to disable because of spamminess - DEBUG_LOG("Dropped ARP packet (invalid parameters)\r\n"); - return; + Packet arpPacket(operation); + arpPacket.targetMac = targetMac; + arpPacket.senderMac = senderMac; + arpPacket.targetIp = targetIp; + arpPacket.senderIp = senderIp; + + Ethernet::Header ethernetHeader(targetMac, senderMac, Ethernet::EtherType::Arp); + + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + size_t size = 0; + size += ethernetHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += arpPacket.Serialize(buffer + size, sizeof(buffer) - size); + + const auto expectedSize = + ethernetHeader.SerializedLength() + arpPacket.SerializedLength(); + assert(size == expectedSize); + assert(size <= sizeof(buffer)); + + USPiSendFrame(buffer, size); } - switch (arpPacket.operation) + void SendRequest( + const Utils::MacAddress targetMac, + const Utils::MacAddress senderMac, + const uint32_t targetIp, + const uint32_t senderIp) { - case ARP_OPERATION_REQUEST: - SendReply(arpPacket.senderMac, macAddress, arpPacket.senderIp, Utils::Ipv4Address); - break; - - case ARP_OPERATION_REPLY: - ArpTable.insert(std::make_pair(arpPacket.senderIp, arpPacket.senderMac)); - break; - - default: - DEBUG_LOG("Dropped ARP packet (invalid operation %d)\r\n", arpPacket.operation); - break; + SendPacket(ARP_OPERATION_REQUEST, targetMac, senderMac, targetIp, senderIp); } - } - std::unordered_map ArpTable; -} // namespace Net::Arp + void SendReply( + const Utils::MacAddress targetMac, + const Utils::MacAddress senderMac, + const uint32_t targetIp, + const uint32_t senderIp) + { + SendPacket(ARP_OPERATION_REPLY, targetMac, senderMac, targetIp, senderIp); + } + + void SendAnnouncement(const Utils::MacAddress mac, const uint32_t ip) + { + SendReply(Utils::MacBroadcast, mac, ip, ip); + } + + void HandlePacket( + const Ethernet::Header ethernetHeader, const uint8_t* buffer, const size_t bufferSize) + { + const auto macAddress = Utils::GetMacAddress(); + + Packet arpPacket; + const auto arpSize = arpPacket.Deserialize(buffer, bufferSize); + if (arpSize == 0) + { + DEBUG_LOG( + "Dropped ARP packet (invalid buffer size %u, expected %u)\r\n", + bufferSize, + arpPacket.SerializedLength()); + return; + } + + if (arpPacket.hardwareType != 1 || + arpPacket.protocolType != Ethernet::EtherType::Ipv4 || + arpPacket.targetIp != Utils::Ipv4Address) + { + // Might want to disable because of spamminess + DEBUG_LOG("Dropped ARP packet (invalid parameters)\r\n"); + return; + } + + switch (arpPacket.operation) + { + case ARP_OPERATION_REQUEST: + SendReply(arpPacket.senderMac, macAddress, arpPacket.senderIp, Utils::Ipv4Address); + break; + + case ARP_OPERATION_REPLY: + ArpTable.insert(std::make_pair(arpPacket.senderIp, arpPacket.senderMac)); + break; + + default: + DEBUG_LOG("Dropped ARP packet (invalid operation %d)\r\n", arpPacket.operation); + break; + } + } + + std::unordered_map ArpTable; + } // namespace Arp +} // namespace Net diff --git a/src/net-arp.h b/src/net-arp.h index eb1b1a5..961cc1a 100644 --- a/src/net-arp.h +++ b/src/net-arp.h @@ -4,64 +4,67 @@ #include "net-ethernet.h" #include "net-utils.h" -namespace Net::Arp +namespace Net { - enum Operation + namespace Arp { - ARP_OPERATION_REQUEST = 1, - ARP_OPERATION_REPLY = 2, - }; - - struct Packet - { - uint16_t hardwareType; - Ethernet::EtherType protocolType; - uint8_t hardwareAddressLength; - uint8_t protocolAddressLength; - uint16_t operation; - - Utils::MacAddress senderMac; - uint32_t senderIp; - Utils::MacAddress targetMac; - uint32_t targetIp; - - Packet(); - Packet(const uint16_t operation); - - constexpr static size_t SerializedLength() + enum Operation { - return sizeof(hardwareType) + sizeof(protocolType) + sizeof(hardwareAddressLength) + - sizeof(protocolAddressLength) + sizeof(operation) + sizeof(senderMac) + - sizeof(senderIp) + sizeof(targetMac) + sizeof(targetIp); - } + ARP_OPERATION_REQUEST = 1, + ARP_OPERATION_REPLY = 2, + }; - size_t Serialize(uint8_t* buffer, const size_t bufferSize) const; - size_t Deserialize(const uint8_t* buffer, const size_t bufferSize); - }; + struct Packet + { + uint16_t hardwareType; + Ethernet::EtherType protocolType; + uint8_t hardwareAddressLength; + uint8_t protocolAddressLength; + uint16_t operation; - void - HandlePacket(const Ethernet::Header header, const uint8_t* buffer, const size_t bufferSize); + Utils::MacAddress senderMac; + uint32_t senderIp; + Utils::MacAddress targetMac; + uint32_t targetIp; - void SendPacket( - const Operation operation, - const Utils::MacAddress targetMac, - const Utils::MacAddress senderMac, - const uint32_t targetIp, - const uint32_t senderIp); + Packet(); + Packet(const uint16_t operation); - void SendRequest( - const Utils::MacAddress targetMac, - const Utils::MacAddress senderMac, - const uint32_t targetIp, - const uint32_t senderIp); + constexpr static size_t SerializedLength() + { + return sizeof(hardwareType) + sizeof(protocolType) + sizeof(hardwareAddressLength) + + sizeof(protocolAddressLength) + sizeof(operation) + sizeof(senderMac) + + sizeof(senderIp) + sizeof(targetMac) + sizeof(targetIp); + } - void SendReply( - const Utils::MacAddress targetMac, - const Utils::MacAddress senderMac, - const uint32_t targetIp, - const uint32_t senderIp); + size_t Serialize(uint8_t* buffer, const size_t bufferSize) const; + size_t Deserialize(const uint8_t* buffer, const size_t bufferSize); + }; - void SendAnnouncement(const Utils::MacAddress mac, const uint32_t ip); + void + HandlePacket(const Ethernet::Header header, const uint8_t* buffer, const size_t bufferSize); - extern std::unordered_map ArpTable; -} // namespace Net::Arp + void SendPacket( + const Operation operation, + const Utils::MacAddress targetMac, + const Utils::MacAddress senderMac, + const uint32_t targetIp, + const uint32_t senderIp); + + void SendRequest( + const Utils::MacAddress targetMac, + const Utils::MacAddress senderMac, + const uint32_t targetIp, + const uint32_t senderIp); + + void SendReply( + const Utils::MacAddress targetMac, + const Utils::MacAddress senderMac, + const uint32_t targetIp, + const uint32_t senderIp); + + void SendAnnouncement(const Utils::MacAddress mac, const uint32_t ip); + + extern std::unordered_map ArpTable; + } // namespace Arp +} // namespace Net diff --git a/src/net-dhcp.cpp b/src/net-dhcp.cpp index 06ad1a9..3e00d0e 100644 --- a/src/net-dhcp.cpp +++ b/src/net-dhcp.cpp @@ -11,257 +11,265 @@ #include "types.h" #include -namespace Net::Dhcp +namespace Net { - Header::Header() {} - - Header::Header(Opcode opcode, uint32_t transactionId) : - opcode(opcode), - hardwareAddressType(1), // Ethernet - hops(0), - transactionId(transactionId), - secondsElapsed(0), - flags(0), // TODO assumption - clientIpAddress(0), - yourIpAddress(0), - serverIpAddress(0), - relayIpAddress(0), - clientHardwareAddress{0}, - serverHostname{0}, - bootFile{0}, - magicValue{99, 130, 83, 99} + namespace Dhcp { - const auto mac = Utils::GetMacAddress(); - hardwareAddressLength = mac.size(); - std::memcpy(clientHardwareAddress.data(), mac.data(), mac.size()); - } + Header::Header() {} - size_t Header::Serialize(uint8_t* buffer, const size_t size) const - { - if (size < Header::SerializedLength()) + Header::Header(Opcode opcode, uint32_t transactionId) : + opcode(opcode), + hardwareAddressType(1), // Ethernet + hops(0), + transactionId(transactionId), + secondsElapsed(0), + flags(0), // TODO assumption + clientIpAddress(0), + yourIpAddress(0), + serverIpAddress(0), + relayIpAddress(0), + clientHardwareAddress{0}, + serverHostname{0}, + bootFile{0}, + magicValue{99, 130, 83, 99} { - return 0; + const auto mac = Utils::GetMacAddress(); + hardwareAddressLength = mac.size(); + std::memcpy(clientHardwareAddress.data(), mac.data(), mac.size()); } - size_t i = 0; - buffer[i++] = static_cast(opcode); - buffer[i++] = hardwareAddressType; - buffer[i++] = hardwareAddressLength; - buffer[i++] = hops; - buffer[i++] = transactionId >> 24; - buffer[i++] = transactionId >> 16; - buffer[i++] = transactionId >> 8; - buffer[i++] = transactionId; - buffer[i++] = secondsElapsed >> 8; - buffer[i++] = secondsElapsed; - buffer[i++] = flags >> 8; - buffer[i++] = flags; - buffer[i++] = clientIpAddress >> 24; - buffer[i++] = clientIpAddress >> 16; - buffer[i++] = clientIpAddress >> 8; - buffer[i++] = clientIpAddress; - buffer[i++] = yourIpAddress >> 24; - buffer[i++] = yourIpAddress >> 16; - buffer[i++] = yourIpAddress >> 8; - buffer[i++] = yourIpAddress; - buffer[i++] = relayIpAddress >> 24; - buffer[i++] = relayIpAddress >> 16; - buffer[i++] = relayIpAddress >> 8; - buffer[i++] = relayIpAddress; - - std::memcpy(buffer + i, clientHardwareAddress.data(), clientHardwareAddress.size()); - i += clientHardwareAddress.size(); - - std::memcpy(buffer + i, serverHostname.data(), serverHostname.size()); - i += serverHostname.size(); - - std::memcpy(buffer + i, bootFile.data(), bootFile.size()); - i += bootFile.size(); - - std::memcpy(buffer + i, magicValue.data(), magicValue.size()); - i += magicValue.size(); - - return i; - } - - size_t Header::Deserialize(Header& out, const uint8_t* buffer, const size_t size) - { - if (size < SerializedLength()) + size_t Header::Serialize(uint8_t* buffer, const size_t size) const { - return 0; + if (size < Header::SerializedLength()) + { + return 0; + } + + size_t i = 0; + buffer[i++] = static_cast(opcode); + buffer[i++] = hardwareAddressType; + buffer[i++] = hardwareAddressLength; + buffer[i++] = hops; + buffer[i++] = transactionId >> 24; + buffer[i++] = transactionId >> 16; + buffer[i++] = transactionId >> 8; + buffer[i++] = transactionId; + buffer[i++] = secondsElapsed >> 8; + buffer[i++] = secondsElapsed; + buffer[i++] = flags >> 8; + buffer[i++] = flags; + buffer[i++] = clientIpAddress >> 24; + buffer[i++] = clientIpAddress >> 16; + buffer[i++] = clientIpAddress >> 8; + buffer[i++] = clientIpAddress; + buffer[i++] = yourIpAddress >> 24; + buffer[i++] = yourIpAddress >> 16; + buffer[i++] = yourIpAddress >> 8; + buffer[i++] = yourIpAddress; + buffer[i++] = relayIpAddress >> 24; + buffer[i++] = relayIpAddress >> 16; + buffer[i++] = relayIpAddress >> 8; + buffer[i++] = relayIpAddress; + + std::memcpy(buffer + i, clientHardwareAddress.data(), clientHardwareAddress.size()); + i += clientHardwareAddress.size(); + + std::memcpy(buffer + i, serverHostname.data(), serverHostname.size()); + i += serverHostname.size(); + + std::memcpy(buffer + i, bootFile.data(), bootFile.size()); + i += bootFile.size(); + + std::memcpy(buffer + i, magicValue.data(), magicValue.size()); + i += magicValue.size(); + + return i; } - out.opcode = static_cast(buffer[0]); - out.hardwareAddressType = buffer[1]; - out.hardwareAddressLength = buffer[2]; - out.hops = buffer[3]; - out.transactionId = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7]; - out.secondsElapsed = buffer[8] << 8 | buffer[9]; - out.flags = buffer[10] << 8 | buffer[11]; - out.clientIpAddress = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15]; - out.yourIpAddress = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19]; - out.serverIpAddress = buffer[20] << 24 | buffer[21] << 16 | buffer[22] << 8 | buffer[23]; - out.relayIpAddress = buffer[24] << 24 | buffer[25] << 16 | buffer[26] << 8 | buffer[27]; - - std::memcpy( - out.clientHardwareAddress.data(), buffer + 28, out.clientHardwareAddress.size()); - std::memcpy(out.serverHostname.data(), buffer + 44, out.serverHostname.size()); - std::memcpy(out.bootFile.data(), buffer + 108, out.bootFile.size()); - std::memcpy(out.magicValue.data(), buffer + 236, out.magicValue.size()); - - assert(SerializedLength() == 240); - return 240; - } - - static uint32_t transactionId; - static std::vector offeredIpAddresses; - static std::vector serverIpAddresses; - static std::vector serverMacAddresses; - static bool serverSelected; - - void sendRequest( - uint32_t clientIpAddress, Utils::MacAddress serverMacAddress, uint32_t serverIpAddress) - { - const Header dhcpHeader(Opcode::BootRequest, transactionId); - - size_t udpLength = dhcpHeader.SerializedLength() + Udp::Header::SerializedLength(); - const Udp::Header udpHeader(Udp::Port::DhcpClient, Udp::Port::DhcpServer, udpLength); - - 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); - - uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; - size_t size = 0; - size += ethernetHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += ipv4Header.Serialize(buffer + size, sizeof(buffer) - size); - size += udpHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += dhcpHeader.Serialize(buffer + size, sizeof(buffer) - size); - - const auto expectedSize = ethernetHeader.SerializedLength() + - ipv4Header.SerializedLength() + udpHeader.SerializedLength() + - dhcpHeader.SerializedLength(); - assert(size == expectedSize); - assert(size <= sizeof(buffer)); - - USPiSendFrame(buffer, size); - } - - void discoverTimerHandler(unsigned int, void* callbackVoid, void*) - { - if (transactionId == 0 || offeredIpAddresses.empty()) + size_t Header::Deserialize(Header& out, const uint8_t* buffer, const size_t size) { - // TODO retry every minute or so? - return; + if (size < SerializedLength()) + { + return 0; + } + + out.opcode = static_cast(buffer[0]); + out.hardwareAddressType = buffer[1]; + out.hardwareAddressLength = buffer[2]; + out.hops = buffer[3]; + out.transactionId = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7]; + out.secondsElapsed = buffer[8] << 8 | buffer[9]; + out.flags = buffer[10] << 8 | buffer[11]; + out.clientIpAddress = + buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15]; + out.yourIpAddress = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19]; + out.serverIpAddress = + buffer[20] << 24 | buffer[21] << 16 | buffer[22] << 8 | buffer[23]; + out.relayIpAddress = buffer[24] << 24 | buffer[25] << 16 | buffer[26] << 8 | buffer[27]; + + std::memcpy( + out.clientHardwareAddress.data(), buffer + 28, out.clientHardwareAddress.size()); + std::memcpy(out.serverHostname.data(), buffer + 44, out.serverHostname.size()); + std::memcpy(out.bootFile.data(), buffer + 108, out.bootFile.size()); + std::memcpy(out.magicValue.data(), buffer + 236, out.magicValue.size()); + + assert(SerializedLength() == 240); + return 240; } - // Select the first IP address - Utils::Ipv4Address = offeredIpAddresses[0]; + static uint32_t transactionId; + static std::vector offeredIpAddresses; + static std::vector serverIpAddresses; + static std::vector serverMacAddresses; + static bool serverSelected; - // Send DHCP Requests to every server with that IP address. - for (size_t i = 0; i < serverIpAddresses.size(); i++) + void sendRequest( + uint32_t clientIpAddress, Utils::MacAddress serverMacAddress, uint32_t serverIpAddress) { - sendRequest(Utils::Ipv4Address, serverMacAddresses[i], serverIpAddresses[i]); + const Header dhcpHeader(Opcode::BootRequest, transactionId); + + size_t udpLength = dhcpHeader.SerializedLength() + Udp::Header::SerializedLength(); + const Udp::Header udpHeader(Udp::Port::DhcpClient, Udp::Port::DhcpServer, udpLength); + + 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); + + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + size_t size = 0; + size += ethernetHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += ipv4Header.Serialize(buffer + size, sizeof(buffer) - size); + size += udpHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += dhcpHeader.Serialize(buffer + size, sizeof(buffer) - size); + + const auto expectedSize = ethernetHeader.SerializedLength() + + ipv4Header.SerializedLength() + udpHeader.SerializedLength() + + dhcpHeader.SerializedLength(); + assert(size == expectedSize); + assert(size <= sizeof(buffer)); + + USPiSendFrame(buffer, size); } - // Run the callback indicating an IP has been obtained - if (callbackVoid != nullptr) + void discoverTimerHandler(unsigned int, void* callbackVoid, void*) { - const auto& callback = *static_cast*>(callbackVoid); - callback(); - } - } + if (transactionId == 0 || offeredIpAddresses.empty()) + { + // TODO retry every minute or so? + return; + } - void sendDiscover() - { - transactionId = std::rand(); - offeredIpAddresses.clear(); - const Header dhcpHeader(Opcode::BootRequest, transactionId); + // Select the first IP address + Utils::Ipv4Address = offeredIpAddresses[0]; - size_t udpLength = dhcpHeader.SerializedLength() + Udp::Header::SerializedLength(); - const Udp::Header udpHeader(Udp::Port::DhcpClient, Udp::Port::DhcpServer, udpLength); + // Send DHCP Requests to every server with that IP address. + for (size_t i = 0; i < serverIpAddresses.size(); i++) + { + sendRequest(Utils::Ipv4Address, serverMacAddresses[i], serverIpAddresses[i]); + } - 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); - - uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; - size_t size = 0; - - size += ethernetHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += ipv4Header.Serialize(buffer + size, sizeof(buffer) - size); - size += udpHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += dhcpHeader.Serialize(buffer + size, sizeof(buffer) - size); - - const auto expectedSize = ethernetHeader.SerializedLength() + - ipv4Header.SerializedLength() + udpHeader.SerializedLength() + - dhcpHeader.SerializedLength(); - assert(size == expectedSize); - assert(size <= sizeof(buffer)); - - USPiSendFrame(buffer, size); - } - - void ObtainIp(std::function& callback) - { - sendDiscover(); - - // Wait three seconds for responses - const auto callbackVoid = static_cast(&callback); - StartKernelTimer(3 * HZ, discoverTimerHandler, callbackVoid, nullptr); - } - - static void handleOfferPacket(const Ethernet::Header ethernetHeader, const Header dhcpHeader) - { - offeredIpAddresses.push_back(dhcpHeader.yourIpAddress); - serverIpAddresses.push_back(dhcpHeader.serverIpAddress); - serverMacAddresses.push_back(ethernetHeader.macSource); - } - - static void handleAckPacket(const Ethernet::Header ethernetHeader, const Header dhcpHeader) - { - Utils::Ipv4Address = dhcpHeader.yourIpAddress; - - // TODO Schedule handler for end of lease. - - transactionId = 0; - offeredIpAddresses.clear(); - serverIpAddresses.clear(); - serverMacAddresses.clear(); - serverSelected = false; - } - - void HandlePacket(const Ethernet::Header& ethernetHeader, const uint8_t* buffer, size_t size) - { - Header header; - const auto dhcpSize = Header::Deserialize(header, buffer, size); - if (dhcpSize != Header::SerializedLength()) - { - DEBUG_LOG( - "Dropped DHCP packet (invalid buffer size %u, expected %u)\r\n", - size, - Header::SerializedLength()); - return; + // Run the callback indicating an IP has been obtained + if (callbackVoid != nullptr) + { + const auto& callback = *static_cast*>(callbackVoid); + callback(); + } } - if (header.opcode != Opcode::BootReply) - return; - if (header.hardwareAddressType != 1) - return; - if (header.hardwareAddressLength != 6) - return; - if (header.transactionId != transactionId) - return; + void sendDiscover() + { + transactionId = std::rand(); + offeredIpAddresses.clear(); + const Header dhcpHeader(Opcode::BootRequest, transactionId); - if (!serverSelected) - { - handleOfferPacket(ethernetHeader, header); + size_t udpLength = dhcpHeader.SerializedLength() + Udp::Header::SerializedLength(); + const Udp::Header udpHeader(Udp::Port::DhcpClient, Udp::Port::DhcpServer, udpLength); + + 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); + + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + size_t size = 0; + + size += ethernetHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += ipv4Header.Serialize(buffer + size, sizeof(buffer) - size); + size += udpHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += dhcpHeader.Serialize(buffer + size, sizeof(buffer) - size); + + const auto expectedSize = ethernetHeader.SerializedLength() + + ipv4Header.SerializedLength() + udpHeader.SerializedLength() + + dhcpHeader.SerializedLength(); + assert(size == expectedSize); + assert(size <= sizeof(buffer)); + + USPiSendFrame(buffer, size); } - else + + void ObtainIp(std::function& callback) { - handleAckPacket(ethernetHeader, header); + sendDiscover(); + + // Wait three seconds for responses + // const auto callbackVoid = static_cast(&callback); + // StartKernelTimer(3 * HZ, discoverTimerHandler, callbackVoid, nullptr); } - } -} // namespace Net::Dhcp + + static void + handleOfferPacket(const Ethernet::Header ethernetHeader, const Header dhcpHeader) + { + offeredIpAddresses.push_back(dhcpHeader.yourIpAddress); + serverIpAddresses.push_back(dhcpHeader.serverIpAddress); + serverMacAddresses.push_back(ethernetHeader.macSource); + } + + static void handleAckPacket(const Ethernet::Header ethernetHeader, const Header dhcpHeader) + { + Utils::Ipv4Address = dhcpHeader.yourIpAddress; + + // TODO Schedule handler for end of lease. + + transactionId = 0; + offeredIpAddresses.clear(); + serverIpAddresses.clear(); + serverMacAddresses.clear(); + serverSelected = false; + } + + void + HandlePacket(const Ethernet::Header& ethernetHeader, const uint8_t* buffer, size_t size) + { + Header header; + const auto dhcpSize = Header::Deserialize(header, buffer, size); + if (dhcpSize != Header::SerializedLength()) + { + DEBUG_LOG( + "Dropped DHCP packet (invalid buffer size %u, expected %u)\r\n", + size, + Header::SerializedLength()); + return; + } + + if (header.opcode != Opcode::BootReply) + return; + if (header.hardwareAddressType != 1) + return; + if (header.hardwareAddressLength != 6) + return; + if (header.transactionId != transactionId) + return; + + if (!serverSelected) + { + handleOfferPacket(ethernetHeader, header); + } + else + { + handleAckPacket(ethernetHeader, header); + } + } + } // namespace Dhcp +} // namespace Net diff --git a/src/net-dhcp.h b/src/net-dhcp.h index 7cfbf00..4bca894 100644 --- a/src/net-dhcp.h +++ b/src/net-dhcp.h @@ -4,80 +4,85 @@ #include "net-ethernet.h" #include "net.h" -namespace Net::Dhcp +namespace Net { - enum class Opcode : uint8_t + namespace Dhcp { - BootRequest = 1, - BootReply = 2, - }; - - struct Header - { - /// Message op code / message type. 1 = BOOTREQUEST, 2 = BOOTREPLY - Opcode opcode; - - /// Hardware address type, see ARP section in "Assigned Numbers" RFC - uint8_t hardwareAddressType; - - uint8_t hardwareAddressLength; - - /// Client sets to zero, optionally used by relay agents when booting via a - /// relay agent. - uint8_t hops; - - /// A random number chosen by the client, used by the client and server to - /// associate messages and responses between a client and a server. - uint32_t transactionId; - - /// Filled in by client, seconds elapsed since client began address acquisition - /// or renewal process. - uint16_t secondsElapsed; - - uint16_t flags; - - /// Only filled in if client is in BOUND, RENEW or REBINDING state and can - /// respond to ARP requests. - uint32_t clientIpAddress; - - /// 'your' (client) IP address. - uint32_t yourIpAddress; - - /// IP address of next server to use in bootstrap; returned in DHCPOFFER, - /// DHCPACK by server. - uint32_t serverIpAddress; - - /// Relay agent IP address, used in booting via a relay agent. - uint32_t relayIpAddress; - - std::array clientHardwareAddress; - - /// Optional server host name, null terminated string. - std::array serverHostname; - - /// Boot file name, null terminated string; "generic" name or null in - /// DHCPDISCOVER, fully qualified directory-path name in DHCPOFFER. - std::array bootFile; - - /// Always 99, 130, 83, 99 - std::array magicValue; - - Header(); - Header(Opcode opcode, uint32_t transactionId); - - constexpr static size_t SerializedLength() + enum class Opcode : uint8_t { - return sizeof(Opcode) + sizeof(hardwareAddressType) + sizeof(hardwareAddressLength) + - sizeof(hops) + sizeof(transactionId) + sizeof(secondsElapsed) + sizeof(flags) + - sizeof(clientIpAddress) + sizeof(yourIpAddress) + sizeof(serverIpAddress) + - sizeof(relayIpAddress) + sizeof(clientHardwareAddress) + sizeof(serverHostname) + - sizeof(bootFile) + sizeof(magicValue); - } + BootRequest = 1, + BootReply = 2, + }; - size_t Serialize(uint8_t* buffer, const size_t size) const; - static size_t Deserialize(Header& out, const uint8_t* buffer, const size_t size); - }; + struct Header + { + /// Message op code / message type. 1 = BOOTREQUEST, 2 = BOOTREPLY + Opcode opcode; - void ObtainIp(std::function& callback); - void HandlePacket(const Ethernet::Header& ethernetHeader, const uint8_t* buffer, size_t size); -} // namespace Net::Dhcp + /// Hardware address type, see ARP section in "Assigned Numbers" RFC + uint8_t hardwareAddressType; + + uint8_t hardwareAddressLength; + + /// Client sets to zero, optionally used by relay agents when booting via a + /// relay agent. + uint8_t hops; + + /// A random number chosen by the client, used by the client and server to + /// associate messages and responses between a client and a server. + uint32_t transactionId; + + /// Filled in by client, seconds elapsed since client began address acquisition + /// or renewal process. + uint16_t secondsElapsed; + + uint16_t flags; + + /// Only filled in if client is in BOUND, RENEW or REBINDING state and can + /// respond to ARP requests. + uint32_t clientIpAddress; + + /// 'your' (client) IP address. + uint32_t yourIpAddress; + + /// IP address of next server to use in bootstrap; returned in DHCPOFFER, + /// DHCPACK by server. + uint32_t serverIpAddress; + + /// Relay agent IP address, used in booting via a relay agent. + uint32_t relayIpAddress; + + std::array clientHardwareAddress; + + /// Optional server host name, null terminated string. + std::array serverHostname; + + /// Boot file name, null terminated string; "generic" name or null in + /// DHCPDISCOVER, fully qualified directory-path name in DHCPOFFER. + std::array bootFile; + + /// Always 99, 130, 83, 99 + std::array magicValue; + + Header(); + Header(Opcode opcode, uint32_t transactionId); + + constexpr static size_t SerializedLength() + { + return sizeof(Opcode) + sizeof(hardwareAddressType) + + sizeof(hardwareAddressLength) + sizeof(hops) + sizeof(transactionId) + + sizeof(secondsElapsed) + sizeof(flags) + sizeof(clientIpAddress) + + sizeof(yourIpAddress) + sizeof(serverIpAddress) + sizeof(relayIpAddress) + + sizeof(clientHardwareAddress) + sizeof(serverHostname) + sizeof(bootFile) + + sizeof(magicValue); + } + + size_t Serialize(uint8_t* buffer, const size_t size) const; + static size_t Deserialize(Header& out, const uint8_t* buffer, const size_t size); + }; + + void ObtainIp(std::function& callback); + void + HandlePacket(const Ethernet::Header& ethernetHeader, const uint8_t* buffer, size_t size); + } // namespace Dhcp +} // namespace Net diff --git a/src/net-ethernet.cpp b/src/net-ethernet.cpp index 59d1d29..ee44d2c 100644 --- a/src/net-ethernet.cpp +++ b/src/net-ethernet.cpp @@ -2,56 +2,59 @@ #include "net-ethernet.h" -namespace Net::Ethernet +namespace Net { - Header::Header() {} - - Header::Header(EtherType type) : - macDestination(Utils::MacBroadcast), macSource{0, 0, 0, 0, 0, 0}, type(type) + namespace Ethernet { - } + Header::Header() {} - Header::Header(MacAddress macSource, EtherType type) : - macDestination(Utils::MacBroadcast), macSource(macSource), type(type) - { - } - - Header::Header(MacAddress macDestination, MacAddress macSource, EtherType type) : - macDestination(macDestination), macSource(macSource), type(type) - { - } - - size_t Header::Serialize(uint8_t* buffer, const size_t size) const - { - if (size < SerializedLength()) + Header::Header(EtherType type) : + macDestination(Utils::MacBroadcast), macSource{0, 0, 0, 0, 0, 0}, type(type) { - return 0; } - size_t i = 0; - - std::memcpy(buffer + i, macDestination.data(), macDestination.size()); - i += sizeof(macDestination); - - std::memcpy(buffer + i, macSource.data(), macSource.size()); - i += sizeof(macSource); - - buffer[i++] = static_cast(type) >> 8; - buffer[i++] = static_cast(type); - - return i; - } - - size_t Header::Deserialize(Header& out, const uint8_t* buffer, const size_t size) - { - if (size < SerializedLength()) + Header::Header(MacAddress macSource, EtherType type) : + macDestination(Utils::MacBroadcast), macSource(macSource), type(type) { - return 0; } - std::memcpy(out.macDestination.data(), buffer + 0, out.macDestination.size()); - std::memcpy(out.macSource.data(), buffer + 6, out.macSource.size()); - out.type = static_cast(buffer[12] << 8 | buffer[13]); - return 14; - } -} // namespace Net::Ethernet + Header::Header(MacAddress macDestination, MacAddress macSource, EtherType type) : + macDestination(macDestination), macSource(macSource), type(type) + { + } + + size_t Header::Serialize(uint8_t* buffer, const size_t size) const + { + if (size < SerializedLength()) + { + return 0; + } + + size_t i = 0; + + std::memcpy(buffer + i, macDestination.data(), macDestination.size()); + i += sizeof(macDestination); + + std::memcpy(buffer + i, macSource.data(), macSource.size()); + i += sizeof(macSource); + + buffer[i++] = static_cast(type) >> 8; + buffer[i++] = static_cast(type); + + return i; + } + + size_t Header::Deserialize(Header& out, const uint8_t* buffer, const size_t size) + { + if (size < SerializedLength()) + { + return 0; + } + + std::memcpy(out.macDestination.data(), buffer + 0, out.macDestination.size()); + std::memcpy(out.macSource.data(), buffer + 6, out.macSource.size()); + out.type = static_cast(buffer[12] << 8 | buffer[13]); + return 14; + } + } // namespace Ethernet +} // namespace Net diff --git a/src/net-ethernet.h b/src/net-ethernet.h index 28e6746..9427d15 100644 --- a/src/net-ethernet.h +++ b/src/net-ethernet.h @@ -3,33 +3,36 @@ #include "net-utils.h" -namespace Net::Ethernet +namespace Net { - using Utils::MacAddress; - - enum class EtherType : uint16_t + namespace Ethernet { - Ipv4 = 0x0800, - Arp = 0x0806, - }; + using Utils::MacAddress; - struct Header - { - MacAddress macDestination; - MacAddress macSource; - EtherType type; - - Header(); - Header(EtherType type); - Header(MacAddress macSource, EtherType type); - Header(MacAddress macDestination, MacAddress macSource, EtherType type); - - constexpr static size_t SerializedLength() + enum class EtherType : uint16_t { - return sizeof(macDestination) + sizeof(macSource) + sizeof(type); - } + Ipv4 = 0x0800, + Arp = 0x0806, + }; - size_t Serialize(uint8_t* buffer, const size_t size) const; - static size_t Deserialize(Header& out, const uint8_t* buffer, const size_t size); - }; -} // namespace Net::Ethernet + struct Header + { + MacAddress macDestination; + MacAddress macSource; + EtherType type; + + Header(); + Header(EtherType type); + Header(MacAddress macSource, EtherType type); + Header(MacAddress macDestination, MacAddress macSource, EtherType type); + + constexpr static size_t SerializedLength() + { + return sizeof(macDestination) + sizeof(macSource) + sizeof(type); + } + + size_t Serialize(uint8_t* buffer, const size_t size) const; + static size_t Deserialize(Header& out, const uint8_t* buffer, const size_t size); + }; + } // namespace Ethernet +} // namespace Net diff --git a/src/net-icmp.cpp b/src/net-icmp.cpp index cbacdf6..f2ab06b 100644 --- a/src/net-icmp.cpp +++ b/src/net-icmp.cpp @@ -9,182 +9,189 @@ #include "types.h" #include -namespace Net::Icmp +namespace Net { - // - // Header - // - Header::Header() : type(static_cast(0)), code(0), checksum(0) {} - Header::Header(Type type, uint8_t code) : type(type), code(code), checksum(0) {} - - size_t Header::Serialize( - uint8_t* buffer, const size_t bufferSize, const uint8_t* data, const size_t dataSize) const + namespace Icmp { - if (bufferSize < SerializedLength()) + // + // Header + // + Header::Header() : type(static_cast(0)), code(0), checksum(0) {} + Header::Header(Type type, uint8_t code) : type(type), code(code), checksum(0) {} + + size_t Header::Serialize( + uint8_t* buffer, + const size_t bufferSize, + const uint8_t* data, + const size_t dataSize) const { - return 0; + if (bufferSize < SerializedLength()) + { + return 0; + } + + size_t i = 0; + buffer[i++] = static_cast(type); + buffer[i++] = code; + buffer[i++] = 0; + buffer[i++] = 0; + + std::memcpy(buffer + i, data, dataSize); + i += dataSize; + + uint16_t checksum = Utils::InternetChecksum(buffer, i); + buffer[2] = checksum >> 8; + buffer[3] = checksum; + + return i; } - size_t i = 0; - buffer[i++] = static_cast(type); - buffer[i++] = code; - buffer[i++] = 0; - buffer[i++] = 0; - - std::memcpy(buffer + i, data, dataSize); - i += dataSize; - - uint16_t checksum = Utils::InternetChecksum(buffer, i); - buffer[2] = checksum >> 8; - buffer[3] = checksum; - - return i; - } - - size_t Header::Deserialize(Header& out, const uint8_t* buffer, const size_t bufferSize) - { - if (bufferSize < SerializedLength()) + size_t Header::Deserialize(Header& out, const uint8_t* buffer, const size_t bufferSize) { - return 0; + if (bufferSize < SerializedLength()) + { + return 0; + } + + out.type = static_cast(buffer[0]); + out.code = buffer[1]; + out.checksum = buffer[2] << 8 | buffer[3]; + return 4; } - out.type = static_cast(buffer[0]); - out.code = buffer[1]; - out.checksum = buffer[2] << 8 | buffer[3]; - return 4; - } - - // - // 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 bufferSize) const - { - if (bufferSize < SerializedLength()) + // + // EchoHeader + // + EchoHeader::EchoHeader() : EchoHeader(0, 0) {} + EchoHeader::EchoHeader(uint16_t identifier, uint16_t sequenceNumber) : + identifier(identifier), sequenceNumber(sequenceNumber) { - return 0; } - size_t i = 0; - buffer[i++] = identifier >> 8; - buffer[i++] = identifier; - buffer[i++] = sequenceNumber >> 8; - buffer[i++] = sequenceNumber; - return i; - } - - size_t EchoHeader::Deserialize(EchoHeader& out, const uint8_t* buffer, const size_t bufferSize) - { - if (bufferSize < SerializedLength()) + size_t EchoHeader::Serialize(uint8_t* buffer, const size_t bufferSize) const { - return 0; + if (bufferSize < SerializedLength()) + { + return 0; + } + + size_t i = 0; + buffer[i++] = identifier >> 8; + buffer[i++] = identifier; + buffer[i++] = sequenceNumber >> 8; + buffer[i++] = sequenceNumber; + return i; } - out.identifier = buffer[0] << 8 | buffer[1]; - out.sequenceNumber = buffer[2] << 8 | buffer[3]; - return 4; - } - - void SendEchoRequest(Utils::MacAddress mac, uint32_t ip) - { - Icmp::Header icmpHeader(Icmp::Type::EchoRequest, 0); - Icmp::EchoHeader pingHeader(0, 0); - - size_t ipv4TotalSize = Icmp::Header::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 size = 0; - - const uint8_t emptyBuffer[1] = {}; - - size += ethernetHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += ipv4Header.Serialize(buffer + size, sizeof(buffer) - size); - size += pingHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += icmpHeader.Serialize(buffer + size, sizeof(buffer) - size, emptyBuffer, 0); - - const auto expectedSize = ethernetHeader.SerializedLength() + - ipv4Header.SerializedLength() + pingHeader.SerializedLength() + - icmpHeader.SerializedLength(); - assert(size == expectedSize); - assert(size <= sizeof(buffer)); - - USPiSendFrame(buffer, size); - } - - static void handleEchoRequest( - const Ethernet::Header& reqEthernetHeader, - const Ipv4::Header& reqIpv4Header, - const Icmp::Header& reqIcmpHeader, - const uint8_t* reqBuffer, - const size_t reqBufferSize) - { - const Ethernet::Header respEthernetHeader( - reqEthernetHeader.macSource, Utils::GetMacAddress(), Ethernet::EtherType::Ipv4); - const Ipv4::Header respIpv4Header( - Ipv4::Protocol::Icmp, - Utils::Ipv4Address, - reqIpv4Header.sourceIp, - reqIpv4Header.totalLength); - Header respIcmpHeader(Type::EchoReply, 0); - - const auto payloadSize = reqIpv4Header.totalLength - reqIpv4Header.SerializedLength() - - reqIcmpHeader.SerializedLength(); - - DEBUG_LOG("payloadSize: %u\r\n", payloadSize); - - std::array respBuffer; - - size_t respSize = 0; - respSize += respEthernetHeader.Serialize( - respBuffer.data() + respSize, respBuffer.size() - respSize); - respSize += - respIpv4Header.Serialize(respBuffer.data() + respSize, respBuffer.size() - respSize); - respSize += respIcmpHeader.Serialize( - respBuffer.data() + respSize, respBuffer.size() - respSize, reqBuffer, payloadSize); - - const auto expectedRespSize = respEthernetHeader.SerializedLength() + - respIpv4Header.SerializedLength() + respIcmpHeader.SerializedLength() + payloadSize; - assert(respSize == expectedRespSize); - assert(respSize <= respBuffer.size()); - - USPiSendFrame(respBuffer.data(), respSize); - } - - void HandlePacket( - Ethernet::Header ethernetHeader, - Ipv4::Header ipv4Header, - const uint8_t* buffer, - const size_t bufferSize) - { - Header icmpHeader; - size_t headerSize = Icmp::Header::Deserialize(icmpHeader, buffer, bufferSize); - if (headerSize != Icmp::Header::SerializedLength()) + size_t + EchoHeader::Deserialize(EchoHeader& out, const uint8_t* buffer, const size_t bufferSize) { - DEBUG_LOG( - "Dropped ICMP packet (invalid buffer size %u, expected at least %u)\r\n", - bufferSize, - Icmp::Header::SerializedLength()); + if (bufferSize < SerializedLength()) + { + return 0; + } + + out.identifier = buffer[0] << 8 | buffer[1]; + out.sequenceNumber = buffer[2] << 8 | buffer[3]; + return 4; } - DEBUG_LOG("Got ICMP header type %u\r\n", static_cast(icmpHeader.type)); - - if (icmpHeader.type == Type::EchoRequest) + void SendEchoRequest(Utils::MacAddress mac, uint32_t ip) { - handleEchoRequest( - ethernetHeader, - ipv4Header, - icmpHeader, - buffer + headerSize, - bufferSize - headerSize); + Icmp::Header icmpHeader(Icmp::Type::EchoRequest, 0); + Icmp::EchoHeader pingHeader(0, 0); + + size_t ipv4TotalSize = Icmp::Header::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 size = 0; + + const uint8_t emptyBuffer[1] = {}; + + size += ethernetHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += ipv4Header.Serialize(buffer + size, sizeof(buffer) - size); + size += pingHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += icmpHeader.Serialize(buffer + size, sizeof(buffer) - size, emptyBuffer, 0); + + const auto expectedSize = ethernetHeader.SerializedLength() + + ipv4Header.SerializedLength() + pingHeader.SerializedLength() + + icmpHeader.SerializedLength(); + assert(size == expectedSize); + assert(size <= sizeof(buffer)); + + USPiSendFrame(buffer, size); } - } -} // namespace Net::Icmp + + static void handleEchoRequest( + const Ethernet::Header& reqEthernetHeader, + const Ipv4::Header& reqIpv4Header, + const Icmp::Header& reqIcmpHeader, + const uint8_t* reqBuffer, + const size_t reqBufferSize) + { + const Ethernet::Header respEthernetHeader( + reqEthernetHeader.macSource, Utils::GetMacAddress(), Ethernet::EtherType::Ipv4); + const Ipv4::Header respIpv4Header( + Ipv4::Protocol::Icmp, + Utils::Ipv4Address, + reqIpv4Header.sourceIp, + reqIpv4Header.totalLength); + Header respIcmpHeader(Type::EchoReply, 0); + + const auto payloadSize = reqIpv4Header.totalLength - reqIpv4Header.SerializedLength() - + reqIcmpHeader.SerializedLength(); + + DEBUG_LOG("payloadSize: %u\r\n", payloadSize); + + std::array respBuffer; + + size_t respSize = 0; + respSize += respEthernetHeader.Serialize( + respBuffer.data() + respSize, respBuffer.size() - respSize); + respSize += respIpv4Header.Serialize( + respBuffer.data() + respSize, respBuffer.size() - respSize); + respSize += respIcmpHeader.Serialize( + respBuffer.data() + respSize, respBuffer.size() - respSize, reqBuffer, payloadSize); + + const auto expectedRespSize = respEthernetHeader.SerializedLength() + + respIpv4Header.SerializedLength() + respIcmpHeader.SerializedLength() + payloadSize; + assert(respSize == expectedRespSize); + assert(respSize <= respBuffer.size()); + + USPiSendFrame(respBuffer.data(), respSize); + } + + void HandlePacket( + Ethernet::Header ethernetHeader, + Ipv4::Header ipv4Header, + const uint8_t* buffer, + const size_t bufferSize) + { + Header icmpHeader; + size_t headerSize = Icmp::Header::Deserialize(icmpHeader, buffer, bufferSize); + if (headerSize != Icmp::Header::SerializedLength()) + { + DEBUG_LOG( + "Dropped ICMP packet (invalid buffer size %u, expected at least %u)\r\n", + bufferSize, + Icmp::Header::SerializedLength()); + } + + DEBUG_LOG("Got ICMP header type %u\r\n", static_cast(icmpHeader.type)); + + if (icmpHeader.type == Type::EchoRequest) + { + handleEchoRequest( + ethernetHeader, + ipv4Header, + icmpHeader, + buffer + headerSize, + bufferSize - headerSize); + } + } + } // namespace Icmp +} // namespace Net diff --git a/src/net-ipv4.cpp b/src/net-ipv4.cpp index 51f5465..27b8310 100644 --- a/src/net-ipv4.cpp +++ b/src/net-ipv4.cpp @@ -13,165 +13,170 @@ #include #include -namespace Net::Ipv4 +namespace Net { - Header::Header() {} - - 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) + namespace Ipv4 { - } + Header::Header() {} - size_t Header::Serialize(uint8_t* buffer, const size_t bufferSize) const - { - if (bufferSize <= SerializedLength()) + 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) { - return 0; } - size_t i = 0; - 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); - - // Zero the checksum before calculating it - buffer[i++] = 0; - buffer[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; - - uint16_t checksum = Net::Utils::InternetChecksum(buffer, i); - buffer[10] = checksum >> 8; - buffer[11] = checksum; - - return i; - } - - size_t Header::Deserialize(Header& out, const uint8_t* buffer, const size_t bufferSize) - { - if (bufferSize <= SerializedLength()) + size_t Header::Serialize(uint8_t* buffer, const size_t bufferSize) const { - return 0; + if (bufferSize <= SerializedLength()) + { + return 0; + } + + size_t i = 0; + 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); + + // Zero the checksum before calculating it + buffer[i++] = 0; + buffer[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; + + uint16_t checksum = Net::Utils::InternetChecksum(buffer, i); + buffer[10] = checksum >> 8; + buffer[11] = checksum; + + return i; } - out.version = buffer[0] >> 4; - out.ihl = buffer[0] & 0x0F; - - out.dscp = buffer[1] >> 2; - out.ecn = buffer[1] & 0x03; - - out.totalLength = buffer[2] << 8 | buffer[3]; - out.identification = buffer[4] << 8 | buffer[5]; - - out.flags = buffer[6] >> 5; - out.fragmentOffset = (buffer[6] & 0x1F) << 8 | buffer[7]; - - out.ttl = buffer[8]; - out.protocol = static_cast(buffer[9]); - out.headerChecksum = buffer[10] << 8 | buffer[11]; - - out.sourceIp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15]; - out.destinationIp = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19]; - - return 20; - } - - void HandlePacket( - const Ethernet::Header& ethernetHeader, const uint8_t* buffer, const size_t bufferSize) - { - Header header; - const auto headerSize = Header::Deserialize(header, buffer, bufferSize); - if (headerSize != Header::SerializedLength()) + size_t Header::Deserialize(Header& out, const uint8_t* buffer, const size_t bufferSize) { + if (bufferSize <= SerializedLength()) + { + return 0; + } + + out.version = buffer[0] >> 4; + out.ihl = buffer[0] & 0x0F; + + out.dscp = buffer[1] >> 2; + out.ecn = buffer[1] & 0x03; + + out.totalLength = buffer[2] << 8 | buffer[3]; + out.identification = buffer[4] << 8 | buffer[5]; + + out.flags = buffer[6] >> 5; + out.fragmentOffset = (buffer[6] & 0x1F) << 8 | buffer[7]; + + out.ttl = buffer[8]; + out.protocol = static_cast(buffer[9]); + out.headerChecksum = buffer[10] << 8 | buffer[11]; + + out.sourceIp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15]; + out.destinationIp = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19]; + + return 20; + } + + void HandlePacket( + const Ethernet::Header& ethernetHeader, const uint8_t* buffer, const size_t bufferSize) + { + Header header; + const auto headerSize = Header::Deserialize(header, buffer, bufferSize); + if (headerSize != Header::SerializedLength()) + { + DEBUG_LOG( + "Dropped IPv4 header (invalid buffer size %u, expected at least %u)\r\n", + bufferSize, + headerSize); + return; + } DEBUG_LOG( - "Dropped IPv4 header (invalid buffer size %u, expected at least %u)\r\n", - bufferSize, - headerSize); - return; - } - DEBUG_LOG( - "IPv4 { src=%08lx, dst=%08lx, len=%u, protocol=%u }\r\n", - header.sourceIp, - header.destinationIp, - header.totalLength, - static_cast(header.protocol)); - if (bufferSize < header.totalLength) - { - DEBUG_LOG( - "Dropped IPv4 packet (invalid buffer size %u, expected at least %u)\r\n", - bufferSize, - header.totalLength); - return; - } + "IPv4 { src=%08lx, dst=%08lx, len=%u, protocol=%u }\r\n", + header.sourceIp, + header.destinationIp, + header.totalLength, + static_cast(header.protocol)); + if (bufferSize < header.totalLength) + { + DEBUG_LOG( + "Dropped IPv4 packet (invalid buffer size %u, expected at least %u)\r\n", + bufferSize, + header.totalLength); + return; + } - // Update ARP table - Arp::ArpTable.insert(std::make_pair(header.sourceIp, ethernetHeader.macSource)); + // Update ARP table + Arp::ArpTable.insert(std::make_pair(header.sourceIp, ethernetHeader.macSource)); - if (header.version != 4) - { - DEBUG_LOG( - "Dropped IPv4 packet (invalid header version %u, expected 4)\r\n", header.version); - return; - } - if (header.ihl != 5) - { - // Not supported - DEBUG_LOG("Dropped IPv4 packet (unsupported IHL %u, expected 5)\r\n", header.ihl); - return; - } - if (header.destinationIp != Utils::Ipv4Address) - { - DEBUG_LOG( - "Dropped IPv4 packet (invalid destination IP address %08lx)\r\n", - header.destinationIp); - return; - } - if (header.fragmentOffset != 0) - { - // TODO Support this - DEBUG_LOG( - "Dropped IPv4 packet (unexpected fragment offset %u, expected 0)\r\n", - header.fragmentOffset); - return; - } + if (header.version != 4) + { + DEBUG_LOG( + "Dropped IPv4 packet (invalid header version %u, expected 4)\r\n", + header.version); + return; + } + if (header.ihl != 5) + { + // Not supported + DEBUG_LOG("Dropped IPv4 packet (unsupported IHL %u, expected 5)\r\n", header.ihl); + return; + } + if (header.destinationIp != Utils::Ipv4Address) + { + DEBUG_LOG( + "Dropped IPv4 packet (invalid destination IP address %08lx)\r\n", + header.destinationIp); + return; + } + if (header.fragmentOffset != 0) + { + // TODO Support this + DEBUG_LOG( + "Dropped IPv4 packet (unexpected fragment offset %u, expected 0)\r\n", + header.fragmentOffset); + return; + } - if (header.protocol == Ipv4::Protocol::Icmp) - { - DEBUG_LOG("Ethernet -> IPv4 -> ICMP\r\n"); - Icmp::HandlePacket( - ethernetHeader, header, buffer + headerSize, bufferSize - headerSize); + if (header.protocol == Ipv4::Protocol::Icmp) + { + DEBUG_LOG("Ethernet -> IPv4 -> ICMP\r\n"); + Icmp::HandlePacket( + ethernetHeader, header, buffer + headerSize, bufferSize - headerSize); + } + else if (header.protocol == Ipv4::Protocol::Udp) + { + DEBUG_LOG("Ethernet -> IPv4 -> UDP\r\n"); + Udp::HandlePacket( + ethernetHeader, header, buffer + headerSize, bufferSize - headerSize); + } } - else if (header.protocol == Ipv4::Protocol::Udp) - { - DEBUG_LOG("Ethernet -> IPv4 -> UDP\r\n"); - Udp::HandlePacket(ethernetHeader, header, buffer + headerSize, bufferSize - headerSize); - } - } -} // namespace Net::Ipv4 + } // namespace Ipv4 +} // namespace Net diff --git a/src/net-ipv4.h b/src/net-ipv4.h index be3d295..b13b339 100644 --- a/src/net-ipv4.h +++ b/src/net-ipv4.h @@ -4,44 +4,48 @@ #include "net-ethernet.h" -namespace Net::Ipv4 +namespace Net { - enum class Protocol : uint8_t + namespace Ipv4 { - Icmp = 1, - Tcp = 6, - Udp = 17, - }; - - 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() + enum class Protocol : uint8_t { - // Hardcoded because of bitfields. - return 20; - } + Icmp = 1, + Tcp = 6, + Udp = 17, + }; - size_t Serialize(uint8_t* buffer, const size_t bufferSize) const; - static size_t Deserialize(Header& out, const uint8_t* buffer, const size_t bufferSize); - }; + 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; - void HandlePacket( - const Ethernet::Header& ethernetHeader, const uint8_t* buffer, const size_t bufferSize); -} // namespace Net::Ipv4 + 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 size_t bufferSize) const; + static size_t Deserialize(Header& out, const uint8_t* buffer, const size_t bufferSize); + }; + + void HandlePacket( + const Ethernet::Header& ethernetHeader, const uint8_t* buffer, const size_t bufferSize); + } // namespace Ipv4 +} // namespace Net diff --git a/src/net-tftp.cpp b/src/net-tftp.cpp index 64c2afa..7daceb0 100644 --- a/src/net-tftp.cpp +++ b/src/net-tftp.cpp @@ -14,360 +14,364 @@ #include "types.h" #include -namespace Net::Tftp +namespace Net { - // TODO Allow multiple files open - static FIL outFile; - static bool shouldReboot = false; - static uint32_t currentBlockNumber = -1; - - Packet::Packet() : opcode(static_cast(0)) {} - Packet::Packet(const Opcode opcode) : opcode(opcode) {} - - static std::unique_ptr - handleTftpWriteRequest(const uint8_t* buffer, const size_t bufferSize) + namespace Tftp { - DEBUG_LOG("Received TFTP write request\r\n"); - WriteReadRequestPacket packet; - const auto size = packet.Deserialize(buffer, bufferSize); - if (size == 0) + // TODO Allow multiple files open + static FIL outFile; + static bool shouldReboot = false; + static uint32_t currentBlockNumber = -1; + + Packet::Packet() : opcode(static_cast(0)) {} + Packet::Packet(const Opcode opcode) : opcode(opcode) {} + + static std::unique_ptr + handleTftpWriteRequest(const uint8_t* buffer, const size_t bufferSize) { - DEBUG_LOG( - "Dropped TFTP packet (invalid buffer size %u, expected at least %u)\r\n", - bufferSize, - sizeof(WriteReadRequestPacket::opcode) + 2); - return nullptr; + DEBUG_LOG("Received TFTP write request\r\n"); + WriteReadRequestPacket packet; + const auto size = packet.Deserialize(buffer, bufferSize); + if (size == 0) + { + DEBUG_LOG( + "Dropped TFTP packet (invalid buffer size %u, expected at least %u)\r\n", + bufferSize, + sizeof(WriteReadRequestPacket::opcode) + 2); + return nullptr; + } + + // TODO Implement netscii, maybe + if (packet.mode != "octet") + { + const auto pointer = new ErrorPacket(0, "please use mode octet"); + return std::unique_ptr(pointer); + } + + currentBlockNumber = 0; + + // TODO Return to the original working directory. + char workingDirectory[256]; + f_getcwd(workingDirectory, sizeof(workingDirectory)); + + // Try opening the file + auto separator = packet.filename.rfind('/', packet.filename.size()); + if (separator != std::string::npos) + { + auto path = "/" + packet.filename.substr(0, separator); + f_chdir(path.c_str()); + } + else + { + f_chdir("/"); + separator = 0; + } + + // Open the output file. + auto filename = packet.filename.substr(separator + 1); + const auto result = f_open(&outFile, filename.c_str(), FA_CREATE_ALWAYS | FA_WRITE); + + std::unique_ptr response; + if (result != FR_OK) + { + response = + std::unique_ptr(new ErrorPacket(0, "error opening target file")); + } + else + { + shouldReboot = packet.filename == "kernel.img" || packet.filename == "options.txt"; + response = std::unique_ptr( + new AcknowledgementPacket(currentBlockNumber)); + } + + // TODO Return to the original working directory here + + return response; } - // TODO Implement netscii, maybe - if (packet.mode != "octet") + static std::unique_ptr handleTftpData(const uint8_t* buffer, size_t size) { - const auto pointer = new ErrorPacket(0, "please use mode octet"); - return std::unique_ptr(pointer); - } + DEBUG_LOG("Received TFTP data\r\n"); + DataPacket packet; + const auto tftpSize = packet.Deserialize(buffer, size); + if (tftpSize == 0) + { + DEBUG_LOG( + "Dropped TFTP data packet (invalid buffer size %u, expected at least %u)\r\n", + size, + sizeof(packet.opcode) + sizeof(packet.blockNumber)); + return nullptr; + } - currentBlockNumber = 0; + if (packet.blockNumber != currentBlockNumber + 1) + { + f_close(&outFile); + return std::unique_ptr(new ErrorPacket(0, "invalid block number")); + } + currentBlockNumber = packet.blockNumber; - // TODO Return to the original working directory. - char workingDirectory[256]; - f_getcwd(workingDirectory, sizeof(workingDirectory)); + unsigned int bytesWritten; + const auto result = + f_write(&outFile, packet.data.data(), packet.data.size(), &bytesWritten); - // Try opening the file - auto separator = packet.filename.rfind('/', packet.filename.size()); - if (separator != std::string::npos) - { - auto path = "/" + packet.filename.substr(0, separator); - f_chdir(path.c_str()); - } - else - { - f_chdir("/"); - separator = 0; - } + if (result != FR_OK || bytesWritten != packet.data.size()) + { + f_close(&outFile); + return std::unique_ptr(new ErrorPacket(0, "io error")); + } - // Open the output file. - auto filename = packet.filename.substr(separator + 1); - const auto result = f_open(&outFile, filename.c_str(), FA_CREATE_ALWAYS | FA_WRITE); + if (packet.data.size() < TFTP_BLOCK_SIZE) + { + // Close the file for the last packet. + f_close(&outFile); + } - std::unique_ptr response; - if (result != FR_OK) - { - response = - std::unique_ptr(new ErrorPacket(0, "error opening target file")); - } - else - { - shouldReboot = packet.filename == "kernel.img" || packet.filename == "options.txt"; - response = std::unique_ptr( + return std::unique_ptr( new AcknowledgementPacket(currentBlockNumber)); } - // TODO Return to the original working directory here - - return response; - } - - static std::unique_ptr handleTftpData(const uint8_t* buffer, size_t size) - { - DEBUG_LOG("Received TFTP data\r\n"); - DataPacket packet; - const auto tftpSize = packet.Deserialize(buffer, size); - if (tftpSize == 0) + void HandlePacket( + const Ethernet::Header ethernetReqHeader, + const Ipv4::Header ipv4ReqHeader, + const Udp::Header udpReqHeader, + const uint8_t* reqBuffer, + const size_t reqBufferSize) { - DEBUG_LOG( - "Dropped TFTP data packet (invalid buffer size %u, expected at least %u)\r\n", - size, - sizeof(packet.opcode) + sizeof(packet.blockNumber)); - return nullptr; + const auto opcode = static_cast(reqBuffer[0] << 8 | reqBuffer[1]); + DEBUG_LOG("Received TFTP %u packet\r\n", static_cast(opcode)); + std::unique_ptr response; + + const auto payloadSize = udpReqHeader.length - udpReqHeader.SerializedLength(); + if (reqBufferSize < payloadSize) + { + DEBUG_LOG( + "Dropped TFTP packet (invalid buffer size %u, expected at least %u)\r\n", + reqBufferSize, + payloadSize); + } + + if (opcode == Opcode::WriteRequest) + { + response = handleTftpWriteRequest(reqBuffer, payloadSize); + } + else if (opcode == Opcode::Data) + { + response = handleTftpData(reqBuffer, payloadSize); + } + else + { + response = std::unique_ptr(new ErrorPacket(4, "not implemented yet")); + } + + if (response != nullptr) + { + DEBUG_LOG("Sending TFTP response\r\n"); + Udp::Header udpRespHeader( + udpReqHeader.destinationPort, + udpReqHeader.sourcePort, + response->SerializedLength() + Udp::Header::SerializedLength()); + Ipv4::Header ipv4RespHeader( + Ipv4::Protocol::Udp, + Utils::Ipv4Address, + ipv4ReqHeader.sourceIp, + udpRespHeader.length + Ipv4::Header::SerializedLength()); + Ethernet::Header ethernetRespHeader( + Arp::ArpTable[ipv4RespHeader.destinationIp], + Utils::GetMacAddress(), + Ethernet::EtherType::Ipv4); + + size_t size = 0; + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + size += ethernetRespHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += ipv4RespHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += udpRespHeader.Serialize(buffer + size, sizeof(buffer) - size); + size += response->Serialize(buffer + size, sizeof(buffer) - size); + + const auto expectedSize = ethernetRespHeader.SerializedLength() + + ipv4RespHeader.SerializedLength() + udpRespHeader.SerializedLength() + + response->SerializedLength(); + assert(size == expectedSize); + assert(size <= sizeof(buffer)); + + USPiSendFrame(buffer, size); + } + else + { + DEBUG_LOG("TFTP response was nullptr\r\n"); + } + + // TODO Reboot the Pi when a system file was received } - if (packet.blockNumber != currentBlockNumber + 1) - { - f_close(&outFile); - return std::unique_ptr(new ErrorPacket(0, "invalid block number")); - } - currentBlockNumber = packet.blockNumber; + // + // WriteReadRequestPacket + // + WriteReadRequestPacket::WriteReadRequestPacket() : Packet() {} + WriteReadRequestPacket::WriteReadRequestPacket(const Opcode opcode) : Packet(opcode) {} - unsigned int bytesWritten; - const auto result = - f_write(&outFile, packet.data.data(), packet.data.size(), &bytesWritten); - - if (result != FR_OK || bytesWritten != packet.data.size()) + size_t WriteReadRequestPacket::SerializedLength() const { - f_close(&outFile); - return std::unique_ptr(new ErrorPacket(0, "io error")); + return sizeof(opcode) + filename.size() + 1 + mode.size() + 1; } - if (packet.data.size() < TFTP_BLOCK_SIZE) + size_t WriteReadRequestPacket::Serialize(uint8_t* buffer, const size_t bufferSize) const { - // Close the file for the last packet. - f_close(&outFile); + if (bufferSize < SerializedLength()) + { + return 0; + } + + size_t i = 0; + buffer[i++] = static_cast(opcode) >> 8; + buffer[i++] = static_cast(opcode); + + i += filename.copy(reinterpret_cast(buffer + i), filename.size()); + buffer[i++] = 0; + + i += mode.copy(reinterpret_cast(buffer + i), mode.size()); + buffer[i++] = 0; + + return i; } - return std::unique_ptr( - new AcknowledgementPacket(currentBlockNumber)); - } - - void HandlePacket( - const Ethernet::Header ethernetReqHeader, - const Ipv4::Header ipv4ReqHeader, - const Udp::Header udpReqHeader, - const uint8_t* reqBuffer, - const size_t reqBufferSize) - { - const auto opcode = static_cast(reqBuffer[0] << 8 | reqBuffer[1]); - DEBUG_LOG("Received TFTP %u packet\r\n", static_cast(opcode)); - std::unique_ptr response; - - const auto payloadSize = udpReqHeader.length - udpReqHeader.SerializedLength(); - if (reqBufferSize < payloadSize) + size_t WriteReadRequestPacket::Deserialize(const uint8_t* buffer, const size_t bufferSize) { - DEBUG_LOG( - "Dropped TFTP packet (invalid buffer size %u, expected at least %u)\r\n", - reqBufferSize, - payloadSize); + // Can't use SerializedLength here, as it's variable. Check each field separately + // instead. + size_t i = 0; + + if (sizeof(Opcode) >= bufferSize - i) + return 0; + opcode = static_cast(buffer[i] << 8 | buffer[i + 1]); + i += sizeof(Opcode); + + // Check if there's a null terminator within the remaining buffer + size_t j; + for (j = i; j < bufferSize; j++) + if (buffer[j] == 0) + break; + if (j == bufferSize) + return 0; + + filename = std::string(reinterpret_cast(buffer + i)); + i += filename.size() + 1; + + // Check if there's a null terminator within the remaining buffer + for (j = i; j < bufferSize; j++) + if (buffer[j] == 0) + break; + if (j == bufferSize) + return 0; + + mode = std::string(reinterpret_cast(buffer + i)); + i += mode.size() + 1; + + return i; } - if (opcode == Opcode::WriteRequest) + // + // ErrorPacket + // + ErrorPacket::ErrorPacket() : Packet(Opcode::Error) {} + ErrorPacket::ErrorPacket(uint16_t errorCode, std::string message) : + Packet(Opcode::Error), errorCode(errorCode), message(message) { - response = handleTftpWriteRequest(reqBuffer, payloadSize); - } - else if (opcode == Opcode::Data) - { - response = handleTftpData(reqBuffer, payloadSize); - } - else - { - response = std::unique_ptr(new ErrorPacket(4, "not implemented yet")); } - if (response != nullptr) + size_t ErrorPacket::SerializedLength() const { - DEBUG_LOG("Sending TFTP response\r\n"); - Udp::Header udpRespHeader( - udpReqHeader.destinationPort, - udpReqHeader.sourcePort, - response->SerializedLength() + Udp::Header::SerializedLength()); - Ipv4::Header ipv4RespHeader( - Ipv4::Protocol::Udp, - Utils::Ipv4Address, - ipv4ReqHeader.sourceIp, - udpRespHeader.length + Ipv4::Header::SerializedLength()); - Ethernet::Header ethernetRespHeader( - Arp::ArpTable[ipv4RespHeader.destinationIp], - Utils::GetMacAddress(), - Ethernet::EtherType::Ipv4); - - size_t size = 0; - uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; - size += ethernetRespHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += ipv4RespHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += udpRespHeader.Serialize(buffer + size, sizeof(buffer) - size); - size += response->Serialize(buffer + size, sizeof(buffer) - size); - - const auto expectedSize = ethernetRespHeader.SerializedLength() + - ipv4RespHeader.SerializedLength() + udpRespHeader.SerializedLength() + - response->SerializedLength(); - assert(size == expectedSize); - assert(size <= sizeof(buffer)); - - USPiSendFrame(buffer, size); - } - else - { - DEBUG_LOG("TFTP response was nullptr\r\n"); + return sizeof(opcode) + sizeof(errorCode) + message.size() + 1; } - // TODO Reboot the Pi when a system file was received - } - - // - // WriteReadRequestPacket - // - WriteReadRequestPacket::WriteReadRequestPacket() : Packet() {} - WriteReadRequestPacket::WriteReadRequestPacket(const Opcode opcode) : Packet(opcode) {} - - size_t WriteReadRequestPacket::SerializedLength() const - { - return sizeof(opcode) + filename.size() + 1 + mode.size() + 1; - } - - size_t WriteReadRequestPacket::Serialize(uint8_t* buffer, const size_t bufferSize) const - { - if (bufferSize < SerializedLength()) + size_t ErrorPacket::Serialize(uint8_t* buffer, const size_t bufferSize) const { - return 0; + if (bufferSize < SerializedLength()) + { + return 0; + } + + size_t i = 0; + buffer[i++] = static_cast(opcode) >> 8; + buffer[i++] = static_cast(opcode); + buffer[i++] = errorCode >> 8; + buffer[i++] = errorCode; + + i += message.copy(reinterpret_cast(buffer + i), message.size()); + buffer[i++] = 0; + + return i; } - size_t i = 0; - buffer[i++] = static_cast(opcode) >> 8; - buffer[i++] = static_cast(opcode); + // + // AcknowledgementPacket + // + AcknowledgementPacket::AcknowledgementPacket() : Packet(Opcode::Acknowledgement) {} - i += filename.copy(reinterpret_cast(buffer + i), filename.size()); - buffer[i++] = 0; - - i += mode.copy(reinterpret_cast(buffer + i), mode.size()); - buffer[i++] = 0; - - return i; - } - - size_t WriteReadRequestPacket::Deserialize(const uint8_t* buffer, const size_t bufferSize) - { - // Can't use SerializedLength here, as it's variable. Check each field separately instead. - size_t i = 0; - - if (sizeof(Opcode) >= bufferSize - i) - return 0; - opcode = static_cast(buffer[i] << 8 | buffer[i + 1]); - i += sizeof(Opcode); - - // Check if there's a null terminator within the remaining buffer - size_t j; - for (j = i; j < bufferSize; j++) - if (buffer[j] == 0) - break; - if (j == bufferSize) - return 0; - - filename = std::string(reinterpret_cast(buffer + i)); - i += filename.size() + 1; - - // Check if there's a null terminator within the remaining buffer - for (j = i; j < bufferSize; j++) - if (buffer[j] == 0) - break; - if (j == bufferSize) - return 0; - - mode = std::string(reinterpret_cast(buffer + i)); - i += mode.size() + 1; - - return i; - } - - // - // ErrorPacket - // - ErrorPacket::ErrorPacket() : Packet(Opcode::Error) {} - ErrorPacket::ErrorPacket(uint16_t errorCode, std::string message) : - Packet(Opcode::Error), errorCode(errorCode), message(message) - { - } - - size_t ErrorPacket::SerializedLength() const - { - return sizeof(opcode) + sizeof(errorCode) + message.size() + 1; - } - - size_t ErrorPacket::Serialize(uint8_t* buffer, const size_t bufferSize) const - { - if (bufferSize < SerializedLength()) + AcknowledgementPacket::AcknowledgementPacket(uint16_t blockNumber) : + Packet(Opcode::Acknowledgement), blockNumber(blockNumber) { - return 0; } - size_t i = 0; - buffer[i++] = static_cast(opcode) >> 8; - buffer[i++] = static_cast(opcode); - buffer[i++] = errorCode >> 8; - buffer[i++] = errorCode; - - i += message.copy(reinterpret_cast(buffer + i), message.size()); - buffer[i++] = 0; - - return i; - } - - // - // AcknowledgementPacket - // - AcknowledgementPacket::AcknowledgementPacket() : Packet(Opcode::Acknowledgement) {} - - AcknowledgementPacket::AcknowledgementPacket(uint16_t blockNumber) : - Packet(Opcode::Acknowledgement), blockNumber(blockNumber) - { - } - - size_t AcknowledgementPacket::SerializedLength() const - { - return sizeof(opcode) + sizeof(blockNumber); - } - - size_t AcknowledgementPacket::Serialize(uint8_t* buffer, const size_t bufferSize) const - { - if (bufferSize < SerializedLength()) + size_t AcknowledgementPacket::SerializedLength() const { - return 0; + return sizeof(opcode) + sizeof(blockNumber); } - size_t i = 0; - buffer[i++] = static_cast(opcode) >> 8; - buffer[i++] = static_cast(opcode); - buffer[i++] = blockNumber >> 8; - buffer[i++] = blockNumber; - return i; - } - - // - // DataPacket - // - DataPacket::DataPacket() : Packet(Opcode::Data), blockNumber(0) {} - - size_t DataPacket::SerializedLength() const - { - return sizeof(opcode) + sizeof(blockNumber) + data.size(); - } - - size_t DataPacket::Serialize(uint8_t* buffer, const size_t bufferSize) const - { - if (bufferSize <= SerializedLength()) + size_t AcknowledgementPacket::Serialize(uint8_t* buffer, const size_t bufferSize) const { - return 0; + if (bufferSize < SerializedLength()) + { + return 0; + } + + size_t i = 0; + buffer[i++] = static_cast(opcode) >> 8; + buffer[i++] = static_cast(opcode); + buffer[i++] = blockNumber >> 8; + buffer[i++] = blockNumber; + return i; } - size_t i = 0; - buffer[i++] = static_cast(opcode) >> 8; - buffer[i++] = static_cast(opcode); - buffer[i++] = blockNumber >> 8; - buffer[i++] = blockNumber; + // + // DataPacket + // + DataPacket::DataPacket() : Packet(Opcode::Data), blockNumber(0) {} - std::memcpy(buffer + i, data.data(), data.size()); - i += data.size(); - - return i; - } - - size_t DataPacket::Deserialize(const uint8_t* buffer, const size_t bufferSize) - { - if (bufferSize < sizeof(opcode) + sizeof(blockNumber)) + size_t DataPacket::SerializedLength() const { - return 0; + return sizeof(opcode) + sizeof(blockNumber) + data.size(); } - opcode = static_cast(buffer[0] << 8 | buffer[1]); - blockNumber = buffer[2] << 8 | buffer[3]; - data = std::vector(buffer + 4, buffer + bufferSize); - return bufferSize; - } -} // namespace Net::Tftp + size_t DataPacket::Serialize(uint8_t* buffer, const size_t bufferSize) const + { + if (bufferSize <= SerializedLength()) + { + return 0; + } + + size_t i = 0; + buffer[i++] = static_cast(opcode) >> 8; + buffer[i++] = static_cast(opcode); + buffer[i++] = blockNumber >> 8; + buffer[i++] = blockNumber; + + std::memcpy(buffer + i, data.data(), data.size()); + i += data.size(); + + return i; + } + + size_t DataPacket::Deserialize(const uint8_t* buffer, const size_t bufferSize) + { + if (bufferSize < sizeof(opcode) + sizeof(blockNumber)) + { + return 0; + } + + opcode = static_cast(buffer[0] << 8 | buffer[1]); + blockNumber = buffer[2] << 8 | buffer[3]; + data = std::vector(buffer + 4, buffer + bufferSize); + return bufferSize; + } + } // namespace Tftp +} // namespace Net diff --git a/src/net-udp.cpp b/src/net-udp.cpp index 15d30a1..ebec972 100644 --- a/src/net-udp.cpp +++ b/src/net-udp.cpp @@ -4,95 +4,98 @@ #include "debug.h" -namespace Net::Udp +namespace Net { - Header::Header() {} - - Header::Header(Port sourcePort, Port destinationPort, uint16_t length) : - sourcePort(sourcePort), destinationPort(destinationPort), length(length), checksum(0) + namespace Udp { - } + Header::Header() {} - size_t Header::Serialize(uint8_t* buffer, const size_t bufferSize) const - { - if (bufferSize < SerializedLength()) + Header::Header(Port sourcePort, Port destinationPort, uint16_t length) : + sourcePort(sourcePort), destinationPort(destinationPort), length(length), checksum(0) { - return 0; } - size_t i = 0; - buffer[i++] = static_cast(sourcePort) >> 8; - buffer[i++] = static_cast(sourcePort); - buffer[i++] = static_cast(destinationPort) >> 8; - buffer[i++] = static_cast(destinationPort); - buffer[i++] = length >> 8; - buffer[i++] = length; - buffer[i++] = checksum >> 8; - buffer[i++] = checksum; - return i; - } - - size_t Header::Deserialize(const uint8_t* buffer, const size_t bufferSize) - { - if (bufferSize < Header::SerializedLength()) + size_t Header::Serialize(uint8_t* buffer, const size_t bufferSize) const { - return 0; + if (bufferSize < SerializedLength()) + { + return 0; + } + + size_t i = 0; + buffer[i++] = static_cast(sourcePort) >> 8; + buffer[i++] = static_cast(sourcePort); + buffer[i++] = static_cast(destinationPort) >> 8; + buffer[i++] = static_cast(destinationPort); + buffer[i++] = length >> 8; + buffer[i++] = length; + buffer[i++] = checksum >> 8; + buffer[i++] = checksum; + return i; } - sourcePort = static_cast(buffer[0] << 8 | buffer[1]); - destinationPort = static_cast(buffer[2] << 8 | buffer[3]); - length = buffer[4] << 8 | buffer[5]; - checksum = buffer[6] << 8 | buffer[7]; - return 8; - } - - void HandlePacket( - const Ethernet::Header ethernetHeader, - const Ipv4::Header ipv4Header, - const uint8_t* buffer, - const size_t bufferSize) - { - Header udpHeader; - const auto headerSize = udpHeader.Deserialize(buffer, bufferSize); - if (headerSize == 0 || headerSize != udpHeader.SerializedLength()) + size_t Header::Deserialize(const uint8_t* buffer, const size_t bufferSize) { + if (bufferSize < Header::SerializedLength()) + { + return 0; + } + + sourcePort = static_cast(buffer[0] << 8 | buffer[1]); + destinationPort = static_cast(buffer[2] << 8 | buffer[3]); + length = buffer[4] << 8 | buffer[5]; + checksum = buffer[6] << 8 | buffer[7]; + return 8; + } + + void HandlePacket( + const Ethernet::Header ethernetHeader, + const Ipv4::Header ipv4Header, + const uint8_t* buffer, + const size_t bufferSize) + { + Header udpHeader; + const auto headerSize = udpHeader.Deserialize(buffer, bufferSize); + if (headerSize == 0 || headerSize != udpHeader.SerializedLength()) + { + DEBUG_LOG( + "Dropped UDP header (invalid buffer size %u, expected at least %u)\r\n", + bufferSize, + Header::SerializedLength()); + return; + } + DEBUG_LOG( - "Dropped UDP header (invalid buffer size %u, expected at least %u)\r\n", - bufferSize, - Header::SerializedLength()); - return; - } + "UDP { src=%u, dst=%u, len=%u, chk=%u }\r\n", + static_cast(udpHeader.sourcePort), + static_cast(udpHeader.destinationPort), + udpHeader.length, + udpHeader.checksum); + if (bufferSize < udpHeader.length) + { + DEBUG_LOG( + "Dropped UDP packet (invalid buffer size %u, expected at least %u)\r\n", + bufferSize, + udpHeader.length); + return; + } - DEBUG_LOG( - "UDP { src=%u, dst=%u, len=%u, chk=%u }\r\n", - static_cast(udpHeader.sourcePort), - static_cast(udpHeader.destinationPort), - udpHeader.length, - udpHeader.checksum); - if (bufferSize < udpHeader.length) - { - DEBUG_LOG( - "Dropped UDP packet (invalid buffer size %u, expected at least %u)\r\n", - bufferSize, - udpHeader.length); - return; + if (udpHeader.destinationPort == Port::DhcpClient) + { + Dhcp::HandlePacket( + ethernetHeader, + buffer + udpHeader.SerializedLength(), + bufferSize - udpHeader.SerializedLength()); + } + else if (udpHeader.destinationPort == Port::Tftp) + { + Tftp::HandlePacket( + ethernetHeader, + ipv4Header, + udpHeader, + buffer + udpHeader.SerializedLength(), + bufferSize - udpHeader.SerializedLength()); + } } - - if (udpHeader.destinationPort == Port::DhcpClient) - { - Dhcp::HandlePacket( - ethernetHeader, - buffer + udpHeader.SerializedLength(), - bufferSize - udpHeader.SerializedLength()); - } - else if (udpHeader.destinationPort == Port::Tftp) - { - Tftp::HandlePacket( - ethernetHeader, - ipv4Header, - udpHeader, - buffer + udpHeader.SerializedLength(), - bufferSize - udpHeader.SerializedLength()); - } - } -} // namespace Net::Udp + } // namespace Udp +} // namespace Net diff --git a/src/net-udp.h b/src/net-udp.h index 8f2ef7b..d2f0ce4 100644 --- a/src/net-udp.h +++ b/src/net-udp.h @@ -6,37 +6,41 @@ #include "net-ethernet.h" #include "net-ipv4.h" -namespace Net::Udp +namespace Net { - enum class Port : uint16_t + namespace Udp { - DhcpServer = 67, - DhcpClient = 68, - Tftp = 69, // nice - }; - - struct Header - { - Port sourcePort; - Port destinationPort; - uint16_t length; - uint16_t checksum; - - Header(); - Header(Port sourcePort, Port destinationPort, uint16_t length); - - static constexpr size_t SerializedLength() + enum class Port : uint16_t { - return sizeof(sourcePort) + sizeof(destinationPort) + sizeof(length) + sizeof(checksum); - } + DhcpServer = 67, + DhcpClient = 68, + Tftp = 69, // nice + }; - size_t Serialize(uint8_t* buffer, const size_t size) const; - size_t Deserialize(const uint8_t* buffer, const size_t size); - }; + struct Header + { + Port sourcePort; + Port destinationPort; + uint16_t length; + uint16_t checksum; - void HandlePacket( - const Ethernet::Header ethernetHeader, - const Ipv4::Header ipv4Header, - const uint8_t* buffer, - const size_t size); -} // namespace Net::Udp + Header(); + Header(Port sourcePort, Port destinationPort, uint16_t length); + + static constexpr size_t SerializedLength() + { + return sizeof(sourcePort) + sizeof(destinationPort) + sizeof(length) + + sizeof(checksum); + } + + size_t Serialize(uint8_t* buffer, const size_t size) const; + size_t Deserialize(const uint8_t* buffer, const size_t size); + }; + + void HandlePacket( + const Ethernet::Header ethernetHeader, + const Ipv4::Header ipv4Header, + const uint8_t* buffer, + const size_t size); + } // namespace Udp +} // namespace Net diff --git a/src/net-utils.cpp b/src/net-utils.cpp index 3552de0..6f08388 100644 --- a/src/net-utils.cpp +++ b/src/net-utils.cpp @@ -3,97 +3,100 @@ #include "types.h" #include -namespace Net::Utils +namespace Net { - const MacAddress MacBroadcast{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - uint32_t Ipv4Address = 0xC0A80164; - - static const uint32_t crcTab32[256] = { - 0x00000000ul, 0x77073096ul, 0xEE0E612Cul, 0x990951BAul, 0x076DC419ul, 0x706AF48Ful, - 0xE963A535ul, 0x9E6495A3ul, 0x0EDB8832ul, 0x79DCB8A4ul, 0xE0D5E91Eul, 0x97D2D988ul, - 0x09B64C2Bul, 0x7EB17CBDul, 0xE7B82D07ul, 0x90BF1D91ul, 0x1DB71064ul, 0x6AB020F2ul, - 0xF3B97148ul, 0x84BE41DEul, 0x1ADAD47Dul, 0x6DDDE4EBul, 0xF4D4B551ul, 0x83D385C7ul, - 0x136C9856ul, 0x646BA8C0ul, 0xFD62F97Aul, 0x8A65C9ECul, 0x14015C4Ful, 0x63066CD9ul, - 0xFA0F3D63ul, 0x8D080DF5ul, 0x3B6E20C8ul, 0x4C69105Eul, 0xD56041E4ul, 0xA2677172ul, - 0x3C03E4D1ul, 0x4B04D447ul, 0xD20D85FDul, 0xA50AB56Bul, 0x35B5A8FAul, 0x42B2986Cul, - 0xDBBBC9D6ul, 0xACBCF940ul, 0x32D86CE3ul, 0x45DF5C75ul, 0xDCD60DCFul, 0xABD13D59ul, - 0x26D930ACul, 0x51DE003Aul, 0xC8D75180ul, 0xBFD06116ul, 0x21B4F4B5ul, 0x56B3C423ul, - 0xCFBA9599ul, 0xB8BDA50Ful, 0x2802B89Eul, 0x5F058808ul, 0xC60CD9B2ul, 0xB10BE924ul, - 0x2F6F7C87ul, 0x58684C11ul, 0xC1611DABul, 0xB6662D3Dul, 0x76DC4190ul, 0x01DB7106ul, - 0x98D220BCul, 0xEFD5102Aul, 0x71B18589ul, 0x06B6B51Ful, 0x9FBFE4A5ul, 0xE8B8D433ul, - 0x7807C9A2ul, 0x0F00F934ul, 0x9609A88Eul, 0xE10E9818ul, 0x7F6A0DBBul, 0x086D3D2Dul, - 0x91646C97ul, 0xE6635C01ul, 0x6B6B51F4ul, 0x1C6C6162ul, 0x856530D8ul, 0xF262004Eul, - 0x6C0695EDul, 0x1B01A57Bul, 0x8208F4C1ul, 0xF50FC457ul, 0x65B0D9C6ul, 0x12B7E950ul, - 0x8BBEB8EAul, 0xFCB9887Cul, 0x62DD1DDFul, 0x15DA2D49ul, 0x8CD37CF3ul, 0xFBD44C65ul, - 0x4DB26158ul, 0x3AB551CEul, 0xA3BC0074ul, 0xD4BB30E2ul, 0x4ADFA541ul, 0x3DD895D7ul, - 0xA4D1C46Dul, 0xD3D6F4FBul, 0x4369E96Aul, 0x346ED9FCul, 0xAD678846ul, 0xDA60B8D0ul, - 0x44042D73ul, 0x33031DE5ul, 0xAA0A4C5Ful, 0xDD0D7CC9ul, 0x5005713Cul, 0x270241AAul, - 0xBE0B1010ul, 0xC90C2086ul, 0x5768B525ul, 0x206F85B3ul, 0xB966D409ul, 0xCE61E49Ful, - 0x5EDEF90Eul, 0x29D9C998ul, 0xB0D09822ul, 0xC7D7A8B4ul, 0x59B33D17ul, 0x2EB40D81ul, - 0xB7BD5C3Bul, 0xC0BA6CADul, 0xEDB88320ul, 0x9ABFB3B6ul, 0x03B6E20Cul, 0x74B1D29Aul, - 0xEAD54739ul, 0x9DD277AFul, 0x04DB2615ul, 0x73DC1683ul, 0xE3630B12ul, 0x94643B84ul, - 0x0D6D6A3Eul, 0x7A6A5AA8ul, 0xE40ECF0Bul, 0x9309FF9Dul, 0x0A00AE27ul, 0x7D079EB1ul, - 0xF00F9344ul, 0x8708A3D2ul, 0x1E01F268ul, 0x6906C2FEul, 0xF762575Dul, 0x806567CBul, - 0x196C3671ul, 0x6E6B06E7ul, 0xFED41B76ul, 0x89D32BE0ul, 0x10DA7A5Aul, 0x67DD4ACCul, - 0xF9B9DF6Ful, 0x8EBEEFF9ul, 0x17B7BE43ul, 0x60B08ED5ul, 0xD6D6A3E8ul, 0xA1D1937Eul, - 0x38D8C2C4ul, 0x4FDFF252ul, 0xD1BB67F1ul, 0xA6BC5767ul, 0x3FB506DDul, 0x48B2364Bul, - 0xD80D2BDAul, 0xAF0A1B4Cul, 0x36034AF6ul, 0x41047A60ul, 0xDF60EFC3ul, 0xA867DF55ul, - 0x316E8EEFul, 0x4669BE79ul, 0xCB61B38Cul, 0xBC66831Aul, 0x256FD2A0ul, 0x5268E236ul, - 0xCC0C7795ul, 0xBB0B4703ul, 0x220216B9ul, 0x5505262Ful, 0xC5BA3BBEul, 0xB2BD0B28ul, - 0x2BB45A92ul, 0x5CB36A04ul, 0xC2D7FFA7ul, 0xB5D0CF31ul, 0x2CD99E8Bul, 0x5BDEAE1Dul, - 0x9B64C2B0ul, 0xEC63F226ul, 0x756AA39Cul, 0x026D930Aul, 0x9C0906A9ul, 0xEB0E363Ful, - 0x72076785ul, 0x05005713ul, 0x95BF4A82ul, 0xE2B87A14ul, 0x7BB12BAEul, 0x0CB61B38ul, - 0x92D28E9Bul, 0xE5D5BE0Dul, 0x7CDCEFB7ul, 0x0BDBDF21ul, 0x86D3D2D4ul, 0xF1D4E242ul, - 0x68DDB3F8ul, 0x1FDA836Eul, 0x81BE16CDul, 0xF6B9265Bul, 0x6FB077E1ul, 0x18B74777ul, - 0x88085AE6ul, 0xFF0F6A70ul, 0x66063BCAul, 0x11010B5Cul, 0x8F659EFFul, 0xF862AE69ul, - 0x616BFFD3ul, 0x166CCF45ul, 0xA00AE278ul, 0xD70DD2EEul, 0x4E048354ul, 0x3903B3C2ul, - 0xA7672661ul, 0xD06016F7ul, 0x4969474Dul, 0x3E6E77DBul, 0xAED16A4Aul, 0xD9D65ADCul, - 0x40DF0B66ul, 0x37D83BF0ul, 0xA9BCAE53ul, 0xDEBB9EC5ul, 0x47B2CF7Ful, 0x30B5FFE9ul, - 0xBDBDF21Cul, 0xCABAC28Aul, 0x53B39330ul, 0x24B4A3A6ul, 0xBAD03605ul, 0xCDD70693ul, - 0x54DE5729ul, 0x23D967BFul, 0xB3667A2Eul, 0xC4614AB8ul, 0x5D681B02ul, 0x2A6F2B94ul, - 0xB40BBE37ul, 0xC30C8EA1ul, 0x5A05DF1Bul, 0x2D02EF8Dul}; - - uint32_t Crc32(const uint8_t* buffer, size_t size) + namespace Utils { - uint32_t crc = 0xFFFFFFFFul; + const MacAddress MacBroadcast{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint32_t Ipv4Address = 0xC0A80164; - for (size_t a = 0; a < size; a++) + static const uint32_t crcTab32[256] = { + 0x00000000ul, 0x77073096ul, 0xEE0E612Cul, 0x990951BAul, 0x076DC419ul, 0x706AF48Ful, + 0xE963A535ul, 0x9E6495A3ul, 0x0EDB8832ul, 0x79DCB8A4ul, 0xE0D5E91Eul, 0x97D2D988ul, + 0x09B64C2Bul, 0x7EB17CBDul, 0xE7B82D07ul, 0x90BF1D91ul, 0x1DB71064ul, 0x6AB020F2ul, + 0xF3B97148ul, 0x84BE41DEul, 0x1ADAD47Dul, 0x6DDDE4EBul, 0xF4D4B551ul, 0x83D385C7ul, + 0x136C9856ul, 0x646BA8C0ul, 0xFD62F97Aul, 0x8A65C9ECul, 0x14015C4Ful, 0x63066CD9ul, + 0xFA0F3D63ul, 0x8D080DF5ul, 0x3B6E20C8ul, 0x4C69105Eul, 0xD56041E4ul, 0xA2677172ul, + 0x3C03E4D1ul, 0x4B04D447ul, 0xD20D85FDul, 0xA50AB56Bul, 0x35B5A8FAul, 0x42B2986Cul, + 0xDBBBC9D6ul, 0xACBCF940ul, 0x32D86CE3ul, 0x45DF5C75ul, 0xDCD60DCFul, 0xABD13D59ul, + 0x26D930ACul, 0x51DE003Aul, 0xC8D75180ul, 0xBFD06116ul, 0x21B4F4B5ul, 0x56B3C423ul, + 0xCFBA9599ul, 0xB8BDA50Ful, 0x2802B89Eul, 0x5F058808ul, 0xC60CD9B2ul, 0xB10BE924ul, + 0x2F6F7C87ul, 0x58684C11ul, 0xC1611DABul, 0xB6662D3Dul, 0x76DC4190ul, 0x01DB7106ul, + 0x98D220BCul, 0xEFD5102Aul, 0x71B18589ul, 0x06B6B51Ful, 0x9FBFE4A5ul, 0xE8B8D433ul, + 0x7807C9A2ul, 0x0F00F934ul, 0x9609A88Eul, 0xE10E9818ul, 0x7F6A0DBBul, 0x086D3D2Dul, + 0x91646C97ul, 0xE6635C01ul, 0x6B6B51F4ul, 0x1C6C6162ul, 0x856530D8ul, 0xF262004Eul, + 0x6C0695EDul, 0x1B01A57Bul, 0x8208F4C1ul, 0xF50FC457ul, 0x65B0D9C6ul, 0x12B7E950ul, + 0x8BBEB8EAul, 0xFCB9887Cul, 0x62DD1DDFul, 0x15DA2D49ul, 0x8CD37CF3ul, 0xFBD44C65ul, + 0x4DB26158ul, 0x3AB551CEul, 0xA3BC0074ul, 0xD4BB30E2ul, 0x4ADFA541ul, 0x3DD895D7ul, + 0xA4D1C46Dul, 0xD3D6F4FBul, 0x4369E96Aul, 0x346ED9FCul, 0xAD678846ul, 0xDA60B8D0ul, + 0x44042D73ul, 0x33031DE5ul, 0xAA0A4C5Ful, 0xDD0D7CC9ul, 0x5005713Cul, 0x270241AAul, + 0xBE0B1010ul, 0xC90C2086ul, 0x5768B525ul, 0x206F85B3ul, 0xB966D409ul, 0xCE61E49Ful, + 0x5EDEF90Eul, 0x29D9C998ul, 0xB0D09822ul, 0xC7D7A8B4ul, 0x59B33D17ul, 0x2EB40D81ul, + 0xB7BD5C3Bul, 0xC0BA6CADul, 0xEDB88320ul, 0x9ABFB3B6ul, 0x03B6E20Cul, 0x74B1D29Aul, + 0xEAD54739ul, 0x9DD277AFul, 0x04DB2615ul, 0x73DC1683ul, 0xE3630B12ul, 0x94643B84ul, + 0x0D6D6A3Eul, 0x7A6A5AA8ul, 0xE40ECF0Bul, 0x9309FF9Dul, 0x0A00AE27ul, 0x7D079EB1ul, + 0xF00F9344ul, 0x8708A3D2ul, 0x1E01F268ul, 0x6906C2FEul, 0xF762575Dul, 0x806567CBul, + 0x196C3671ul, 0x6E6B06E7ul, 0xFED41B76ul, 0x89D32BE0ul, 0x10DA7A5Aul, 0x67DD4ACCul, + 0xF9B9DF6Ful, 0x8EBEEFF9ul, 0x17B7BE43ul, 0x60B08ED5ul, 0xD6D6A3E8ul, 0xA1D1937Eul, + 0x38D8C2C4ul, 0x4FDFF252ul, 0xD1BB67F1ul, 0xA6BC5767ul, 0x3FB506DDul, 0x48B2364Bul, + 0xD80D2BDAul, 0xAF0A1B4Cul, 0x36034AF6ul, 0x41047A60ul, 0xDF60EFC3ul, 0xA867DF55ul, + 0x316E8EEFul, 0x4669BE79ul, 0xCB61B38Cul, 0xBC66831Aul, 0x256FD2A0ul, 0x5268E236ul, + 0xCC0C7795ul, 0xBB0B4703ul, 0x220216B9ul, 0x5505262Ful, 0xC5BA3BBEul, 0xB2BD0B28ul, + 0x2BB45A92ul, 0x5CB36A04ul, 0xC2D7FFA7ul, 0xB5D0CF31ul, 0x2CD99E8Bul, 0x5BDEAE1Dul, + 0x9B64C2B0ul, 0xEC63F226ul, 0x756AA39Cul, 0x026D930Aul, 0x9C0906A9ul, 0xEB0E363Ful, + 0x72076785ul, 0x05005713ul, 0x95BF4A82ul, 0xE2B87A14ul, 0x7BB12BAEul, 0x0CB61B38ul, + 0x92D28E9Bul, 0xE5D5BE0Dul, 0x7CDCEFB7ul, 0x0BDBDF21ul, 0x86D3D2D4ul, 0xF1D4E242ul, + 0x68DDB3F8ul, 0x1FDA836Eul, 0x81BE16CDul, 0xF6B9265Bul, 0x6FB077E1ul, 0x18B74777ul, + 0x88085AE6ul, 0xFF0F6A70ul, 0x66063BCAul, 0x11010B5Cul, 0x8F659EFFul, 0xF862AE69ul, + 0x616BFFD3ul, 0x166CCF45ul, 0xA00AE278ul, 0xD70DD2EEul, 0x4E048354ul, 0x3903B3C2ul, + 0xA7672661ul, 0xD06016F7ul, 0x4969474Dul, 0x3E6E77DBul, 0xAED16A4Aul, 0xD9D65ADCul, + 0x40DF0B66ul, 0x37D83BF0ul, 0xA9BCAE53ul, 0xDEBB9EC5ul, 0x47B2CF7Ful, 0x30B5FFE9ul, + 0xBDBDF21Cul, 0xCABAC28Aul, 0x53B39330ul, 0x24B4A3A6ul, 0xBAD03605ul, 0xCDD70693ul, + 0x54DE5729ul, 0x23D967BFul, 0xB3667A2Eul, 0xC4614AB8ul, 0x5D681B02ul, 0x2A6F2B94ul, + 0xB40BBE37ul, 0xC30C8EA1ul, 0x5A05DF1Bul, 0x2D02EF8Dul}; + + uint32_t Crc32(const uint8_t* buffer, size_t size) { - auto index = (crc ^ (uint32_t)*buffer++) & 0x000000FFul; - crc = (crc >> 8) ^ crcTab32[index]; + uint32_t crc = 0xFFFFFFFFul; + + for (size_t a = 0; a < size; a++) + { + auto index = (crc ^ (uint32_t)*buffer++) & 0x000000FFul; + crc = (crc >> 8) ^ crcTab32[index]; + } + + return crc ^ 0xFFFFFFFFul; } - return crc ^ 0xFFFFFFFFul; - } - - uint16_t InternetChecksum(const void* data, size_t size) - { - if (size == 0) - return ~0; - - auto u8data = static_cast(data); - - uint32_t sum = 0; - for (size_t i = 0; i < size - 1; i += 2) - sum += u8data[i] << 8 | u8data[i + 1]; - - if (size % 2 == 1) - sum += u8data[size - 1] << 8; - - sum = (sum >> 16) + (sum & 0xFFFF); - - return ~sum; - } - - MacAddress GetMacAddress() - { - static MacAddress macAddress{0}; - - if (macAddress == MacAddress{0}) + uint16_t InternetChecksum(const void* data, size_t size) { - USPiGetMACAddress(macAddress.data()); + if (size == 0) + return ~0; + + auto u8data = static_cast(data); + + uint32_t sum = 0; + for (size_t i = 0; i < size - 1; i += 2) + sum += u8data[i] << 8 | u8data[i + 1]; + + if (size % 2 == 1) + sum += u8data[size - 1] << 8; + + sum = (sum >> 16) + (sum & 0xFFFF); + + return ~sum; } - return macAddress; - } -} // namespace Net::Utils + MacAddress GetMacAddress() + { + static MacAddress macAddress{0}; + + if (macAddress == MacAddress{0}) + { + USPiGetMACAddress(macAddress.data()); + } + + return macAddress; + } + } // namespace Utils +} // namespace Net diff --git a/src/net-utils.h b/src/net-utils.h index 9340454..3849a36 100644 --- a/src/net-utils.h +++ b/src/net-utils.h @@ -2,13 +2,16 @@ #include #include -namespace Net::Utils +namespace Net { - typedef std::array MacAddress; - extern const MacAddress MacBroadcast; - extern uint32_t Ipv4Address; + namespace Utils + { + typedef std::array MacAddress; + extern const MacAddress MacBroadcast; + extern uint32_t Ipv4Address; - uint32_t Crc32(const uint8_t* buffer, size_t size); - uint16_t InternetChecksum(const void* data, size_t size); - MacAddress GetMacAddress(); -}; // namespace Net::Utils + uint32_t Crc32(const uint8_t* buffer, size_t size); + uint16_t InternetChecksum(const void* data, size_t size); + MacAddress GetMacAddress(); + } // namespace Utils +} // namespace Net diff --git a/src/net.cpp b/src/net.cpp index 68fb050..a64af8c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -58,7 +58,6 @@ namespace Net } } - void Update() { if (postInitializeTime && read32(ARM_SYSTIMER_CLO) > postInitializeTime)