Orion
Barry Importing existing Orion kernel d41a53c (3 years, 2 months ago)
/*
* This file implements the Ethernet layer of the Network Stack. It wraps any
* packet sent to it with the Ethernet Header. Equally, it unwraps any packets
* before passing them to the next layer, determined by the EtherType in the
* header.
*/
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "net.h"
#include "../mem/heap.h"
#include "../screen.h"
/* Structure for an Ethernet Header */
typedef struct Header {
uint8_t dst[6];
uint8_t src[6];
uint16_t ethertype;
} __attribute__((packed)) Header;
/* Receive a frame of data */
void
ethernet_receive_frame(NetIF *netif, void *data, size_t len)
{
Header header;
memcpy(&header, data, sizeof(Header));
header.ethertype = ntohs(header.ethertype);
/* Handle appropriately */
switch (header.ethertype) {
case 0x0800: /* IPv4 */
ipv4_receive_packet(netif, data + sizeof(Header),
len - sizeof(Header));
break;
case 0x0806: /* ARP */
arp_receive_packet(netif, data + sizeof(Header),
len - sizeof(Header));
break;
// default:
// kprintf("Unhandled type (%04x)", header.ethertype);
}
}
/* Send a frame of data */
void
ethernet_send_frame(NetIF *netif, uint8_t dst[6], uint16_t type,
void *data, size_t len)
{
Header header;
header.ethertype = htons(type);
memcpy(header.src, netif->mac, 6);
memcpy(header.dst, dst, 6);
size_t frameLen = sizeof(Header) + len;
if (frameLen < 64)
frameLen = 64;
char *frame = kmalloc(frameLen);
memcpy(frame, &header, sizeof(Header));
memcpy(frame + sizeof(Header), data, len);
netif->transmit(frame, frameLen);
kfree(frame);
}