diff options
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Net/NetworkTask.cpp | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index 4d0a92a87d..8a980a7916 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -20,11 +20,11 @@ //#define UDP_DEBUG //#define TCP_DEBUG -static void handle_arp(const EthernetFrameHeader&, int frame_size); -static void handle_ipv4(const EthernetFrameHeader&, int frame_size); -static void handle_icmp(const EthernetFrameHeader&, int frame_size); -static void handle_udp(const EthernetFrameHeader&, int frame_size); -static void handle_tcp(const EthernetFrameHeader&, int frame_size); +static void handle_arp(const EthernetFrameHeader&, size_t frame_size); +static void handle_ipv4(const EthernetFrameHeader&, size_t frame_size); +static void handle_icmp(const EthernetFrameHeader&, const IPv4Packet&); +static void handle_udp(const IPv4Packet&); +static void handle_tcp(const IPv4Packet&); Lockable<HashMap<IPv4Address, MACAddress>>& arp_table() { @@ -118,9 +118,9 @@ void NetworkTask_main() } } -void handle_arp(const EthernetFrameHeader& eth, int frame_size) +void handle_arp(const EthernetFrameHeader& eth, size_t frame_size) { - constexpr int minimum_arp_frame_size = sizeof(EthernetFrameHeader) + sizeof(ARPPacket); + constexpr size_t minimum_arp_frame_size = sizeof(EthernetFrameHeader) + sizeof(ARPPacket); if (frame_size < minimum_arp_frame_size) { kprintf("handle_arp: Frame too small (%d, need %d)\n", frame_size, minimum_arp_frame_size); return; @@ -180,9 +180,9 @@ void handle_arp(const EthernetFrameHeader& eth, int frame_size) } } -void handle_ipv4(const EthernetFrameHeader& eth, int frame_size) +void handle_ipv4(const EthernetFrameHeader& eth, size_t frame_size) { - constexpr int minimum_ipv4_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet); + constexpr size_t minimum_ipv4_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet); if (frame_size < minimum_ipv4_frame_size) { kprintf("handle_ipv4: Frame too small (%d, need %d)\n", frame_size, minimum_ipv4_frame_size); return; @@ -208,21 +208,19 @@ void handle_ipv4(const EthernetFrameHeader& eth, int frame_size) switch ((IPv4Protocol)packet.protocol()) { case IPv4Protocol::ICMP: - return handle_icmp(eth, frame_size); + return handle_icmp(eth, packet); case IPv4Protocol::UDP: - return handle_udp(eth, frame_size); + return handle_udp(packet); case IPv4Protocol::TCP: - return handle_tcp(eth, frame_size); + return handle_tcp(packet); default: kprintf("handle_ipv4: Unhandled protocol %u\n", packet.protocol()); break; } } -void handle_icmp(const EthernetFrameHeader& eth, int frame_size) +void handle_icmp(const EthernetFrameHeader& eth, const IPv4Packet& ipv4_packet) { - (void)frame_size; - auto& ipv4_packet = *static_cast<const IPv4Packet*>(eth.payload()); auto& icmp_header = *static_cast<const ICMPHeader*>(ipv4_packet.payload()); #ifdef ICMP_DEBUG kprintf("handle_icmp: source=%s, destination=%s, type=%b, code=%b\n", @@ -266,10 +264,12 @@ void handle_icmp(const EthernetFrameHeader& eth, int frame_size) } } -void handle_udp(const EthernetFrameHeader& eth, int frame_size) +void handle_udp(const IPv4Packet& ipv4_packet) { - (void)frame_size; - auto& ipv4_packet = *static_cast<const IPv4Packet*>(eth.payload()); + if (ipv4_packet.payload_size() < sizeof(UDPPacket)) { + kprintf("handle_udp: Packet too small (%u, need %zu)\n", ipv4_packet.payload_size()); + return; + } auto adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination()); if (!adapter) { @@ -298,18 +298,26 @@ void handle_udp(const EthernetFrameHeader& eth, int frame_size) socket->did_receive(ipv4_packet.source(), udp_packet.source_port(), KBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); } -void handle_tcp(const EthernetFrameHeader& eth, int frame_size) +void handle_tcp(const IPv4Packet& ipv4_packet) { - (void)frame_size; - auto& ipv4_packet = *static_cast<const IPv4Packet*>(eth.payload()); - - auto adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination()); - if (!adapter) { - kprintf("handle_tcp: this packet is not for me, it's for %s\n", ipv4_packet.destination().to_string().characters()); + if (ipv4_packet.payload_size() < sizeof(TCPPacket)) { + kprintf("handle_tcp: IPv4 payload is too small to be a TCP packet (%u, need %zu)\n", ipv4_packet.payload_size(), sizeof(TCPPacket)); return; } auto& tcp_packet = *static_cast<const TCPPacket*>(ipv4_packet.payload()); + + size_t minimum_tcp_header_size = 5 * sizeof(u32); + size_t maximum_tcp_header_size = 15 * sizeof(u32); + if (tcp_packet.header_size() < minimum_tcp_header_size || tcp_packet.header_size() > maximum_tcp_header_size) { + kprintf("handle_tcp: TCP packet header has invalid size %zu\n", tcp_packet.header_size()); + } + + if (ipv4_packet.payload_size() < tcp_packet.header_size()) { + kprintf("handle_tcp: IPv4 payload is smaller than TCP header claims (%u, supposedly %u)\n", ipv4_packet.payload_size(), tcp_packet.header_size()); + return; + } + size_t payload_size = ipv4_packet.payload_size() - tcp_packet.header_size(); #ifdef TCP_DEBUG @@ -329,6 +337,12 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size) payload_size); #endif + auto adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination()); + if (!adapter) { + kprintf("handle_tcp: this packet is not for me, it's for %s\n", ipv4_packet.destination().to_string().characters()); + return; + } + IPv4SocketTuple tuple(ipv4_packet.destination(), tcp_packet.destination_port(), ipv4_packet.source(), tcp_packet.source_port()); #ifdef TCP_DEBUG |