136 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|              LUFA Library
 | |
|      Copyright (C) Dean Camera, 2017.
 | |
| 
 | |
|   dean [at] fourwalledcubicle [dot] com
 | |
|            www.lufa-lib.org
 | |
| */
 | |
| 
 | |
| /*
 | |
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 | |
| 
 | |
|   Permission to use, copy, modify, distribute, and sell this
 | |
|   software and its documentation for any purpose is hereby granted
 | |
|   without fee, provided that the above copyright notice appear in
 | |
|   all copies and that both that the copyright notice and this
 | |
|   permission notice and warranty disclaimer appear in supporting
 | |
|   documentation, and that the name of the author not be used in
 | |
|   advertising or publicity pertaining to distribution of the
 | |
|   software without specific, written prior permission.
 | |
| 
 | |
|   The author disclaims all warranties with regard to this
 | |
|   software, including all implied warranties of merchantability
 | |
|   and fitness.  In no event shall the author be liable for any
 | |
|   special, indirect or consequential damages or any damages
 | |
|   whatsoever resulting from loss of use, data or profits, whether
 | |
|   in an action of contract, negligence or other tortious action,
 | |
|   arising out of or in connection with the use or performance of
 | |
|   this software.
 | |
| */
 | |
| 
 | |
| /** \file
 | |
|  *
 | |
|  *  Ethernet frame packet handling routines. This protocol handles the processing of raw Ethernet
 | |
|  *  frames sent and received, deferring the processing of sub-packet protocols to the appropriate
 | |
|  *  protocol handlers, such as DHCP or ARP.
 | |
|  */
 | |
| 
 | |
| #include "Ethernet.h"
 | |
| 
 | |
| /** Ethernet Frame buffer structure, to hold the incoming Ethernet frame from the host. */
 | |
| Ethernet_Frame_Info_t FrameIN;
 | |
| 
 | |
| /** Ethernet Frame buffer structure, to hold the outgoing Ethernet frame to the host. */
 | |
| Ethernet_Frame_Info_t FrameOUT;
 | |
| 
 | |
| /** Constant for convenience when checking against or setting a MAC address to the virtual server MAC address. */
 | |
| const MAC_Address_t ServerMACAddress    = {SERVER_MAC_ADDRESS};
 | |
| 
 | |
| /** Constant for convenience when checking against or setting an IP address to the virtual server IP address. */
 | |
| const IP_Address_t  ServerIPAddress     = {SERVER_IP_ADDRESS};
 | |
| 
 | |
| /** Constant for convenience when checking against or setting a MAC address to the broadcast MAC address. */
 | |
| const MAC_Address_t BroadcastMACAddress = {BROADCAST_MAC_ADDRESS};
 | |
| 
 | |
| /** Constant for convenience when checking against or setting a IP address to the broadcast IP address. */
 | |
| const IP_Address_t  BroadcastIPAddress  = {BROADCAST_IP_ADDRESS};
 | |
| 
 | |
| /** Constant for convenience when checking against or setting an IP address to the client (host) IP address. */
 | |
| const IP_Address_t  ClientIPAddress     = {CLIENT_IP_ADDRESS};
 | |
| 
 | |
| 
 | |
| /** Processes an incoming Ethernet frame, and writes the appropriate response to the output Ethernet
 | |
|  *  frame buffer if the sub protocol handlers create a valid response.
 | |
|  */
 | |
| void Ethernet_ProcessPacket(void)
 | |
| {
 | |
| 	DecodeEthernetFrameHeader(FrameIN.FrameData);
 | |
| 
 | |
| 	/* Cast the incoming Ethernet frame to the Ethernet header type */
 | |
| 	Ethernet_Frame_Header_t* FrameINHeader  = (Ethernet_Frame_Header_t*)&FrameIN.FrameData;
 | |
| 	Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;
 | |
| 
 | |
| 	int16_t                  RetSize        = NO_RESPONSE;
 | |
| 
 | |
| 	/* Ensure frame is addressed to either all (broadcast) or the virtual webserver, and is a type II frame */
 | |
| 	if ((MAC_COMPARE(&FrameINHeader->Destination, &ServerMACAddress) ||
 | |
| 	     MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)) &&
 | |
| 		(SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE))
 | |
| 	{
 | |
| 		/* Process the packet depending on its protocol */
 | |
| 		switch (SwapEndian_16(FrameINHeader->EtherType))
 | |
| 		{
 | |
| 			case ETHERTYPE_ARP:
 | |
| 				RetSize = ARP_ProcessARPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],
 | |
| 				                               &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);
 | |
| 				break;
 | |
| 			case ETHERTYPE_IPV4:
 | |
| 				RetSize = IP_ProcessIPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],
 | |
| 				                             &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);
 | |
| 				break;
 | |
| 		}
 | |
| 
 | |
| 		/* Protocol processing routine has filled a response, complete the ethernet frame header */
 | |
| 		if (RetSize > 0)
 | |
| 		{
 | |
| 			/* Fill out the response Ethernet frame header */
 | |
| 			FrameOUTHeader->Source          = ServerMACAddress;
 | |
| 			FrameOUTHeader->Destination     = FrameINHeader->Source;
 | |
| 			FrameOUTHeader->EtherType       = FrameINHeader->EtherType;
 | |
| 
 | |
| 			/* Set the response length in the buffer and indicate that a response is ready to be sent */
 | |
| 			FrameOUT.FrameLength            = (sizeof(Ethernet_Frame_Header_t) + RetSize);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* Check if the packet was processed */
 | |
| 	if (RetSize != NO_PROCESS)
 | |
| 	{
 | |
| 		/* Clear the frame buffer */
 | |
| 		FrameIN.FrameLength = 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /** Calculates the appropriate ethernet checksum, consisting of the addition of the one's
 | |
|  *  compliment of each word, complimented.
 | |
|  *
 | |
|  *  \param[in] Data   Pointer to the packet buffer data whose checksum must be calculated
 | |
|  *  \param[in] Bytes  Number of bytes in the data buffer to process
 | |
|  *
 | |
|  *  \return A 16-bit Ethernet checksum value
 | |
|  */
 | |
| uint16_t Ethernet_Checksum16(void* Data,
 | |
|                              uint16_t Bytes)
 | |
| {
 | |
| 	uint16_t* Words    = (uint16_t*)Data;
 | |
| 	uint32_t  Checksum = 0;
 | |
| 
 | |
| 	for (uint16_t CurrWord = 0; CurrWord < (Bytes >> 1); CurrWord++)
 | |
| 	  Checksum += Words[CurrWord];
 | |
| 
 | |
| 	while (Checksum & 0xFFFF0000)
 | |
| 	  Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16));
 | |
| 
 | |
| 	return ~Checksum;
 | |
| }
 | |
| 
 | 
