summaryrefslogtreecommitdiff
path: root/network/arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'network/arp.c')
-rw-r--r--network/arp.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/network/arp.c b/network/arp.c
new file mode 100644
index 0000000..eb8aca3
--- /dev/null
+++ b/network/arp.c
@@ -0,0 +1,83 @@
+#include <assert.h>
+#include <drivers/rtl8139.h>
+#include <network/arp.h>
+#include <network/bytes.h>
+#include <network/ethernet.h>
+#include <stdio.h>
+#include <string.h>
+
+struct ARP_DATA {
+ uint16_t htype; // Hardware type
+ uint16_t ptype; // Protocol type
+ uint8_t hlen; // Hardware address length (Ethernet = 6)
+ uint8_t plen; // Protocol address length (IPv4 = 4)
+ uint16_t opcode; // ARP Operation Code
+ uint8_t srchw[6]; // Source hardware address - hlen bytes (see above)
+ uint8_t srcpr[4]; // Source protocol address - plen bytes (see above).
+ // If IPv4 can just be a "u32" type.
+ uint8_t dsthw[6]; // Destination hardware address - hlen bytes (see above)
+ uint8_t dstpr[4]; // Destination protocol address - plen bytes (see
+ // above). If IPv4 can just be a "u32" type.
+};
+
+// FIXME: This is hardcoded, don't do this.
+uint8_t ip_address[4] = {10, 0, 2, 15};
+
+void print_mac(const char *str, uint8_t *mac) {
+ kprintf("%s: ", str);
+ for (int i = 0; i < 6; i++) {
+ kprintf("%x", mac[i]);
+ if (5 != i)
+ kprintf(":");
+ }
+ kprintf("\n");
+}
+
+void print_ip(const char *str, uint8_t *ip) {
+ kprintf("%s: ", str);
+ for (int i = 0; i < 4; i++) {
+ kprintf("%d", ip[i]);
+ if (3 != i)
+ kprintf(".");
+ }
+ kprintf("\n");
+}
+
+void handle_arp(uint8_t *payload) {
+ struct ARP_DATA *data = (struct ARP_DATA *)payload;
+
+ // Assert that communication is over ethernet
+ assert(1 == ntohs(data->htype));
+ // Assert it is a request
+ assert(0x0001 == ntohs(data->opcode));
+ // Assert that request uses IP
+ assert(0x0800 == ntohs(data->ptype));
+
+ assert(6 == data->hlen);
+ assert(4 == data->plen);
+ print_mac("srchw: ", data->srchw);
+ print_ip("srcpr: ", data->srcpr);
+
+ print_mac("dsthw: ", data->dsthw);
+ print_ip("dstpr: ", data->dstpr);
+
+ uint8_t mac[6];
+ get_mac_address(mac);
+ print_mac("THIS DEVICE MAC: ", mac);
+ assert(0 == memcmp(data->dstpr, ip_address, sizeof(uint8_t[4])));
+
+ // Now we have to construct a ARP response
+ struct ARP_DATA response;
+ response.htype = htons(1);
+ response.ptype = htons(0x0800);
+ response.opcode = htons(0x00002);
+ response.hlen = 6;
+ response.plen = 4;
+ get_mac_address(response.srchw);
+ memcpy(response.srcpr, ip_address, sizeof(uint8_t[4]));
+
+ memcpy(response.dsthw, data->srchw, sizeof(uint8_t[6]));
+ memcpy(response.dstpr, data->srcpr, sizeof(uint8_t[4]));
+
+ send_ethernet_packet(data->srchw, 0x0806, (uint8_t*)&response, sizeof(response));
+}