|
@@ -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)
|
|
|
+{
|
|
|
+
|
|
|
+}
|