diff --git a/Makefile b/Makefile index bf7d55c..c5127ad 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ OBJS = armc-start.o armc-cstartup.o armc-cstubs.o armc-cppstubs.o \ Drive.o Pi1541.o DiskImage.o iec_bus.o iec_commands.o m6502.o m6522.o \ gcr.o prot.o lz.o emmc.o diskio.o options.o Screen.o SSD1306.o ScreenLCD.o \ Timer.o FileBrowser.o DiskCaddy.o ROMs.o InputMappings.o xga_font_data.o m8520.o wd177x.o Pi1581.o SpinLock.o \ - net.o net-tftp.o net-arp.o net-ethernet.o net-icmp.o net-ipv4.o net-udp.o + net.o net-tftp.o net-arp.o net-ethernet.o net-icmp.o net-ipv4.o net-udp.o net-dhcp.o SRCDIR = src OBJS := $(addprefix $(SRCDIR)/, $(OBJS)) diff --git a/src/main.cpp b/src/main.cpp index 7f30d46..8b13317 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,17 +2,17 @@ // Copyright(C) 2018 Stephen White // // This file is part of Pi1541. -// +// // Pi1541 is free software : you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // Pi1541 is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with Pi1541. If not, see . @@ -377,6 +377,7 @@ void updateNetwork() } auto ethernetHeader = EthernetFrameHeader::Deserialize(ipBuffer); + const auto offset = ethernetHeader.SerializedLength(); static bool announcementSent = false; if (!announcementSent) @@ -388,10 +389,10 @@ void updateNetwork() switch (ethernetHeader.type) { case ETHERTYPE_ARP: - HandleArpFrame(ethernetHeader, ipBuffer + ethernetHeader.SerializedLength()); + HandleArpFrame(ethernetHeader, ipBuffer + offset); break; case ETHERTYPE_IPV4: - HandleIpv4Packet(ethernetHeader, ipBuffer + ethernetHeader.SerializedLength()); + HandleIpv4Packet(ethernetHeader, ipBuffer + offset, sizeof(ipBuffer) - offset); break; } } @@ -659,7 +660,7 @@ void UpdateScreen() //if (options.GetSupportUARTInput()) // UpdateUartControls(refreshUartStatusDisplay, oldLED, oldMotor, oldATN, oldDATA, oldCLOCK, oldTrack, romIndex); - + updateNetwork(); // Go back to sleep. The USB irq will wake us up again. @@ -831,7 +832,7 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) #endif inputMappings->directDiskSwapRequest = 0; - // Force an update on all the buttons now before we start emulation mode. + // Force an update on all the buttons now before we start emulation mode. IEC_Bus::ReadBrowseMode(); bool extraRAM = options.GetExtraRAM(); @@ -995,7 +996,7 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) } while (ctAfter == ctBefore); #endif ctBefore = ctAfter; - + if (!refreshOutsAfterCPUStep) { IEC_Bus::ReadEmulationMode1541(); @@ -1085,7 +1086,7 @@ EXIT_TYPE Emulate1581(FileBrowser* fileBrowser) #endif inputMappings->directDiskSwapRequest = 0; - // Force an update on all the buttons now before we start emulation mode. + // Force an update on all the buttons now before we start emulation mode. IEC_Bus::ReadBrowseMode(); DataBusReadFn dataBusRead = read6502_1581; @@ -1440,7 +1441,7 @@ void emulator() IEC_Bus::WaitUntilReset(); emulating = IEC_COMMANDS; - + if ((exitReason == EXIT_RESET) && (options.GetOnResetChangeToStartingFolder() || selectedViaIECCommands)) fileBrowser->DisplayRoot(); // TO CHECK @@ -1462,9 +1463,9 @@ void emulator() //} #ifdef HAS_MULTICORE -extern "C" +extern "C" { - void run_core() + void run_core() { enable_MMU_and_IDCaches(); _enable_unaligned_access(); @@ -1978,7 +1979,7 @@ extern "C" #endif inputMappings = new InputMappings(); //USPiMouseRegisterStatusHandler(MouseHandler); - + while (!USPiEthernetAvailable()) { snprintf(tempBuffer, tempBufferSize, "Waiting for ethernet..."); screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); @@ -2048,4 +2049,3 @@ extern "C" #endif } } - diff --git a/src/net-dhcp.cpp b/src/net-dhcp.cpp new file mode 100644 index 0000000..6322807 --- /dev/null +++ b/src/net-dhcp.cpp @@ -0,0 +1,265 @@ +#include "net-dhcp.h" +#include "net-udp.h" +#include "net-ipv4.h" +#include "net-ethernet.h" +#include +#include +#include "types.h" +#include +#include + +namespace Net::Dhcp +{ + DhcpHeader::DhcpHeader() + {} + + DhcpHeader::DhcpHeader(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} + { + const auto mac = GetMacAddress(); + hardwareAddressLength = mac.size(); + std::memcpy(clientHardwareAddress.data(), mac.data(), mac.size()); + } + + size_t DhcpHeader::Serialize(uint8_t* buffer, const size_t size) const + { + if (size < DhcpHeader::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; + } + + size_t DhcpHeader::Deserialize( + DhcpHeader& out, const uint8_t* buffer, const size_t size + ) { + 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; + } + + static uint32_t transactionId; + static std::vector offeredIpAddresses; + static std::vector serverIpAddresses; + static std::vector serverMacAddresses; + static bool serverSelected; + + void sendRequest(uint32_t clientIpAddress, MacAddress serverMacAddress, uint32_t serverIpAddress) + { + const DhcpHeader dhcpHeader(Opcode::BootRequest, transactionId); + + size_t udpLength = + dhcpHeader.SerializedLength() + UdpDatagramHeader::SerializedLength(); + const UdpDatagramHeader udpHeader( + UDP_PORT_DHCP_CLIENT, UDP_PORT_DHCP_SERVER, udpLength); + + size_t ipv4Length = udpLength + Ipv4Header::SerializedLength(); + const Ipv4Header ipv4Header( + IP_PROTO_UDP, clientIpAddress, serverIpAddress, ipv4Length); + const EthernetFrameHeader ethernetHeader( + serverMacAddress, GetMacAddress(), ETHERTYPE_IPV4); + + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + size_t size = 0; + const auto expectedSize = + ethernetHeader.SerializedLength() + + ipv4Header.SerializedLength() + + udpHeader.SerializedLength() + + dhcpHeader.SerializedLength(); + + size += ethernetHeader.Serialize(buffer + size); + size += ipv4Header.Serialize(buffer + size); + size += udpHeader.Serialize(buffer + size); + size += dhcpHeader.Serialize(buffer + size, USPI_FRAME_BUFFER_SIZE - size); + + if (size != expectedSize) { + // TODO Log + return; + } + + USPiSendFrame(buffer, size); + } + + void discoverTimerHandler(unsigned int hTimer, void* nParam, void* nContext) + { + if (transactionId == 0 || offeredIpAddresses.empty()) + { + return; + } + + // Select the first IP address + const auto clientIpAddress = offeredIpAddresses[0]; + + // Send DHCP Requests to every server with that IP address. + for (size_t i = 0; i < serverIpAddresses.size(); i++) + { + sendRequest(clientIpAddress, serverMacAddresses[i], serverIpAddresses[i]); + } + } + + void SendDiscover() + { + transactionId = std::rand(); + offeredIpAddresses.clear(); + const DhcpHeader dhcpHeader(Opcode::BootRequest, transactionId); + + size_t udpLength = + dhcpHeader.SerializedLength() + UdpDatagramHeader::SerializedLength(); + const UdpDatagramHeader udpHeader( + UDP_PORT_DHCP_CLIENT, UDP_PORT_DHCP_SERVER, udpLength); + + size_t ipv4Length = udpLength + Ipv4Header::SerializedLength(); + const Ipv4Header ipv4Header(IP_PROTO_UDP, 0, 0xFFFFFFFF, ipv4Length); + const EthernetFrameHeader ethernetHeader(GetMacAddress(), ETHERTYPE_IPV4); + + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + size_t size = 0; + const auto expectedSize = + ethernetHeader.SerializedLength() + + ipv4Header.SerializedLength() + + udpHeader.SerializedLength() + + dhcpHeader.SerializedLength(); + + size += ethernetHeader.Serialize(buffer + size); + size += ipv4Header.Serialize(buffer + size); + size += udpHeader.Serialize(buffer + size); + size += dhcpHeader.Serialize(buffer + size, USPI_FRAME_BUFFER_SIZE - size); + + if (size != expectedSize) { + // TODO Log + return; + } + + USPiSendFrame(buffer, size); + + // Wait a second for responses + StartKernelTimer(1 * HZ, discoverTimerHandler, nullptr, nullptr); + } + + static void handleOfferPacket( + const EthernetFrameHeader ethernetHeader, const DhcpHeader dhcpHeader + ) { + offeredIpAddresses.push_back(dhcpHeader.yourIpAddress); + serverIpAddresses.push_back(dhcpHeader.serverIpAddress); + serverMacAddresses.push_back(ethernetHeader.macSource); + } + + static void handleAckPacket( + const EthernetFrameHeader ethernetHeader, const DhcpHeader dhcpHeader + ) { + Ipv4Address = dhcpHeader.yourIpAddress; + + // TODO Schedule handler for end of lease. + + transactionId = 0; + offeredIpAddresses.clear(); + serverIpAddresses.clear(); + serverMacAddresses.clear(); + serverSelected = false; + } + + void HandlePacket( + const EthernetFrameHeader& ethernetHeader, const uint8_t* buffer, size_t size + ) { + auto dhcpHeader = DhcpHeader(); + const auto dhcpSize = DhcpHeader::Deserialize(dhcpHeader, buffer, size); + if (dhcpSize == 0) { + // TODO log + return; + } + + if (dhcpHeader.opcode != Opcode::BootReply) return; + if (dhcpHeader.hardwareAddressType != 1) return; + if (dhcpHeader.hardwareAddressLength != 6) return; + if (dhcpHeader.transactionId != transactionId) return; + + if (!serverSelected) + { + handleOfferPacket(ethernetHeader, dhcpHeader); + } + else + { + handleAckPacket(ethernetHeader, dhcpHeader); + } + } +} // namespace Net::Dhcp diff --git a/src/net-dhcp.h b/src/net-dhcp.h new file mode 100644 index 0000000..afcb2dc --- /dev/null +++ b/src/net-dhcp.h @@ -0,0 +1,93 @@ +#pragma once +#include "net.h" + +namespace Net::Dhcp +{ + enum class Opcode : uint8_t + { + BootRequest = 1, + BootReply = 2, + }; + + struct DhcpHeader + { + /// 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; + + DhcpHeader(); + DhcpHeader(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( + DhcpHeader& out, const uint8_t* buffer, const size_t size); + }; + + void SendDiscover(); + void HandlePacket( + const EthernetFrameHeader& ethernetHeader, const uint8_t* buffer, size_t size); +} // namespace Net::Dhcp diff --git a/src/net-ethernet.cpp b/src/net-ethernet.cpp index cbf2e24..6a90867 100644 --- a/src/net-ethernet.cpp +++ b/src/net-ethernet.cpp @@ -4,37 +4,48 @@ EthernetFrameHeader::EthernetFrameHeader() {} EthernetFrameHeader::EthernetFrameHeader(std::uint16_t type) : - macDestination{255, 255, 255, 255, 255, 255}, - macSource{0, 0, 0, 0, 0, 0}, - type(type) - {} + macDestination{255, 255, 255, 255, 255, 255}, + macSource{0, 0, 0, 0, 0, 0}, + type(type) +{} EthernetFrameHeader::EthernetFrameHeader( - MacAddress macDestination, MacAddress macSource, uint16_t type -) : macDestination(macDestination), macSource(macSource), type(type) + MacAddress macSource, uint16_t type +) : + macDestination{255, 255, 255, 255, 255, 255}, + macSource(macSource), + type(type) +{} + +EthernetFrameHeader::EthernetFrameHeader( + MacAddress macDestination, MacAddress macSource, uint16_t type +) : + macDestination(macDestination), + macSource(macSource), + type(type) {} std::size_t EthernetFrameHeader::Serialize(uint8_t* buffer) const { - std::size_t i = 0; + std::size_t i = 0; - std::memcpy(buffer + i, macDestination.data(), macDestination.size()); - i += sizeof(macDestination); + std::memcpy(buffer + i, macDestination.data(), macDestination.size()); + i += sizeof(macDestination); - std::memcpy(buffer + i, macSource.data(), macSource.size()); - i += sizeof(macSource); + std::memcpy(buffer + i, macSource.data(), macSource.size()); + i += sizeof(macSource); - buffer[i++] = type >> 8; - buffer[i++] = type; + buffer[i++] = type >> 8; + buffer[i++] = type; - return i; + return i; } EthernetFrameHeader EthernetFrameHeader::Deserialize(const uint8_t* buffer) { - EthernetFrameHeader self; - std::memcpy(self.macDestination.data(), buffer + 0, self.macDestination.size()); - std::memcpy(self.macSource.data(), buffer + 6, self.macSource.size()); - self.type = buffer[12] << 8 | buffer[13]; - return self; + EthernetFrameHeader self; + std::memcpy(self.macDestination.data(), buffer + 0, self.macDestination.size()); + std::memcpy(self.macSource.data(), buffer + 6, self.macSource.size()); + self.type = buffer[12] << 8 | buffer[13]; + return self; } diff --git a/src/net-ethernet.h b/src/net-ethernet.h index 32258bd..b5ccfa7 100644 --- a/src/net-ethernet.h +++ b/src/net-ethernet.h @@ -9,6 +9,7 @@ struct EthernetFrameHeader EthernetFrameHeader(); EthernetFrameHeader(std::uint16_t type); + EthernetFrameHeader(MacAddress macSource, uint16_t type); EthernetFrameHeader(MacAddress macDestination, MacAddress macSource, uint16_t type); constexpr static std::size_t SerializedLength() diff --git a/src/net-tftp.cpp b/src/net-tftp.cpp index 62770e5..54bc46f 100644 --- a/src/net-tftp.cpp +++ b/src/net-tftp.cpp @@ -71,9 +71,15 @@ static std::unique_ptr handleTftpWriteRequest(const uint8_t* data) return response; } -static std::unique_ptr handleTftpData(const uint8_t* data, size_t length) +static std::unique_ptr handleTftpData(const uint8_t* buffer, size_t size) { - auto packet = TftpDataPacket::Deserialize(data, length); + TftpDataPacket packet; + const auto tftpSize = TftpDataPacket::Deserialize(packet, buffer, size); + if (size == 0) + { + // TODO log + return nullptr; + } if (packet.blockNumber != currentBlockNumber + 1) { @@ -268,11 +274,15 @@ size_t TftpAcknowledgementPacket::Serialize(uint8_t* buffer) const // TftpDataPacket::TftpDataPacket() : opcode(TFTP_OP_DATA) {} -TftpDataPacket TftpDataPacket::Deserialize(const uint8_t* buffer, size_t length) -{ - TftpDataPacket self; - self.opcode = buffer[0] << 8 | buffer[1]; - self.blockNumber = buffer[2] << 8 | buffer[3]; - self.data = std::vector(buffer + 4, buffer + length); - return self; +size_t TftpDataPacket::Deserialize( + TftpDataPacket& out, const uint8_t* buffer, size_t size +) { + if (size < sizeof(opcode) + sizeof(blockNumber)) { + return 0; + } + + out.opcode = buffer[0] << 8 | buffer[1]; + out.blockNumber = buffer[2] << 8 | buffer[3]; + out.data = std::vector(buffer + 4, buffer + size); + return size; } diff --git a/src/net-tftp.h b/src/net-tftp.h index 4042633..05ef1a0 100644 --- a/src/net-tftp.h +++ b/src/net-tftp.h @@ -64,5 +64,6 @@ struct TftpDataPacket std::vector data; TftpDataPacket(); - static TftpDataPacket Deserialize(const uint8_t* buffer, size_t length); + static size_t Deserialize( + TftpDataPacket& out, const uint8_t* buffer, size_t length); }; diff --git a/src/net-udp.cpp b/src/net-udp.cpp index 48a036a..83faf85 100644 --- a/src/net-udp.cpp +++ b/src/net-udp.cpp @@ -14,7 +14,7 @@ UdpDatagramHeader::UdpDatagramHeader( checksum(0) {} -size_t UdpDatagramHeader::Serialize(uint8_t* buffer) +size_t UdpDatagramHeader::Serialize(uint8_t* buffer) const { size_t i = 0; buffer[i++] = sourcePort >> 8; diff --git a/src/net-udp.h b/src/net-udp.h index 2084a54..c18d17a 100644 --- a/src/net-udp.h +++ b/src/net-udp.h @@ -22,6 +22,6 @@ struct UdpDatagramHeader sizeof(checksum); } - size_t Serialize(uint8_t* buffer); + size_t Serialize(uint8_t* buffer) const; static UdpDatagramHeader Deserialize(const uint8_t* buffer); }; diff --git a/src/net.cpp b/src/net.cpp index 5c59a12..5670db3 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -6,6 +6,7 @@ #include "net-icmp.h" #include "net-ipv4.h" #include "net-udp.h" +#include "net-dhcp.h" #include "net.h" #include "types.h" @@ -82,9 +83,11 @@ void HandleArpFrame(const EthernetFrameHeader ethernetHeader, uint8_t* buffer) // // IPv4 // -void HandleIpv4Packet(const EthernetFrameHeader ethernetHeader, const uint8_t* buffer) -{ +void HandleIpv4Packet( + const EthernetFrameHeader ethernetHeader, const uint8_t* buffer, const size_t size +) { const auto ipv4Header = Ipv4Header::Deserialize(buffer); + const auto offset = Ipv4Header::SerializedLength(); // Update ARP table ArpTable.insert(std::make_pair(ipv4Header.sourceIp, ethernetHeader.macSource)); @@ -100,8 +103,7 @@ void HandleIpv4Packet(const EthernetFrameHeader ethernetHeader, const uint8_t* b } else if (ipv4Header.protocol == IP_PROTO_UDP) { - HandleUdpDatagram( - ethernetHeader, ipv4Header, buffer + ipv4Header.SerializedLength()); + HandleUdpDatagram(ethernetHeader, ipv4Header, buffer + offset, size - offset); } } @@ -111,12 +113,20 @@ void HandleIpv4Packet(const EthernetFrameHeader ethernetHeader, const uint8_t* b void HandleUdpDatagram( const EthernetFrameHeader ethernetHeader, const Ipv4Header ipv4Header, - const uint8_t* buffer -) -{ + const uint8_t* buffer, + const size_t size +) { const auto udpHeader = UdpDatagramHeader::Deserialize(buffer); - if (udpHeader.destinationPort == 69) // nice + if (udpHeader.destinationPort == UDP_PORT_DHCP_CLIENT) + { + Net::Dhcp::HandlePacket( + ethernetHeader, + buffer + udpHeader.SerializedLength(), + size - udpHeader.SerializedLength() + ); + } + else if (udpHeader.destinationPort == UDP_PORT_TFTP) { HandleTftpDatagram( ethernetHeader, @@ -155,8 +165,10 @@ void SendIcmpEchoRequest(MacAddress mac, uint32_t ip) void HandleIcmpFrame(const uint8_t* buffer) { + // TODO Don't re-parse the upper layers size_t requestSize = 0; - const auto requestEthernetHeader = EthernetFrameHeader::Deserialize(buffer + requestSize); + const auto requestEthernetHeader = + EthernetFrameHeader::Deserialize(buffer + requestSize); requestSize += requestEthernetHeader.SerializedLength(); const auto requestIpv4Header = Ipv4Header::Deserialize(buffer + requestSize); requestSize += requestIpv4Header.SerializedLength(); @@ -165,7 +177,8 @@ void HandleIcmpFrame(const uint8_t* buffer) if (requestIcmpHeader.type == ICMP_ECHO_REQUEST) { - const auto requestEchoHeader = IcmpEchoHeader::Deserialize(buffer + requestSize); + const auto requestEchoHeader = + IcmpEchoHeader::Deserialize(buffer + requestSize); requestSize += requestEchoHeader.SerializedLength(); const IcmpPacketHeader responseIcmpHeader(ICMP_ECHO_REPLY, 0); @@ -309,7 +322,7 @@ MacAddress GetMacAddress() return macAddress; } -const uint32_t Ipv4Address = 0xC0A80164; +uint32_t Ipv4Address = 0xC0A80164; const MacAddress MacBroadcast{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; bool FileUploaded = false; diff --git a/src/net.h b/src/net.h index dea68d5..3123512 100644 --- a/src/net.h +++ b/src/net.h @@ -15,6 +15,12 @@ enum ArpOperation { ARP_OPERATION_REPLY = 2, }; +enum UdpPort { + UDP_PORT_DHCP_SERVER = 67, + UDP_PORT_DHCP_CLIENT = 68, + UDP_PORT_TFTP = 69, // nice +}; + typedef std::array MacAddress; struct EthernetFrameHeader; @@ -41,7 +47,8 @@ void SendArpAnnouncement(MacAddress mac, uint32_t ip); // // IPv4 // -void HandleIpv4Packet(const EthernetFrameHeader ethernetHeader, const uint8_t* buffer); +void HandleIpv4Packet( + const EthernetFrameHeader ethernetHeader, const uint8_t* buffer, const size_t size); // // UDP @@ -49,7 +56,8 @@ void HandleIpv4Packet(const EthernetFrameHeader ethernetHeader, const uint8_t* b void HandleUdpDatagram( const EthernetFrameHeader ethernetHeader, const Ipv4Header ipv4Header, - const uint8_t* buffer + const uint8_t* buffer, + const size_t size ); void HandleTftpDatagram( @@ -73,7 +81,7 @@ std::uint16_t InternetChecksum(const void* data, std::size_t size); MacAddress GetMacAddress(); extern const MacAddress MacBroadcast; -extern const uint32_t Ipv4Address; +extern uint32_t Ipv4Address; extern bool FileUploaded; extern std::unordered_map ArpTable;