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); +}