1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#include <Kernel/E1000NetworkAdapter.h>
#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.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");
for (;;) {
auto packet = e1000.dequeue_packet();
if (packet.is_null()) {
sleep(100);
continue;
}
if (packet.size() < sizeof(EthernetFrameHeader) + 4) {
kprintf("NetworkTask: Packet is too small to be an Ethernet packet! (%d)\n", packet.size());
continue;
}
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)
{
}
|