BarryServer : Git

All the code for all my projects
// BarryServer : Git / Orion / blob / e59e4fe0bbf5a3f56db0700ee49a81131b590f9c / net / ethernet.c

// Related

Orion

Barry Importing existing Orion kernel d41a53c (2 years, 4 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);
}