From 60b30c036397cb5627fa374bb930794b225daa29 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 7 Jul 2017 11:55:23 -0400 Subject: Squashed 'lib/lufa/' content from commit 385d40300 git-subtree-dir: lib/lufa git-subtree-split: 385d4030035dbaf41591309dbde47653bd03841b --- Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c | 87 +++ Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.h | 76 +++ Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c | 129 +++++ Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.h | 131 +++++ .../ClassDriver/RNDISEthernet/Lib/Ethernet.c | 132 +++++ .../ClassDriver/RNDISEthernet/Lib/Ethernet.h | 101 ++++ .../RNDISEthernet/Lib/EthernetProtocols.h | 92 +++ Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.c | 83 +++ Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.h | 83 +++ Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c | 116 ++++ Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.h | 93 +++ .../RNDISEthernet/Lib/ProtocolDecoders.c | 277 +++++++++ .../RNDISEthernet/Lib/ProtocolDecoders.h | 60 ++ Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c | 632 +++++++++++++++++++++ Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h | 260 +++++++++ Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.c | 84 +++ Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.h | 70 +++ .../ClassDriver/RNDISEthernet/Lib/Webserver.c | 203 +++++++ .../ClassDriver/RNDISEthernet/Lib/Webserver.h | 57 ++ 19 files changed, 2766 insertions(+) create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.h create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.h create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.h create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/EthernetProtocols.h create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.c create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.h create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.h create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.h create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.c create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.h create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.c create mode 100644 Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.h (limited to 'Demos/Device/ClassDriver/RNDISEthernet/Lib') diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c new file mode 100644 index 0000000000..518ba8c6a1 --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c @@ -0,0 +1,87 @@ +/* + 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 + * + * Address Resolution Protocol (ARP) packet handling routines. This protocol handles the + * conversion of physical MAC addresses to protocol IP addresses between the host and the + * device. + */ + +#include "ARP.h" + +/** Processes an ARP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if the host is requesting the IP or MAC address of the + * virtual server device on the network. + * + * \param[in] InDataStart Pointer to the start of the incoming packet's ARP header + * \param[out] OutDataStart Pointer to the start of the outgoing packet's ARP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise + */ +int16_t ARP_ProcessARPPacket(void* InDataStart, + void* OutDataStart) +{ + DecodeARPHeader(InDataStart); + + ARP_Header_t* ARPHeaderIN = (ARP_Header_t*)InDataStart; + ARP_Header_t* ARPHeaderOUT = (ARP_Header_t*)OutDataStart; + + /* Ensure that the ARP request is a IPv4 request packet */ + if ((SwapEndian_16(ARPHeaderIN->ProtocolType) == ETHERTYPE_IPV4) && + (SwapEndian_16(ARPHeaderIN->Operation) == ARP_OPERATION_REQUEST)) + { + /* If the ARP packet is requesting the MAC or IP of the virtual webserver, return the response */ + if (IP_COMPARE(&ARPHeaderIN->TPA, &ServerIPAddress) || + MAC_COMPARE(&ARPHeaderIN->THA, &ServerMACAddress)) + { + /* Fill out the ARP response header */ + ARPHeaderOUT->HardwareType = ARPHeaderIN->HardwareType; + ARPHeaderOUT->ProtocolType = ARPHeaderIN->ProtocolType; + ARPHeaderOUT->HLEN = ARPHeaderIN->HLEN; + ARPHeaderOUT->PLEN = ARPHeaderIN->PLEN; + ARPHeaderOUT->Operation = SwapEndian_16(ARP_OPERATION_REPLY); + + /* Copy over the sender MAC/IP to the target fields for the response */ + ARPHeaderOUT->THA = ARPHeaderIN->SHA; + ARPHeaderOUT->TPA = ARPHeaderIN->SPA; + + /* Copy over the new sender MAC/IP - MAC and IP addresses of the virtual webserver */ + ARPHeaderOUT->SHA = ServerMACAddress; + ARPHeaderOUT->SPA = ServerIPAddress; + + /* Return the size of the response so far */ + return sizeof(ARP_Header_t); + } + } + + return NO_RESPONSE; +} + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.h new file mode 100644 index 0000000000..e64c38ec5f --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.h @@ -0,0 +1,76 @@ +/* + 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 + * + * Header file for ARP.c. + */ + +#ifndef _ARP_H_ +#define _ARP_H_ + + /* Includes: */ + #include + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** ARP header operation constant, indicating a request from a host for an address translation. */ + #define ARP_OPERATION_REQUEST 1 + + /** ARP header operation constant, indicating a reply from a host giving an address translation. */ + #define ARP_OPERATION_REPLY 2 + + /* Type Defines: */ + /** Type define for an ARP packet inside an Ethernet frame. */ + typedef struct + { + uint16_t HardwareType; /**< Hardware type constant, indicating the hardware used */ + uint16_t ProtocolType; /**< Protocol being resolved, usually ETHERTYPE_IPV4 */ + + uint8_t HLEN; /**< Length in bytes of the source/destination hardware addresses */ + uint8_t PLEN; /**< Length in bytes of the source/destination protocol addresses */ + uint16_t Operation; /**< Type of operation, either ARP_OPERATION_REQUEST or ARP_OPERATION_REPLY */ + + MAC_Address_t SHA; /**< Sender's hardware address */ + IP_Address_t SPA; /**< Sender's protocol address */ + MAC_Address_t THA; /**< Target's hardware address */ + IP_Address_t TPA; /**< Target's protocol address */ + } ARP_Header_t; + + /* Function Prototypes: */ + int16_t ARP_ProcessARPPacket(void* InDataStart, + void* OutDataStart); + +#endif + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c new file mode 100644 index 0000000000..7adc648360 --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c @@ -0,0 +1,129 @@ +/* + 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 + * + * Dynamic Host Configuration Protocol (DHCP) packet handling routines. This protocol + * handles the automatic IP negotiation to the host, so that the host will use the provided + * IP address given to it by the device. + */ + +#include "DHCP.h" + +/** Processes a DHCP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if the host is requesting or accepting an IP address. + * + * \param[in] IPHeaderInStart Pointer to the start of the incoming packet's IP header + * \param[in] DHCPHeaderInStart Pointer to the start of the incoming packet's DHCP header + * \param[out] DHCPHeaderOutStart Pointer to the start of the outgoing packet's DHCP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise + */ +int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, + void* DHCPHeaderInStart, + void* DHCPHeaderOutStart) +{ + IP_Header_t* IPHeaderIN = (IP_Header_t*)IPHeaderInStart; + DHCP_Header_t* DHCPHeaderIN = (DHCP_Header_t*)DHCPHeaderInStart; + DHCP_Header_t* DHCPHeaderOUT = (DHCP_Header_t*)DHCPHeaderOutStart; + + uint8_t* DHCPOptionsINStart = ((uint8_t*)DHCPHeaderInStart + sizeof(DHCP_Header_t)); + uint8_t* DHCPOptionsOUTStart = ((uint8_t*)DHCPHeaderOutStart + sizeof(DHCP_Header_t)); + + DecodeDHCPHeader(DHCPHeaderInStart); + + /* Zero out the response DHCP packet, as much of it is legacy and left at 0 */ + memset(DHCPHeaderOUT, 0, sizeof(DHCP_Header_t)); + + /* Fill out the response DHCP packet */ + DHCPHeaderOUT->HardwareType = DHCPHeaderIN->HardwareType; + DHCPHeaderOUT->Operation = DHCP_OP_BOOTREPLY; + DHCPHeaderOUT->HardwareAddressLength = DHCPHeaderIN->HardwareAddressLength; + DHCPHeaderOUT->Hops = 0; + DHCPHeaderOUT->TransactionID = DHCPHeaderIN->TransactionID; + DHCPHeaderOUT->ElapsedSeconds = 0; + DHCPHeaderOUT->Flags = DHCPHeaderIN->Flags; + DHCPHeaderOUT->YourIP = ClientIPAddress; + memmove(&DHCPHeaderOUT->ClientHardwareAddress, &DHCPHeaderIN->ClientHardwareAddress, sizeof(MAC_Address_t)); + DHCPHeaderOUT->Cookie = SwapEndian_32(DHCP_MAGIC_COOKIE); + + /* Alter the incoming IP packet header so that the corrected IP source and destinations are used - this means that + when the response IP header is generated, it will use the corrected addresses and not the null/broatcast addresses */ + IPHeaderIN->SourceAddress = ClientIPAddress; + IPHeaderIN->DestinationAddress = ServerIPAddress; + + /* Process the incoming DHCP packet options */ + while (DHCPOptionsINStart[0] != DHCP_OPTION_END) + { + /* Find the Message Type DHCP option, to determine the type of DHCP packet */ + if (DHCPOptionsINStart[0] == DHCP_OPTION_MESSAGETYPE) + { + if ((DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_DISCOVER) || (DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_REQUEST)) + { + /* Fill out the response DHCP packet options for a DHCP OFFER or ACK response */ + + *(DHCPOptionsOUTStart++) = DHCP_OPTION_MESSAGETYPE; + *(DHCPOptionsOUTStart++) = 1; + *(DHCPOptionsOUTStart++) = (DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_DISCOVER) ? DHCP_MESSAGETYPE_OFFER + : DHCP_MESSAGETYPE_ACK; + + *(DHCPOptionsOUTStart++) = DHCP_OPTION_SUBNETMASK; + *(DHCPOptionsOUTStart++) = sizeof(IP_Address_t); + *(DHCPOptionsOUTStart++) = 0xFF; + *(DHCPOptionsOUTStart++) = 0xFF; + *(DHCPOptionsOUTStart++) = 0xFF; + *(DHCPOptionsOUTStart++) = 0x00; + + *(DHCPOptionsOUTStart++) = DHCP_OPTION_LEASETIME; + *(DHCPOptionsOUTStart++) = sizeof(uint32_t); + /* Lease Time 86400s (ONE_DAY) */ + *(DHCPOptionsOUTStart++) = 0x00; + *(DHCPOptionsOUTStart++) = 0x01; + *(DHCPOptionsOUTStart++) = 0x51; + *(DHCPOptionsOUTStart++) = 0x80; + + *(DHCPOptionsOUTStart++) = DHCP_OPTION_DHCPSERVER; + *(DHCPOptionsOUTStart++) = sizeof(IP_Address_t); + memcpy(DHCPOptionsOUTStart, &ServerIPAddress, sizeof(IP_Address_t)); + DHCPOptionsOUTStart += sizeof(IP_Address_t); + + *(DHCPOptionsOUTStart++) = DHCP_OPTION_END; + + return (sizeof(DHCP_Header_t) + 18 + sizeof(IP_Address_t)); + } + } + + /* Go to the next DHCP option - skip one byte if option is a padding byte, else skip the complete option's size */ + DHCPOptionsINStart += ((DHCPOptionsINStart[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptionsINStart[1] + 2)); + } + + return NO_RESPONSE; +} + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.h new file mode 100644 index 0000000000..5ef78469ec --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.h @@ -0,0 +1,131 @@ +/* + 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 + * + * Header file for DHCP.c. + */ + +#ifndef _DHCP_H_ +#define _DHCP_H_ + + /* Includes: */ + #include + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** DHCP operation constant, indicating a request from a host to a DHCP server. */ + #define DHCP_OP_BOOTREQUEST 0x01 + + /** DHCP operation constant, indicating a reply from a DHCP server to a host. */ + #define DHCP_OP_BOOTREPLY 0x02 + + /** Hardware type constant, indicating Ethernet as a carrier. */ + #define DHCP_HTYPE_ETHERNET 0x01 + + /** Magic boot protocol "cookie", inserted into all BOOTP packets (BOOTP is the carrier of DHCP). */ + #define DHCP_MAGIC_COOKIE 0x63825363 + + /** DHCP option list entry header, indicating that a subnet mask will follow. */ + #define DHCP_OPTION_SUBNETMASK 1 + + /** DHCP option list entry header, indicating that the Lease Time will follow. */ + #define DHCP_OPTION_LEASETIME 51 + + /** DHCP option list entry header, indicating that the DHCP message type constant will follow. */ + #define DHCP_OPTION_MESSAGETYPE 53 + + /** DHCP option list entry header, indicating that the IP address of the DHCP server will follow. */ + #define DHCP_OPTION_DHCPSERVER 54 + + /** DHCP option list entry header, used to pad out option data. */ + #define DHCP_OPTION_PAD 0 + + /** DHCP option list entry header, indicating the end of option data. */ + #define DHCP_OPTION_END 255 + + /** Message type constant, used in the DHCP option data field, requesting that a DHCP server offer an IP address. */ + #define DHCP_MESSAGETYPE_DISCOVER 1 + + /** Message type constant, used in the DHCP option data field, indicating that a DHCP server is offering an IP address. */ + #define DHCP_MESSAGETYPE_OFFER 2 + + /** Message type constant, used in the DHCP option data field, requesting that a DHCP server lease a given IP address. */ + #define DHCP_MESSAGETYPE_REQUEST 3 + + /** Message type constant, used in the DHCP option data field, declining an offered DHCP server IP address lease. */ + #define DHCP_MESSAGETYPE_DECLINE 4 + + /** Message type constant, used in the DHCP option data field, ACKing a host IP lease request. */ + #define DHCP_MESSAGETYPE_ACK 5 + + /** Message type constant, used in the DHCP option data field, NACKing a host IP lease request. */ + #define DHCP_MESSAGETYPE_NACK 6 + + /** Message type constant, used in the DHCP option data field, indicating that a host is releasing a leased IP address. */ + #define DHCP_MESSAGETYPE_RELEASE 7 + + /* Type Defines: */ + /** Type define for a DHCP packet inside an Ethernet frame. */ + typedef struct + { + uint8_t Operation; /**< DHCP operation, either DHCP_OP_BOOTREQUEST or DHCP_OP_BOOTREPLY */ + uint8_t HardwareType; /**< Hardware carrier type constant */ + uint8_t HardwareAddressLength; /**< Length in bytes of a hardware (MAC) address on the network */ + uint8_t Hops; /**< Number of hops required to reach the server, unused */ + + uint32_t TransactionID; /**< Unique ID of the DHCP packet, for positive matching between sent and received packets */ + + uint16_t ElapsedSeconds; /**< Elapsed seconds since the request was made */ + uint16_t Flags; /**< BOOTP packet flags */ + + IP_Address_t ClientIP; /**< Client IP address, if already leased an IP */ + IP_Address_t YourIP; /**< Client IP address */ + IP_Address_t NextServerIP; /**< Legacy BOOTP protocol field, unused for DHCP */ + IP_Address_t RelayAgentIP; /**< Legacy BOOTP protocol field, unused for DHCP */ + + uint8_t ClientHardwareAddress[16]; /**< Hardware (MAC) address of the client making a request to the DHCP server */ + uint8_t ServerHostnameString[64]; /**< Legacy BOOTP protocol field, unused for DHCP */ + uint8_t BootFileName[128]; /**< Legacy BOOTP protocol field, unused for DHCP */ + + uint32_t Cookie; /**< Magic BOOTP protocol cookie to indicate a valid packet */ + } DHCP_Header_t; + + /* Function Prototypes: */ + int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, + void* DHCPHeaderInStart, + void* DHCPHeaderOutStart); + +#endif + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c new file mode 100644 index 0000000000..c28fa2336b --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c @@ -0,0 +1,132 @@ +/* + 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" + +/** 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(Ethernet_Frame_Info_t* const FrameIN, + Ethernet_Frame_Info_t* const FrameOUT) +{ + 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, + &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; +} + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.h new file mode 100644 index 0000000000..9bdb71c8f6 --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.h @@ -0,0 +1,101 @@ +/* + 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 + * + * Header file for Ethernet.c. + */ + +#ifndef _ETHERNET_H_ +#define _ETHERNET_H_ + + /* Includes: */ + #include + #include + + #include + + #include "Config/AppConfig.h" + + #include "EthernetProtocols.h" + #include "ProtocolDecoders.h" + #include "ICMP.h" + #include "TCP.h" + #include "UDP.h" + #include "DHCP.h" + #include "ARP.h" + #include "IP.h" + + /* Macros: */ + /** Physical MAC address of the network broadcast address. */ + #define BROADCAST_MAC_ADDRESS {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + + /** Performs a comparison between two MAC addresses, indicating if they are identical. + * + * \param[in] MAC1 First MAC address + * \param[in] MAC2 Second MAC address + * + * \return True if the addresses match, \c false otherwise + */ + #define MAC_COMPARE(MAC1, MAC2) (memcmp(MAC1, MAC2, sizeof(MAC_Address_t)) == 0) + + /** Minimum size of an Ethernet packet in bytes, to conform to the Ethernet V2 packet standard. */ + #define ETHERNET_VER2_MINSIZE 0x0600 + + /** Return value for all sub protocol handling routines, indicating that no response packet has been generated. */ + #define NO_RESPONSE 0 + + /** Return value for all sub protocol handling routines, indicating that the packet has not yet been handled. */ + #define NO_PROCESS -1 + + /* Type Defines: */ + /** Type define for an Ethernet frame header. */ + typedef struct + { + MAC_Address_t Destination; /**< Physical MAC address of the packet recipient */ + MAC_Address_t Source; /**< Physics MAC address of the packet source */ + uint16_t EtherType; /**< Ethernet packet sub-protocol type, for Ethernet V2 packets */ + } Ethernet_Frame_Header_t; + + /* External Variables: */ + extern const MAC_Address_t ServerMACAddress; + extern const IP_Address_t ServerIPAddress; + extern const MAC_Address_t BroadcastMACAddress; + extern const IP_Address_t BroadcastIPAddress; + extern const IP_Address_t ClientIPAddress; + + /* Function Prototypes: */ + void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* const FrameIN, + Ethernet_Frame_Info_t* const FrameOUT); + uint16_t Ethernet_Checksum16(void* Data, + uint16_t Bytes); + +#endif + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/EthernetProtocols.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/EthernetProtocols.h new file mode 100644 index 0000000000..51d3f32ee3 --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/EthernetProtocols.h @@ -0,0 +1,92 @@ +/* + 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 + * + * General Ethernet protocol constants and type defines, for use by + * all network protocol portions of the TCP/IP stack. + */ + +#ifndef _ETHERNET_PROTOCOLS_H_ +#define _ETHERNET_PROTOCOLS_H_ + + /* Includes: */ + #include + + /* Macros: */ + #define ETHERTYPE_IPV4 0x0800 + #define ETHERTYPE_ARP 0x0806 + #define ETHERTYPE_RARP 0x8035 + #define ETHERTYPE_APPLETALK 0x809b + #define ETHERTYPE_APPLETALKARP 0x80f3 + #define ETHERTYPE_IEEE8021Q 0x8100 + #define ETHERTYPE_NOVELLIPX 0x8137 + #define ETHERTYPE_NOVELL 0x8138 + #define ETHERTYPE_IPV6 0x86DD + #define ETHERTYPE_COBRANET 0x8819 + #define ETHERTYPE_PROVIDERBRIDGING 0x88a8 + #define ETHERTYPE_MPLSUNICAST 0x8847 + #define ETHERTYPE_MPLSMULTICAST 0x8848 + #define ETHERTYPE_PPPoEDISCOVERY 0x8863 + #define ETHERTYPE_PPPoESESSION 0x8864 + #define ETHERTYPE_EAPOVERLAN 0x888E + #define ETHERTYPE_HYPERSCSI 0x889A + #define ETHERTYPE_ATAOVERETHERNET 0x88A2 + #define ETHERTYPE_ETHERCAT 0x88A4 + #define ETHERTYPE_SERCOSIII 0x88CD + #define ETHERTYPE_CESoE 0x88D8 + #define ETHERTYPE_MACSECURITY 0x88E5 + #define ETHERTYPE_FIBRECHANNEL 0x8906 + #define ETHERTYPE_QINQ 0x9100 + #define ETHERTYPE_VLLT 0xCAFE + + #define PROTOCOL_ICMP 1 + #define PROTOCOL_IGMP 2 + #define PROTOCOL_TCP 6 + #define PROTOCOL_UDP 17 + #define PROTOCOL_OSPF 89 + #define PROTOCOL_SCTP 132 + + /* Type Defines: */ + /** Type define for an Ethernet frame buffer data and information structure. */ + typedef struct + { + uint8_t FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents. */ + uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer. */ + } Ethernet_Frame_Info_t; + + /** Type define for a protocol IP address of a device on a network. */ + typedef struct + { + uint8_t Octets[4]; /**< Individual bytes of an IP address */ + } IP_Address_t; + +#endif + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.c new file mode 100644 index 0000000000..24bc4b53fe --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.c @@ -0,0 +1,83 @@ +/* + 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 + * + * Internet Control Message Protocol (ICMP) packet handling routines. This protocol handles + * Echo requests from the host, to indicate a successful network connection between the host + * and the virtual server. + */ + +#include "ICMP.h" + +/** Processes an ICMP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if the host is issuing a ICMP ECHO request. + * + * \param[in] FrameIN Pointer to the incoming Ethernet frame information structure + * \param[in] InDataStart Pointer to the start of the incoming packet's ICMP header + * \param[out] OutDataStart Pointer to the start of the outgoing packet's ICMP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise + */ +int16_t ICMP_ProcessICMPPacket(Ethernet_Frame_Info_t* const FrameIN, + void* InDataStart, + void* OutDataStart) +{ + ICMP_Header_t* ICMPHeaderIN = (ICMP_Header_t*)InDataStart; + ICMP_Header_t* ICMPHeaderOUT = (ICMP_Header_t*)OutDataStart; + + DecodeICMPHeader(InDataStart); + + /* Determine if the ICMP packet is an echo request (ping) */ + if (ICMPHeaderIN->Type == ICMP_TYPE_ECHOREQUEST) + { + /* Fill out the ICMP response packet */ + ICMPHeaderOUT->Type = ICMP_TYPE_ECHOREPLY; + ICMPHeaderOUT->Code = 0; + ICMPHeaderOUT->Checksum = 0; + ICMPHeaderOUT->Id = ICMPHeaderIN->Id; + ICMPHeaderOUT->Sequence = ICMPHeaderIN->Sequence; + + intptr_t DataSize = FrameIN->FrameLength - ((((intptr_t)InDataStart + sizeof(ICMP_Header_t)) - (intptr_t)FrameIN->FrameData)); + + /* Copy the remaining payload to the response - echo requests should echo back any sent data */ + memmove(&((uint8_t*)OutDataStart)[sizeof(ICMP_Header_t)], + &((uint8_t*)InDataStart)[sizeof(ICMP_Header_t)], + DataSize); + + ICMPHeaderOUT->Checksum = Ethernet_Checksum16(ICMPHeaderOUT, (DataSize + sizeof(ICMP_Header_t))); + + /* Return the size of the response so far */ + return (DataSize + sizeof(ICMP_Header_t)); + } + + return NO_RESPONSE; +} + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.h new file mode 100644 index 0000000000..594dfffb24 --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.h @@ -0,0 +1,83 @@ +/* + 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 + * + * Header file for ICMP.c. + */ + +#ifndef _ICMP_H_ +#define _ICMP_H_ + + /* Includes: */ + #include + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** ICMP message type constant, indicating an ICMP ECHO Reply message. */ + #define ICMP_TYPE_ECHOREPLY 0 + + /** ICMP message type constant, indicating a packet destination is unreachable. */ + #define ICMP_TYPE_DESTINATIONUNREACHABLE 3 + + /** ICMP message type constant, indicating an ICMP Source Quench message. */ + #define ICMP_TYPE_SOURCEQUENCH 4 + + /** ICMP message type constant, indicating an ICMP Redirect message. */ + #define ICMP_TYPE_REDIRECTMESSAGE 5 + + /** ICMP message type constant, indicating an ICMP ECHO Request message. */ + #define ICMP_TYPE_ECHOREQUEST 8 + + /** ICMP message type constant, indicating an ICMP Time Exceeded message. */ + #define ICMP_TYPE_TIMEEXCEEDED 11 + + /* Type Defines: */ + /** Type define for an ICMP message header. */ + typedef struct + { + uint8_t Type; /**< ICMP message type, an \c ICMP_TYPE_* constant */ + uint8_t Code; /**< ICMP message code, indicating the message value */ + uint16_t Checksum; /**< Ethernet checksum of the ICMP message */ + uint16_t Id; /**< Id of the ICMP message */ + uint16_t Sequence; /**< Sequence number of the ICMP message, to link together message responses */ + } ICMP_Header_t; + + /* Function Prototypes: */ + int16_t ICMP_ProcessICMPPacket(Ethernet_Frame_Info_t* const FrameIN, + void* InDataStart, + void* OutDataStart); + +#endif + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c new file mode 100644 index 0000000000..05d4ebeeee --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c @@ -0,0 +1,116 @@ +/* + 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 + * + * Internet Protocol (IP) packet handling routines. This protocol handles IP packets from the + * host which typically encapsulate other protocols such as ICMP, UDP and TCP. + */ + +#include "IP.h" + +/** Processes an IP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if one is created by a sub-protocol handler. + * + * \param[in] FrameIN Pointer to the incoming Ethernet frame information structure + * \param[in] InDataStart Pointer to the start of the incoming packet's IP header + * \param[out] OutDataStart Pointer to the start of the outgoing packet's IP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE if no + * response was generated, NO_PROCESS if the packet processing was deferred until the + * next Ethernet packet handler iteration + */ +int16_t IP_ProcessIPPacket(Ethernet_Frame_Info_t* const FrameIN, + void* InDataStart, + void* OutDataStart) +{ + DecodeIPHeader(InDataStart); + + IP_Header_t* IPHeaderIN = (IP_Header_t*)InDataStart; + IP_Header_t* IPHeaderOUT = (IP_Header_t*)OutDataStart; + + /* Header length is specified in number of longs in the packet header, convert to bytes */ + uint16_t HeaderLengthBytes = (IPHeaderIN->HeaderLength * sizeof(uint32_t)); + + int16_t RetSize = NO_RESPONSE; + + /* Check to ensure the IP packet is addressed to the virtual webserver's IP or the broadcast IP address */ + if (!(IP_COMPARE(&IPHeaderIN->DestinationAddress, &ServerIPAddress)) && + !(IP_COMPARE(&IPHeaderIN->DestinationAddress, &BroadcastIPAddress))) + { + return NO_RESPONSE; + } + + /* Pass off the IP payload to the appropriate protocol processing routine */ + switch (IPHeaderIN->Protocol) + { + case PROTOCOL_ICMP: + RetSize = ICMP_ProcessICMPPacket(FrameIN, + &((uint8_t*)InDataStart)[HeaderLengthBytes], + &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); + break; + case PROTOCOL_TCP: + RetSize = TCP_ProcessTCPPacket(InDataStart, + &((uint8_t*)InDataStart)[HeaderLengthBytes], + &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); + break; + case PROTOCOL_UDP: + RetSize = UDP_ProcessUDPPacket(InDataStart, + &((uint8_t*)InDataStart)[HeaderLengthBytes], + &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); + break; + } + + /* Check to see if the protocol processing routine has filled out a response */ + if (RetSize > 0) + { + /* Fill out the response IP packet header */ + IPHeaderOUT->TotalLength = SwapEndian_16(sizeof(IP_Header_t) + RetSize); + IPHeaderOUT->TypeOfService = 0; + IPHeaderOUT->HeaderLength = (sizeof(IP_Header_t) / sizeof(uint32_t)); + IPHeaderOUT->Version = 4; + IPHeaderOUT->Flags = 0; + IPHeaderOUT->FragmentOffset = 0; + IPHeaderOUT->Identification = 0; + IPHeaderOUT->HeaderChecksum = 0; + IPHeaderOUT->Protocol = IPHeaderIN->Protocol; + IPHeaderOUT->TTL = DEFAULT_TTL; + IPHeaderOUT->SourceAddress = IPHeaderIN->DestinationAddress; + IPHeaderOUT->DestinationAddress = IPHeaderIN->SourceAddress; + + IPHeaderOUT->HeaderChecksum = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t)); + + /* Return the size of the response so far */ + return (sizeof(IP_Header_t) + RetSize); + } + + return RetSize; +} + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.h new file mode 100644 index 0000000000..0dd6db8a41 --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.h @@ -0,0 +1,93 @@ +/* + 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 + * + * Header file for IP.c. + */ + +#ifndef _IP_H_ +#define _IP_H_ + + /* Includes: */ + #include + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + #include "Config/AppConfig.h" + + /* Macros: */ + /** Protocol IP address of the broadcast address. */ + #define BROADCAST_IP_ADDRESS {0xFF, 0xFF, 0xFF, 0xFF} + + /** Default Time To Live (TTL) value for sent packets, indicating the maximum allowable hops until their destination + * is reached. + */ + #define DEFAULT_TTL 128 + + /** Performs a comparison between two IP addresses, indicating if they are identical. + * + * \param[in] IP1 First IP address + * \param[in] IP2 Second IP address + * + * \return True if the addresses match, \c false otherwise + */ + #define IP_COMPARE(IP1, IP2) (memcmp(IP1, IP2, sizeof(IP_Address_t)) == 0) + + /* Type Defines: */ + /** Type define of an IP packet header. */ + typedef struct + { + unsigned HeaderLength : 4; /**< Total length of the packet header, in 4-byte blocks */ + unsigned Version : 4; /**< IP protocol version */ + uint8_t TypeOfService; /**< Special service type identifier, indicating delay/throughput/reliability levels */ + uint16_t TotalLength; /**< Total length of the IP packet, in bytes */ + + uint16_t Identification; /**< Identification value for identifying fragmented packets */ + unsigned FragmentOffset : 13; /**< Offset of this IP fragment */ + unsigned Flags : 3; /**< Fragment flags, to indicate if a packet is fragmented */ + + uint8_t TTL; /**< Maximum allowable number of hops to reach the packet destination */ + uint8_t Protocol; /**< Encapsulated protocol type */ + uint16_t HeaderChecksum; /**< Ethernet checksum of the IP header */ + + IP_Address_t SourceAddress; /**< Source protocol IP address of the packet */ + IP_Address_t DestinationAddress; /**< Destination protocol IP address of the packet */ + } IP_Header_t; + + /* Function Prototypes: */ + int16_t IP_ProcessIPPacket(Ethernet_Frame_Info_t* const FrameIN, + void* InDataStart, + void* OutDataStart); + +#endif + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c new file mode 100644 index 0000000000..4c72f81b39 --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c @@ -0,0 +1,277 @@ +/* + 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. +*/ + +/* Protocol decoders for Ethernet, TCP, IP, ICMP and ARP. Each of these routines + accepts a header to the appropriate protocol and prints out pertinent information + on the packet through the serial port. + + To disable printing of a specific protocol, define the token NO_DECODE_{Protocol} + in the project makefile, and pass it to the compiler using the -D switch. +*/ + +/** \file + * + * Protocol decoding routines, for the plain-text decoding of Ethernet frames for debugging purposes. + * Enabled protocol decoders will print incoming Ethernet frame contents through the USART in a human + * readable format. + * + * Note that the USART is a slow transmission medium, and will slow down packet processing considerably. + * Packet decoding routines can be disabled by defining NO_DECODE_{Protocol Name} in the project makefile + * and passing it to the compiler via the -D switch. + */ + +#include "ProtocolDecoders.h" + +/** Decodes an Ethernet frame header and prints its contents to through the USART in a human readable format. + * + * \param[in] InDataStart Pointer to the start of an Ethernet frame of data + */ +void DecodeEthernetFrameHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_ETHERNET) + Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)InDataStart; + + printf_P(PSTR("\r\n")); + + printf_P(PSTR(" ETHERNET\r\n")); + + if (!(MAC_COMPARE(&FrameHeader->Destination, &ServerMACAddress)) && + !(MAC_COMPARE(&FrameHeader->Destination, &BroadcastMACAddress))) + { + printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n")); + return; + } + + printf_P(PSTR(" + MAC Source : %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Source.Octets[0], + FrameHeader->Source.Octets[1], + FrameHeader->Source.Octets[2], + FrameHeader->Source.Octets[3], + FrameHeader->Source.Octets[4], + FrameHeader->Source.Octets[5]); + + printf_P(PSTR(" + MAC Dest: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Destination.Octets[0], + FrameHeader->Destination.Octets[1], + FrameHeader->Destination.Octets[2], + FrameHeader->Destination.Octets[3], + FrameHeader->Destination.Octets[4], + FrameHeader->Destination.Octets[5]); + + printf_P(PSTR(" + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType)); + #endif +} + +/** Decodes an ARP header and prints its contents to through the USART in a human readable format. + * + * \param[in] InDataStart Pointer to the start of an ARP packet header + */ +void DecodeARPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_ARP) + ARP_Header_t* ARPHeader = (ARP_Header_t*)InDataStart; + + printf_P(PSTR(" \\\r\n ARP\r\n")); + + if (!(IP_COMPARE(&ARPHeader->TPA, &ServerIPAddress)) && + !(MAC_COMPARE(&ARPHeader->THA, &ServerMACAddress))) + { + printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n")); + return; + } + + printf_P(PSTR(" + Protocol: %x\r\n"), SwapEndian_16(ARPHeader->ProtocolType)); + printf_P(PSTR(" + Operation: %u\r\n"), SwapEndian_16(ARPHeader->Operation)); + + if (SwapEndian_16(ARPHeader->ProtocolType) == ETHERTYPE_IPV4) + { + printf_P(PSTR(" + SHA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->SHA.Octets[0], + ARPHeader->SHA.Octets[1], + ARPHeader->SHA.Octets[2], + ARPHeader->SHA.Octets[3], + ARPHeader->SHA.Octets[4], + ARPHeader->SHA.Octets[5]); + + printf_P(PSTR(" + SPA IP: %u.%u.%u.%u\r\n"), ARPHeader->SPA.Octets[0], + ARPHeader->SPA.Octets[1], + ARPHeader->SPA.Octets[2], + ARPHeader->SPA.Octets[3]); + + printf_P(PSTR(" + THA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->THA.Octets[0], + ARPHeader->THA.Octets[1], + ARPHeader->THA.Octets[2], + ARPHeader->THA.Octets[3], + ARPHeader->THA.Octets[4], + ARPHeader->THA.Octets[5]); + + printf_P(PSTR(" + TPA IP: %u.%u.%u.%u\r\n"), ARPHeader->TPA.Octets[0], + ARPHeader->TPA.Octets[1], + ARPHeader->TPA.Octets[2], + ARPHeader->TPA.Octets[3]); + } + #endif +} + +/** Decodes an IP header and prints its contents to through the USART in a human readable format. + * + * \param[in] InDataStart Pointer to the start of an IP packet header + */ +void DecodeIPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_IP) + IP_Header_t* IPHeader = (IP_Header_t*)InDataStart; + + uint16_t HeaderLengthBytes = (IPHeader->HeaderLength * sizeof(uint32_t)); + + printf_P(PSTR(" \\\r\n IP\r\n")); + + if (!(IP_COMPARE(&IPHeader->DestinationAddress, &ServerIPAddress))) + { + printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n")); + return; + } + + printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes); + printf_P(PSTR(" + Packet Version: %u\r\n"), IPHeader->Version); + printf_P(PSTR(" + Total Length: %u\r\n"), SwapEndian_16(IPHeader->TotalLength)); + + printf_P(PSTR(" + Protocol: %u\r\n"), IPHeader->Protocol); + printf_P(PSTR(" + TTL: %u\r\n"), IPHeader->TTL); + + printf_P(PSTR(" + IP Src: %u.%u.%u.%u\r\n"), IPHeader->SourceAddress.Octets[0], + IPHeader->SourceAddress.Octets[1], + IPHeader->SourceAddress.Octets[2], + IPHeader->SourceAddress.Octets[3]); + + printf_P(PSTR(" + IP Dst: %u.%u.%u.%u\r\n"), IPHeader->DestinationAddress.Octets[0], + IPHeader->DestinationAddress.Octets[1], + IPHeader->DestinationAddress.Octets[2], + IPHeader->DestinationAddress.Octets[3]); + #endif +} + +/** Decodes an ICMP header and prints its contents to through the USART in a human readable format. + * + * \param[in] InDataStart Pointer to the start of an ICMP packet header + */ +void DecodeICMPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_ICMP) + ICMP_Header_t* ICMPHeader = (ICMP_Header_t*)InDataStart; + + printf_P(PSTR(" \\\r\n ICMP\r\n")); + + printf_P(PSTR(" + Type: %u\r\n"), ICMPHeader->Type); + printf_P(PSTR(" + Code: %u\r\n"), ICMPHeader->Code); + #endif +} + +/** Decodes a TCP header and prints its contents to through the USART in a human readable format. + * + * \param[in] InDataStart Pointer to the start of a TCP packet header + */ +void DecodeTCPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_TCP) + TCP_Header_t* TCPHeader = (TCP_Header_t*)InDataStart; + + uint16_t HeaderLengthBytes = (TCPHeader->DataOffset * sizeof(uint32_t)); + + printf_P(PSTR(" \\\r\n TCP\r\n")); + + printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes); + + printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(TCPHeader->SourcePort)); + printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(TCPHeader->DestinationPort)); + + printf_P(PSTR(" + Sequence Number: %lu\r\n"), SwapEndian_32(TCPHeader->SequenceNumber)); + printf_P(PSTR(" + Acknowledgment Number: %lu\r\n"), SwapEndian_32(TCPHeader->AcknowledgmentNumber)); + + printf_P(PSTR(" + Flags: 0x%02X\r\n"), TCPHeader->Flags); + + if (TCP_GetPortState(TCPHeader->DestinationPort) == TCP_Port_Closed) + printf_P(PSTR(" + NOT LISTENING ON DESTINATION PORT\r\n")); + #endif +} + +/** Decodes an UDP header and prints its contents to through the USART in a human readable format. + * + * \param[in] InDataStart Pointer to the start of a UDP packet header + */ +void DecodeUDPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_UDP) + UDP_Header_t* UDPHeader = (UDP_Header_t*)InDataStart; + + printf_P(PSTR(" \\\r\n UDP\r\n")); + + printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(UDPHeader->SourcePort)); + printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(UDPHeader->DestinationPort)); + + printf_P(PSTR(" + Data Length: %d\r\n"), SwapEndian_16(UDPHeader->Length)); + #endif +} + +/** Decodes an DHCP header and prints its contents to through the USART in a human readable format. + * + * \param[in] InDataStart Pointer to the start of a DHCP packet header + */ +void DecodeDHCPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_DHCP) + uint8_t* DHCPOptions = ((uint8_t*)InDataStart + sizeof(DHCP_Header_t)); + + printf_P(PSTR(" \\\r\n DHCP\r\n")); + + while (DHCPOptions[0] != DHCP_OPTION_END) + { + if (DHCPOptions[0] == DHCP_OPTION_MESSAGETYPE) + { + switch (DHCPOptions[2]) + { + case DHCP_MESSAGETYPE_DISCOVER: + printf_P(PSTR(" + DISCOVER\r\n")); + break; + case DHCP_MESSAGETYPE_REQUEST: + printf_P(PSTR(" + REQUEST\r\n")); + break; + case DHCP_MESSAGETYPE_RELEASE: + printf_P(PSTR(" + RELEASE\r\n")); + break; + case DHCP_MESSAGETYPE_DECLINE: + printf_P(PSTR(" + DECLINE\r\n")); + break; + } + } + + DHCPOptions += ((DHCPOptions[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptions[1] + 2)); + } + + #endif +} + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.h new file mode 100644 index 0000000000..77a50f02f4 --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.h @@ -0,0 +1,60 @@ +/* + 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 + * + * Header file for ProtocolDecoders.c. + */ + +#ifndef _PROTOCOL_DECODERS_H_ +#define _PROTOCOL_DECODERS_H_ + + /* Includes: */ + #include + #include + #include + + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "Config/AppConfig.h" + + /* Function Prototypes: */ + void DecodeEthernetFrameHeader(void* InDataStart); + void DecodeARPHeader(void* InDataStart); + void DecodeIPHeader(void* InDataStart); + void DecodeICMPHeader(void* InDataStart); + void DecodeTCPHeader(void* InDataStart); + void DecodeUDPHeader(void* InDataStart); + void DecodeDHCPHeader(void* InDataStart); + +#endif + diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c new file mode 100644 index 0000000000..dcc527aa97 --- /dev/null +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c @@ -0,0 +1,632 @@ +/* + 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 docu