BarryServer : Git

All the code for all my projects
// BarryServer : Git / Orion / commit / d41a53cbc7d055b1c00cf0a339dbed6925f4f02c / net / arp.c

// Related

Orion

Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)
diff --git a/net/arp.c b/net/arp.c
new file mode 100644
index 0000000..8906abb
--- /dev/null
+++ b/net/arp.c
@@ -0,0 +1,118 @@
+/*
+ * This file contains the implementation of ARP for the Network Stack.  It
+ * handles converting IP addresses to MAC addresses, and sits between the
+ * Network layer and the Ethernet layer.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include "net.h"
+#include "../mem/heap.h"
+#include "../screen.h"
+
+typedef struct ARPCacheEntry ARPCacheEntry;
+
+/* Structure for an ARP Cache Entry */
+struct ARPCacheEntry {
+	uint8_t mac[6], ip[4];
+	ARPCacheEntry *next;
+};
+
+/* Structure for an ARP Packet */
+typedef struct Packet {
+	uint16_t hardwareType;
+	uint16_t protocolType;
+	uint8_t hardwareSize;
+	uint8_t protocolSize;
+	uint16_t opcode;
+	uint8_t srcMac[6], srcIp[4];
+	uint8_t dstMac[6], dstIp[4];
+} __attribute__((packed)) Packet;
+
+ARPCacheEntry *arpCache;
+
+/* Request a MAC address from IP with ARP */
+void
+arp_request(NetIF *netif, uint8_t dstIp[4], uint8_t *res)
+{
+	uint8_t dstMac[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	Packet packet = {
+		.hardwareType = htons(netif->type),
+		.protocolType = htons(0x0800), /* EtherType IPv4 */
+		.hardwareSize = 6,
+		.protocolSize = 4,
+		.opcode = htons(0x0001), /* ARP Request */
+	};
+	memcpy(packet.srcMac, netif->mac, 6);
+	memcpy(packet.srcIp, netif->ip, 4);
+	memcpy(packet.dstMac, dstMac, 6);
+	memcpy(packet.dstIp, dstIp, 4);
+
+	ethernet_send_frame(netif, dstMac, 0x0806, &packet, sizeof(Packet));
+
+	if (!res)
+		return;
+	/* Wait for result */
+	ARPCacheEntry *ce;
+search:
+	for (ce = arpCache; ce; ce = ce->next)
+		if (!memcmp(ce->ip, dstIp, 4))
+			break;
+	if (!ce)
+		goto search;
+	memcpy(res, ce->mac, 6);
+}
+
+/* Reply to an ARP Request */
+void
+arp_reply(NetIF *netif, Packet *request)
+{
+	Packet reply = {
+		.hardwareType = htons(netif->type),
+		.hardwareSize = request->hardwareSize,
+		.protocolType = htons(request->protocolType),
+		.protocolSize = request->protocolSize,
+		.opcode = htons(0x0002), /* ARP Reply */
+	};
+	memcpy(reply.srcMac, netif->mac, 6);
+	memcpy(reply.srcIp, netif->ip, 4);
+	memcpy(reply.dstMac, request->srcMac, 6);
+	memcpy(reply.dstIp, request->srcIp, 4);
+
+	ethernet_send_frame(netif, request->srcMac, 0x0806, &reply,
+	                    sizeof(Packet));
+}
+
+/* Handle an incoming ARP packet */
+void
+arp_receive_packet(NetIF *netif, void *data, size_t len)
+{
+	Packet packet;
+	memcpy(&packet, data, sizeof(Packet));
+	packet.hardwareType = ntohs(packet.hardwareType);
+	packet.protocolType = ntohs(packet.protocolType);
+	packet.opcode = ntohs(packet.opcode);
+
+	switch (packet.opcode) {
+	case 0x0001: /* ARP Request */
+		if (!memcmp(packet.dstIp, netif->ip, 4))
+			arp_reply(netif, &packet);
+		/* FALLTHROUGH */
+	case 0x0002: /* ARP Reply */
+		ARPCacheEntry *ce;
+		for (ce = arpCache; ce; ce = ce->next)
+			if (!memcmp(ce->ip, packet.srcIp, 4))
+				break;
+		if (ce) {
+			memcpy(ce->mac, packet.srcMac, 6);
+			break;
+		}
+		ce = kmalloc(sizeof(ARPCacheEntry));
+		memcpy(ce->mac, packet.srcMac, 6);
+		memcpy(ce->ip, packet.srcIp, 4);
+		ce->next = arpCache;
+		arpCache = ce;
+		break;
+	}
+}