mirror of
https://github.com/fergalmoran/ladybird.git
synced 2025-12-31 05:39:55 +00:00
Kernel: Bring up enough networking code that we can respond to ARP requests.
This is all pretty rickety but we can now respond to "arping" from the host while running inside QEMU. Very cool. :^)
This commit is contained in:
@@ -2,18 +2,24 @@
|
||||
#include <Kernel/EthernetFrameHeader.h>
|
||||
#include <Kernel/ARPPacket.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/EtherType.h>
|
||||
|
||||
static void handle_arp(const EthernetFrameHeader&, int frame_size);
|
||||
static void handle_ipv4(const EthernetFrameHeader&, int frame_size);
|
||||
|
||||
void NetworkTask_main()
|
||||
{
|
||||
auto* e1000_ptr = E1000NetworkAdapter::the();
|
||||
ASSERT(e1000_ptr);
|
||||
auto& e1000 = *e1000_ptr;
|
||||
|
||||
e1000.set_ipv4_address(IPv4Address(192, 168, 5, 2));
|
||||
ARPPacket arp;
|
||||
arp.hardware_type = 1; // Ethernet
|
||||
arp.hardware_address_length = 6; // MAC length
|
||||
arp.protocol_type = 0x0800; // IPv4
|
||||
arp.protocol_address_length = 4; // IP length
|
||||
arp.operation = 1; // 1 (request)
|
||||
arp.set_hardware_type(1); // Ethernet
|
||||
arp.set_hardware_address_length(sizeof(MACAddress));
|
||||
arp.set_protocol_type(EtherType::IPv4);
|
||||
arp.set_protocol_address_length(sizeof(IPv4Address));
|
||||
arp.set_operation(1); // Request
|
||||
e1000.send(MACAddress(), arp);
|
||||
|
||||
kprintf("NetworkTask: Enter main loop.\n");
|
||||
@@ -27,7 +33,74 @@ void NetworkTask_main()
|
||||
kprintf("NetworkTask: Packet is too small to be an Ethernet packet! (%d)\n", packet.size());
|
||||
continue;
|
||||
}
|
||||
auto* eth = (const EthernetFrameHeader*)packet.pointer();
|
||||
kprintf("NetworkTask: Handle packet from %s to %s\n", eth->source().to_string().characters(), eth->destination().to_string().characters());
|
||||
auto& eth = *(const EthernetFrameHeader*)packet.pointer();
|
||||
kprintf("NetworkTask: From %s to %s, ether_type=%w, packet_length=%u\n",
|
||||
eth.source().to_string().characters(),
|
||||
eth.destination().to_string().characters(),
|
||||
eth.ether_type(),
|
||||
packet.size()
|
||||
);
|
||||
|
||||
switch (eth.ether_type()) {
|
||||
case EtherType::ARP:
|
||||
handle_arp(eth, packet.size());
|
||||
break;
|
||||
case EtherType::IPv4:
|
||||
handle_ipv4(eth, packet.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_arp(const EthernetFrameHeader& eth, int frame_size)
|
||||
{
|
||||
constexpr int minimum_arp_frame_size = sizeof(EthernetFrameHeader) + sizeof(ARPPacket) + 4;
|
||||
if (frame_size < minimum_arp_frame_size) {
|
||||
kprintf("handle_arp: Frame too small (%d, need %d)\n", frame_size, minimum_arp_frame_size);
|
||||
return;
|
||||
}
|
||||
const ARPPacket& incoming_packet = *static_cast<const ARPPacket*>(eth.payload());
|
||||
if (incoming_packet.hardware_type() != 1 || incoming_packet.hardware_address_length() != sizeof(MACAddress)) {
|
||||
kprintf("handle_arp: Hardware type not ethernet (%w, len=%u)\n", incoming_packet.hardware_type(), incoming_packet.hardware_address_length());
|
||||
return;
|
||||
}
|
||||
if (incoming_packet.protocol_type() != EtherType::IPv4 || incoming_packet.protocol_address_length() != sizeof(IPv4Address)) {
|
||||
kprintf("handle_arp: Protocol type not IPv4 (%w, len=%u)\n", incoming_packet.hardware_type(), incoming_packet.protocol_address_length());
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ARP_DEBUG
|
||||
kprintf("handle_arp: operation=%w, sender=%s/%s, target=%s/%s\n",
|
||||
incoming_packet.operation(),
|
||||
incoming_packet.sender_hardware_address().to_string().characters(),
|
||||
incoming_packet.sender_protocol_address().to_string().characters(),
|
||||
incoming_packet.target_hardware_address().to_string().characters(),
|
||||
incoming_packet.target_protocol_address().to_string().characters()
|
||||
);
|
||||
#endif
|
||||
|
||||
// FIXME: Get the adapter through some kind of lookup by IPv4 address.
|
||||
auto& e1000 = *E1000NetworkAdapter::the();
|
||||
|
||||
if (incoming_packet.operation() == 1) {
|
||||
// Who has this IP address?
|
||||
if (e1000.ipv4_address() == incoming_packet.target_protocol_address()) {
|
||||
// We do!
|
||||
kprintf("handle_arp: Responding to ARP request for my IPv4 address (%s)\n", e1000.ipv4_address().to_string().characters());
|
||||
ARPPacket response;
|
||||
response.set_operation(2); // Response
|
||||
|
||||
response.set_target_hardware_address(incoming_packet.sender_hardware_address());
|
||||
response.set_target_protocol_address(incoming_packet.sender_protocol_address());
|
||||
response.set_sender_hardware_address(e1000.mac_address());
|
||||
response.set_sender_protocol_address(e1000.ipv4_address());
|
||||
|
||||
e1000.send(incoming_packet.sender_hardware_address(), response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_ipv4(const EthernetFrameHeader& eth, int frame_size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user