BarryServer : Git

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

// Related

Orion

Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)
diff --git a/net/ipv4.c b/net/ipv4.c
new file mode 100644
index 0000000..ce27ba7
--- /dev/null
+++ b/net/ipv4.c
@@ -0,0 +1,97 @@
+/*
+ * This file contains the IPv4 implementation in the Network Stack.  It sits
+ * above the Ethernet layer, but makes heavy use of the Address Resolution
+ * Protocol.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include "net.h"
+#include "../mem/heap.h"
+#include "../screen.h"
+
+/* Structure for an IPv4 Packet Header */
+typedef struct Header {
+	/* ihl and version are swapped to work with network byte order */
+	uint8_t ihl : 4;
+	uint8_t version : 4;
+	uint8_t service;
+	uint16_t len;
+	uint16_t id;
+	uint16_t flags;
+	uint8_t ttl;
+	uint8_t proto;
+	uint16_t checksum;
+	uint32_t src, dst;
+} __attribute__((packed)) Header;
+
+uint16_t ipid = 1;
+
+/* Calculate an IPv4 checksum */
+static uint16_t
+ipv4_checksum(void *addr, size_t len)
+{
+	register uint32_t sum = 0;
+	while (len > 1) {
+		sum += *(uint16_t *) addr++;
+		len -= 2;
+	}
+	if (len > 0)
+		sum += *(uint8_t *) addr;
+
+	while (sum >> 16)
+		sum = (sum & 0xFFFF) + (sum >> 16);
+
+	return ~sum;
+}
+
+/* Receive an IPv4 Packet */
+void
+ipv4_receive_packet(NetIF *netif, void *data, size_t len)
+{
+	Header header;
+	memcpy(&header, data, sizeof(Header));
+
+	uint8_t src[4];
+	memcpy(src, &header.src, 4);
+	kprintf("Received IPv4 Packet from %d.%d.%d.%d",
+	        src[0], src[1], src[2], src[3]);
+
+	/* Handle packet */
+	switch (header.proto) {
+//	case 0x01: /* ICMP */
+//		break;
+//	case 0x02: /* IGMP */
+//	case 0x06: /* TCP */
+//	case 0x11: /* UDP */
+	default:
+		kprintf("Unhandled IP packet (proto %d)", header.proto);
+	}
+}
+
+/* Transmit an IPv4 Packet */
+void
+ipv4_send_packet(NetIF *netif, uint8_t dst[4], uint8_t proto, uint16_t flags,
+                 void *data, size_t len)
+{
+	Header header;
+	header.ihl = 5;
+	header.version = 4;
+	header.service = 0;
+	header.len = htons(len + sizeof(Header));
+	header.id = htons(ipid++);
+	header.flags = htons(flags);
+	header.ttl = 255;
+	header.proto = proto;
+	memcpy(&header.src, netif->ip, 4);
+	memcpy(&header.dst, dst, 4);
+	header.checksum = ipv4_checksum(&header, sizeof(Header));
+
+	char *packet = kmalloc(len + sizeof(Header));
+	memcpy(packet, &header, sizeof(Header));
+	memcpy(packet + sizeof(Header), data, len);
+	ethernet_send_frame(netif, netif->gatewayMac,
+	                    0x800, packet, len + sizeof(Header));
+	kfree(packet);
+}