diff options
Diffstat (limited to 'Demos/Device/ClassDriver/RNDISEthernet/Lib')
19 files changed, 2698 insertions, 2698 deletions
diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c index 53eaa57a9..6cbc67f89 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c @@ -1,85 +1,85 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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;
-}
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 index 93409babc..fce77969d 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.h @@ -1,74 +1,74 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 <avr/io.h>
- #include <string.h>
-
- #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
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 <avr/io.h> + #include <string.h> + + #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 index 085a50705..e6377af52 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c @@ -1,118 +1,118 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 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;
- memcpy(&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++) = 4;
- *(DHCPOptionsOUTStart++) = 0xFF;
- *(DHCPOptionsOUTStart++) = 0xFF;
- *(DHCPOptionsOUTStart++) = 0xFF;
- *(DHCPOptionsOUTStart++) = 0x00;
-
- *(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) + 12 + 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;
-}
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 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; + memcpy(&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++) = 4; + *(DHCPOptionsOUTStart++) = 0xFF; + *(DHCPOptionsOUTStart++) = 0xFF; + *(DHCPOptionsOUTStart++) = 0xFF; + *(DHCPOptionsOUTStart++) = 0x00; + + *(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) + 12 + 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 index c4df5b3c7..cacdd8ffd 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.h @@ -1,125 +1,125 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 <avr/io.h>
- #include <string.h>
-
- #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 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
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 <avr/io.h> + #include <string.h> + + #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 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 index d09930e4e..a3a42e22d 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c @@ -1,130 +1,130 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 subpacket 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* FrameIN, Ethernet_Frame_Info_t* FrameOUT)
-{
- DecodeEthernetFrameHeader(FrameIN);
-
- /* 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);
- FrameOUT->FrameInBuffer = true;
- }
- }
-
- /* Check if the packet was processed */
- if (RetSize != NO_PROCESS)
- {
- /* Clear the frame buffer */
- FrameIN->FrameInBuffer = false;
- }
-}
-
-/** 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 (uint8_t CurrWord = 0; CurrWord < (Bytes >> 1); CurrWord++)
- Checksum += Words[CurrWord];
-
- while (Checksum & 0xFFFF0000)
- Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16));
-
- return ~Checksum;
-}
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 subpacket 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* FrameIN, Ethernet_Frame_Info_t* FrameOUT) +{ + DecodeEthernetFrameHeader(FrameIN); + + /* 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); + FrameOUT->FrameInBuffer = true; + } + } + + /* Check if the packet was processed */ + if (RetSize != NO_PROCESS) + { + /* Clear the frame buffer */ + FrameIN->FrameInBuffer = false; + } +} + +/** 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 (uint8_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 index 5029b7f3e..d5e091c13 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.h @@ -1,107 +1,107 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 <avr/io.h>
- #include <string.h>
-
- #include <LUFA/Drivers/USB/Class/RNDIS.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 USB RNDIS network adapter */
- #define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00}
-
- /** Physical MAC address of the virtual server on the network */
- #define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}
-
- /** 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, 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 */
-
- union
- {
- uint16_t EtherType; /**< Ethernet packet sub-protocol type, for Ethernet V2 packets */
- uint16_t Length; /**< Ethernet frame length, for Ethernet V1 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* FrameIN, Ethernet_Frame_Info_t* FrameOUT);
- uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes);
-
-#endif
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 <avr/io.h> + #include <string.h> + + #include <LUFA/Drivers/USB/Class/RNDIS.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 USB RNDIS network adapter */ + #define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00} + + /** Physical MAC address of the virtual server on the network */ + #define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01} + + /** 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, 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 */ + + union + { + uint16_t EtherType; /**< Ethernet packet sub-protocol type, for Ethernet V2 packets */ + uint16_t Length; /**< Ethernet frame length, for Ethernet V1 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* FrameIN, Ethernet_Frame_Info_t* 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 index 23f75108f..6117fe13e 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/EthernetProtocols.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/EthernetProtocols.h @@ -1,81 +1,81 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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_
-
- /* 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 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
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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_ + + /* 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 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 index dd339ca3a..2d8183746 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.c @@ -1,80 +1,80 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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* 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;
-
- uint16_t DataSize = FrameIN->FrameLength - ((((uint16_t)InDataStart + sizeof(ICMP_Header_t)) - (uint16_t)FrameIN->FrameData));
-
- /* Copy the remaining payload to the response - echo requests should echo back any sent data */
- memcpy(&((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;
-}
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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* 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; + + uint16_t DataSize = FrameIN->FrameLength - ((((uint16_t)InDataStart + sizeof(ICMP_Header_t)) - (uint16_t)FrameIN->FrameData)); + + /* Copy the remaining payload to the response - echo requests should echo back any sent data */ + memcpy(&((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 index e630c1afc..6c2fbb134 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.h @@ -1,80 +1,80 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 <avr/io.h>
- #include <string.h>
-
- #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, a 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* FrameIN, void* InDataStart, void* OutDataStart);
-
-#endif
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 <avr/io.h> + #include <string.h> + + #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, a 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* FrameIN, void* InDataStart, void* OutDataStart); + +#endif diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c index 000d89001..6766322ca 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c @@ -1,113 +1,113 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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* 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;
-}
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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* 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 index 60d43e14d..82f28e80e 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.h @@ -1,93 +1,93 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 <avr/io.h>
- #include <string.h>
-
- #include "EthernetProtocols.h"
- #include "Ethernet.h"
- #include "ProtocolDecoders.h"
-
- /* Macros: */
- /** Protocol IP address of the host (client) machine, once assigned by DHCP */
- #define CLIENT_IP_ADDRESS { 10, 0, 0, 1}
-
- /** Protocol IP address of the virtual server machine */
- #define SERVER_IP_ADDRESS { 10, 0, 0, 2}
-
- /** 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, 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 char HeaderLength : 4; /**< Total length of the packet header, in 4-byte blocks */
- unsigned char 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 int FragmentOffset : 13; /**< Offset of this IP fragment */
- unsigned int 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* FrameIN, void* InDataStart, void* OutDataStart);
-
-#endif
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 <avr/io.h> + #include <string.h> + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** Protocol IP address of the host (client) machine, once assigned by DHCP */ + #define CLIENT_IP_ADDRESS { 10, 0, 0, 1} + + /** Protocol IP address of the virtual server machine */ + #define SERVER_IP_ADDRESS { 10, 0, 0, 2} + + /** 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, 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 char HeaderLength : 4; /**< Total length of the packet header, in 4-byte blocks */ + unsigned char 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 int FragmentOffset : 13; /**< Offset of this IP fragment */ + unsigned int 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* FrameIN, void* InDataStart, void* OutDataStart); + +#endif diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c index 37cb840fd..e0bf6ecfe 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c @@ -1,280 +1,280 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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] FrameINData Pointer to the start of an Ethernet frame information structure
- */
-void DecodeEthernetFrameHeader(Ethernet_Frame_Info_t* FrameINData)
-{
- #if !defined(NO_DECODE_ETHERNET)
- Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)FrameINData->FrameData;
-
- printf_P(PSTR("\r\n"));
-
- printf_P(PSTR(" ETHERNET\r\n"));
- printf_P(PSTR(" + Frame Size: %u\r\n"), FrameINData->FrameLength);
-
- 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]);
-
- if (SwapEndian_16(FrameINData->FrameLength) > ETHERNET_VER2_MINSIZE)
- printf_P(PSTR(" + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType));
- else
- printf_P(PSTR(" + Protocol: UNKNOWN E1\r\n"));
- #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 = (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
-}
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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] FrameINData Pointer to the start of an Ethernet frame information structure + */ +void DecodeEthernetFrameHeader(Ethernet_Frame_Info_t* FrameINData) +{ + #if !defined(NO_DECODE_ETHERNET) + Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)FrameINData->FrameData; + + printf_P(PSTR("\r\n")); + + printf_P(PSTR(" ETHERNET\r\n")); + printf_P(PSTR(" + Frame Size: %u\r\n"), FrameINData->FrameLength); + + 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]); + + if (SwapEndian_16(FrameINData->FrameLength) > ETHERNET_VER2_MINSIZE) + printf_P(PSTR(" + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType)); + else + printf_P(PSTR(" + Protocol: UNKNOWN E1\r\n")); + #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 = (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 index 2dfc60868..56ed795e6 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.h @@ -1,59 +1,59 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 <avr/io.h>
- #include <avr/pgmspace.h>
- #include <stdio.h>
-
- #include <LUFA/Drivers/USB/Class/RNDIS.h>
- #include <LUFA/Drivers/Peripheral/SerialStream.h>
-
- #include "EthernetProtocols.h"
- #include "Ethernet.h"
-
- /* Function Prototypes: */
- void DecodeEthernetFrameHeader(Ethernet_Frame_Info_t* FrameINData);
- 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
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 <avr/io.h> + #include <avr/pgmspace.h> + #include <stdio.h> + + #include <LUFA/Drivers/USB/Class/RNDIS.h> + #include <LUFA/Drivers/Peripheral/SerialStream.h> + + #include "EthernetProtocols.h" + #include "Ethernet.h" + + /* Function Prototypes: */ + void DecodeEthernetFrameHeader(Ethernet_Frame_Info_t* FrameINData); + 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 index 6500f3ba0..318085f59 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c @@ -1,621 +1,621 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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
- *
- * Transmission Control Protocol (TCP) packet handling routines. This protocol handles the reliable in-order transmission
- * and reception of packets to and from devices on a network, to "ports" on the device. It is used in situations where data
- * delivery must be reliable and correct, e.g. HTTP, TELNET and most other non-streaming protocols.
- */
-
-#define INCLUDE_FROM_TCP_C
-#include "TCP.h"
-
-/** Port state table array. This contains the current status of TCP ports in the device. To save on space, only open ports are
- * stored - closed ports may be overwritten at any time, and the system will assume any ports not present in the array are closed. This
- * allows for MAX_OPEN_TCP_PORTS to be less than the number of ports used by the application if desired.
- */
-TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS];
-
-/** Connection state table array. This contains the current status of TCP connections in the device. To save on space, only active
- * (non-closed) connections are stored - closed connections may be overwritten at any time, and the system will assume any connections
- * not present in the array are closed.
- */
-TCP_ConnectionState_t ConnectionStateTable[MAX_TCP_CONNECTIONS];
-
-
-/** Task to handle the calling of each registered application's callback function, to process and generate TCP packets at the application
- * level. If an application produces a response, this task constructs the appropriate Ethernet frame and places it into the Ethernet OUT
- * buffer for later transmission.
- */
-void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* RNDISInterfaceInfo)
-{
- /* Run each application in sequence, to process incoming and generate outgoing packets */
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
- {
- /* Find the corresponding port entry in the port table */
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++)
- {
- /* Run the application handler for the port */
- if ((PortStateTable[PTableEntry].Port == ConnectionStateTable[CSTableEntry].Port) &&
- (PortStateTable[PTableEntry].State == TCP_Port_Open))
- {
- PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry],
- &ConnectionStateTable[CSTableEntry].Info.Buffer);
- }
- }
- }
-
- /* Get pointer to the output frame info struct for convenience */
- Ethernet_Frame_Info_t* FrameOUT = &RNDISInterfaceInfo->State.FrameOUT;
-
- /* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */
- if (FrameOUT->FrameInBuffer)
- return;
-
- /* Send response packets from each application as the TCP packet buffers are filled by the applications */
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
- {
- /* For each completely received packet, pass it along to the listening application */
- if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) &&
- (ConnectionStateTable[CSTableEntry].Info.Buffer.Ready))
- {
- Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT->FrameData;
- IP_Header_t* IPHeaderOUT = (IP_Header_t*)&FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t)];
- TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t) +
- sizeof(IP_Header_t)];
- void* TCPDataOUT = &FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t) +
- sizeof(IP_Header_t) +
- sizeof(TCP_Header_t)];
-
- uint16_t PacketSize = ConnectionStateTable[CSTableEntry].Info.Buffer.Length;
-
- /* Fill out the TCP data */
- TCPHeaderOUT->SourcePort = ConnectionStateTable[CSTableEntry].Port;
- TCPHeaderOUT->DestinationPort = ConnectionStateTable[CSTableEntry].RemotePort;
- TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut);
- TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberIn);
- TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t));
- TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE);
-
- TCPHeaderOUT->Flags = TCP_FLAG_ACK;
- TCPHeaderOUT->UrgentPointer = 0;
- TCPHeaderOUT->Checksum = 0;
- TCPHeaderOUT->Reserved = 0;
-
- memcpy(TCPDataOUT, ConnectionStateTable[CSTableEntry].Info.Buffer.Data, PacketSize);
-
- ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut += PacketSize;
-
- TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, ServerIPAddress,
- ConnectionStateTable[CSTableEntry].RemoteAddress,
- (sizeof(TCP_Header_t) + PacketSize));
-
- PacketSize += sizeof(TCP_Header_t);
-
- /* Fill out the response IP header */
- IPHeaderOUT->TotalLength = SwapEndian_16(sizeof(IP_Header_t) + PacketSize);
- 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 = PROTOCOL_TCP;
- IPHeaderOUT->TTL = DEFAULT_TTL;
- IPHeaderOUT->SourceAddress = ServerIPAddress;
- IPHeaderOUT->DestinationAddress = ConnectionStateTable[CSTableEntry].RemoteAddress;
-
- IPHeaderOUT->HeaderChecksum = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t));
-
- PacketSize += sizeof(IP_Header_t);
-
- /* Fill out the response Ethernet frame header */
- FrameOUTHeader->Source = ServerMACAddress;
- FrameOUTHeader->Destination = (MAC_Address_t){{0x02, 0x00, 0x02, 0x00, 0x02, 0x00}};
- FrameOUTHeader->EtherType = SwapEndian_16(ETHERTYPE_IPV4);
-
- PacketSize += sizeof(Ethernet_Frame_Header_t);
-
- /* Set the response length in the buffer and indicate that a response is ready to be sent */
- FrameOUT->FrameLength = PacketSize;
- FrameOUT->FrameInBuffer = true;
-
- ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false;
-
- break;
- }
- }
-}
-
-/** Initializes the TCP protocol handler, clearing the port and connection state tables. This must be called before TCP packets are
- * processed.
- */
-void TCP_Init(void)
-{
- /* Initialize the port state table with all CLOSED entries */
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++)
- PortStateTable[PTableEntry].State = TCP_Port_Closed;
-
- /* Initialize the connection table with all CLOSED entries */
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
- ConnectionStateTable[CSTableEntry].State = TCP_Connection_Closed;
-}
-
-/** Sets the state and callback handler of the given port, specified in big endian to the given state.
- *
- * \param[in] Port Port whose state and callback function to set, specified in big endian
- * \param[in] State New state of the port, a value from the TCP_PortStates_t enum
- * \param[in] Handler Application callback handler for the port
- *
- * \return Boolean true if the port state was set, false otherwise (no more space in the port state table)
- */
-bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*))
-{
- /* Note, Port number should be specified in BIG endian to simplify network code */
-
- /* Check to see if the port entry is already in the port state table */
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)
- {
- /* Find existing entry for the port in the table, update it if found */
- if (PortStateTable[PTableEntry].Port == Port)
- {
- PortStateTable[PTableEntry].State = State;
- PortStateTable[PTableEntry].ApplicationHandler = Handler;
- return true;
- }
- }
-
- /* Check if trying to open the port -- if so we need to find an unused (closed) entry and replace it */
- if (State == TCP_Port_Open)
- {
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)
- {
- /* Find a closed port entry in the table, change it to the given port and state */
- if (PortStateTable[PTableEntry].State == TCP_Port_Closed)
- {
- PortStateTable[PTableEntry].Port = Port;
- PortStateTable[PTableEntry].State = State;
- PortStateTable[PTableEntry].ApplicationHandler = Handler;
- return true;
- }
- }
-
- /* Port not in table and no room to add it, return failure */
- return false;
- }
- else
- {
- /* Port not in table but trying to close it, so operation successful */
- return true;
- }
-}
-
-/** Retrieves the current state of a given TCP port, specified in big endian.
- *
- * \param[in] Port TCP port whose state is to be retrieved, given in big-endian
- *
- * \return A value from the TCP_PortStates_t enum
- */
-uint8_t TCP_GetPortState(uint16_t Port)
-{
- /* Note, Port number should be specified in BIG endian to simplify network code */
-
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)
- {
- /* Find existing entry for the port in the table, return the port status if found */
- if (PortStateTable[PTableEntry].Port == Port)
- return PortStateTable[PTableEntry].State;
- }
-
- /* Port not in table, assume closed */
- return TCP_Port_Closed;
-}
-
-/** Sets the connection state of the given port, remote address and remote port to the given TCP connection state. If the
- * connection exists in the connection state table it is updated, otherwise it is created if possible.
- *
- * \param[in] Port TCP port of the connection on the device, specified in big endian
- * \param[in] RemoteAddress Remote protocol IP address of the connected device
- * \param[in] RemotePort TCP port of the remote device in the connection, specified in big endian
- * \param[in] State TCP connection state, a value from the TCP_ConnectionStates_t enum
- *
- * \return Boolean true if the connection was updated or created, false otherwise (no more space in the connection state table)
- */
-bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State)
-{
- /* Note, Port number should be specified in BIG endian to simplify network code */
-
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
- {
- /* Find port entry in the table */
- if ((ConnectionStateTable[CSTableEntry].Port == Port) &&
- IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&
- ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)
- {
- ConnectionStateTable[CSTableEntry].State = State;
- return true;
- }
- }
-
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
- {
- /* Find empty entry in the table */
- if (ConnectionStateTable[CSTableEntry].State == TCP_Connection_Closed)
- {
- ConnectionStateTable[CSTableEntry].Port = Port;
- ConnectionStateTable[CSTableEntry].RemoteAddress = RemoteAddress;
- ConnectionStateTable[CSTableEntry].RemotePort = RemotePort;
- ConnectionStateTable[CSTableEntry].State = State;
- return true;
- }
- }
-
- return false;
-}
-
-/** Retrieves the current state of a given TCP connection to a host.
- *
- * \param[in] Port TCP port on the device in the connection, specified in big endian
- * \param[in] RemoteAddress Remote protocol IP address of the connected host
- * \param[in] RemotePort Remote TCP port of the connected host, specified in big endian
- *
- * \return A value from the TCP_ConnectionStates_t enum
- */
-uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort)
-{
- /* Note, Port number should be specified in BIG endian to simplify network code */
-
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
- {
- /* Find port entry in the table */
- if ((ConnectionStateTable[CSTableEntry].Port == Port) &&
- IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&
- ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)
-
- {
- return ConnectionStateTable[CSTableEntry].State;
- }
- }
-
- return TCP_Connection_Closed;
-}
-
-/** Retrieves the connection info structure of a given connection to a host.
- *
- * \param[in] Port TCP port on the device in the connection, specified in big endian
- * \param[in] RemoteAddress Remote protocol IP address of the connected host
- * \param[in] RemotePort Remote TCP port of the connected host, specified in big endian
- *
- * \return ConnectionInfo structure of the connection if found, NULL otherwise
- */
-TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort)
-{
- /* Note, Port number should be specified in BIG endian to simplify network code */
-
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
- {
- /* Find port entry in the table */
- if ((ConnectionStateTable[CSTableEntry].Port == Port) &&
- IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&
- ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)
- {
- return &ConnectionStateTable[CSTableEntry].Info;
- }
- }
-
- return NULL;
-}
-
-/** Processes a TCP packet inside an Ethernet frame, and writes the appropriate response
- * to the output Ethernet frame if one is created by a application handler.
- *
- * \param[in] IPHeaderInStart Pointer to the start of the incoming packet's IP header
- * \param[in] TCPHeaderInStart Pointer to the start of the incoming packet's TCP header
- * \param[out] TCPHeaderOutStart Pointer to the start of the outgoing packet's TCP 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 TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart)
-{
- IP_Header_t* IPHeaderIN = (IP_Header_t*)IPHeaderInStart;
- TCP_Header_t* TCPHeaderIN = (TCP_Header_t*)TCPHeaderInStart;
- TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)TCPHeaderOutStart;
-
- TCP_ConnectionInfo_t* ConnectionInfo;
-
- DecodeTCPHeader(TCPHeaderInStart);
-
- bool PacketResponse = false;
-
- /* Check if the destination port is open and allows incoming connections */
- if (TCP_GetPortState(TCPHeaderIN->DestinationPort) == TCP_Port_Open)
- {
- /* Detect SYN from host to start a connection */
- if (TCPHeaderIN->Flags & TCP_FLAG_SYN)
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort, TCP_Connection_Listen);
-
- /* Detect RST from host to abort existing connection */
- if (TCPHeaderIN->Flags & TCP_FLAG_RST)
- {
- if (TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort, TCP_Connection_Closed))
- {
- TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK);
- PacketResponse = true;
- }
- }
- else
- {
- /* Process the incoming TCP packet based on the current connection state for the sender and port */
- switch (TCP_GetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort))
- {
- case TCP_Connection_Listen:
- if (TCPHeaderIN->Flags == TCP_FLAG_SYN)
- {
- /* SYN connection starts a connection with a peer */
- if (TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort, TCP_Connection_SYNReceived))
- {
- TCPHeaderOUT->Flags = (TCP_FLAG_SYN | TCP_FLAG_ACK);
-
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort);
-
- ConnectionInfo->SequenceNumberIn = (SwapEndian_32(TCPHeaderIN->SequenceNumber) + 1);
- ConnectionInfo->SequenceNumberOut = 0;
- ConnectionInfo->Buffer.InUse = false;
- }
- else
- {
- TCPHeaderOUT->Flags = TCP_FLAG_RST;
- }
-
- PacketResponse = true;
- }
-
- break;
- case TCP_Connection_SYNReceived:
- if (TCPHeaderIN->Flags == TCP_FLAG_ACK)
- {
- /* ACK during the connection process completes the connection to a peer */
-
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort, TCP_Connection_Established);
-
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort);
-
- ConnectionInfo->SequenceNumberOut++;
- }
-
- break;
- case TCP_Connection_Established:
- if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))
- {
- /* FIN ACK when connected to a peer starts the finalization process */
-
- TCPHeaderOUT->Flags = (TCP_FLAG_FIN | TCP_FLAG_ACK);
- PacketResponse = true;
-
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort, TCP_Connection_CloseWait);
-
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort);
-
- ConnectionInfo->SequenceNumberIn++;
- ConnectionInfo->SequenceNumberOut++;
- }
- else if ((TCPHeaderIN->Flags == TCP_FLAG_ACK) || (TCPHeaderIN->Flags == (TCP_FLAG_ACK | TCP_FLAG_PSH)))
- {
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort);
-
- /* Check if the buffer is currently in use either by a buffered data to send, or receive */
- if ((ConnectionInfo->Buffer.InUse == false) && (ConnectionInfo->Buffer.Ready == false))
- {
- ConnectionInfo->Buffer.Direction = TCP_PACKETDIR_IN;
- ConnectionInfo->Buffer.InUse = true;
- ConnectionInfo->Buffer.Length = 0;
- }
-
- /* Check if the buffer has been claimed by us to read in data from the peer */
- if ((ConnectionInfo->Buffer.Direction == TCP_PACKETDIR_IN) &&
- (ConnectionInfo->Buffer.Length != TCP_WINDOW_SIZE))
- {
- uint16_t IPOffset = (IPHeaderIN->HeaderLength * sizeof(uint32_t));
- uint16_t TCPOffset = (TCPHeaderIN->DataOffset * sizeof(uint32_t));
- uint16_t DataLength = (SwapEndian_16(IPHeaderIN->TotalLength) - IPOffset - TCPOffset);
-
- /* Copy the packet data into the buffer */
- memcpy(&ConnectionInfo->Buffer.Data[ConnectionInfo->Buffer.Length],
- &((uint8_t*)TCPHeaderInStart)[TCPOffset],
- DataLength);
-
- ConnectionInfo->SequenceNumberIn += DataLength;
- ConnectionInfo->Buffer.Length += DataLength;
-
- /* Check if the buffer is full or if the PSH flag is set, if so indicate buffer ready */
- if ((!(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length)) || (TCPHeaderIN->Flags & TCP_FLAG_PSH))
- {
- ConnectionInfo->Buffer.InUse = false;
- ConnectionInfo->Buffer.Ready = true;
-
- TCPHeaderOUT->Flags = TCP_FLAG_ACK;
- PacketResponse = true;
- }
- }
- else
- {
- /* Buffer is currently in use by the application, defer processing of the incoming packet */
- return NO_PROCESS;
- }
- }
-
- break;
- case TCP_Connection_Closing:
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort);
-
- TCPHeaderOUT->Flags = (TCP_FLAG_ACK | TCP_FLAG_FIN);
- PacketResponse = true;
-
- ConnectionInfo->Buffer.InUse = false;
-
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort, TCP_Connection_FINWait1);
-
- break;
- case TCP_Connection_FINWait1:
- if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))
- {
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort);
-
- TCPHeaderOUT->Flags = TCP_FLAG_ACK;
- PacketResponse = true;
-
- ConnectionInfo->SequenceNumberIn++;
- ConnectionInfo->SequenceNumberOut++;
-
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort, TCP_Connection_Closed);
- }
- else if (TCPHeaderIN->Flags == TCP_FLAG_ACK)
- {
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort, TCP_Connection_FINWait2);
- }
-
- break;
- case TCP_Connection_FINWait2:
- if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))
- {
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort);
-
- TCPHeaderOUT->Flags = TCP_FLAG_ACK;
- PacketResponse = true;
-
- ConnectionInfo->SequenceNumberIn++;
- ConnectionInfo->SequenceNumberOut++;
-
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort, TCP_Connection_Closed);
- }
-
- break;
- case TCP_Connection_CloseWait:
- if (TCPHeaderIN->Flags == TCP_FLAG_ACK)
- {
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort, TCP_Connection_Closed);
- }
-
- break;
- }
- }
- }
- else
- {
- /* Port is not open, indicate via a RST/ACK response to the sender */
- TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK);
- PacketResponse = true;
- }
-
- /* Check if we need to respond to the sent packet */
- if (PacketResponse)
- {
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
- TCPHeaderIN->SourcePort);
-
- TCPHeaderOUT->SourcePort = TCPHeaderIN->DestinationPort;
- TCPHeaderOUT->DestinationPort = TCPHeaderIN->SourcePort;
- TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionInfo->SequenceNumberOut);
- TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionInfo->SequenceNumberIn);
- TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t));
-
- if (!(ConnectionInfo->Buffer.InUse))
- TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE);
- else
- TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length);
-
- TCPHeaderOUT->UrgentPointer = 0;
- TCPHeaderOUT->Checksum = 0;
- TCPHeaderOUT->Reserved = 0;
-
- TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, IPHeaderIN->DestinationAddress,
- IPHeaderIN->SourceAddress, sizeof(TCP_Header_t));
-
- return sizeof(TCP_Header_t);
- }
-
- return NO_RESPONSE;
-}
-
-/** Calculates the appropriate TCP checksum, consisting of the addition of the one's compliment of each word,
- * complimented.
- *
- * \param[in] TCPHeaderOutStart Pointer to the start of the packet's outgoing TCP header
- * \param[in] SourceAddress Source protocol IP address of the outgoing IP header
- * \param[in] DestinationAddress Destination protocol IP address of the outgoing IP header
- * \param[in] TCPOutSize Size in bytes of the TCP data header and payload
- *
- * \return A 16-bit TCP checksum value
- */
-static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress,
- IP_Address_t DestinationAddress, uint16_t TCPOutSize)
-{
- uint32_t Checksum = 0;
-
- /* TCP/IP checksums are the addition of the one's compliment of each word including the IP pseudo-header,
- complimented */
-
- Checksum += ((uint16_t*)&SourceAddress)[0];
- Checksum += ((uint16_t*)&SourceAddress)[1];
- Checksum += ((uint16_t*)&DestinationAddress)[0];
- Checksum += ((uint16_t*)&DestinationAddress)[1];
- Checksum += SwapEndian_16(PROTOCOL_TCP);
- Checksum += SwapEndian_16(TCPOutSize);
-
- for (uint8_t CurrWord = 0; CurrWord < (TCPOutSize >> 1); CurrWord++)
- Checksum += ((uint16_t*)TCPHeaderOutStart)[CurrWord];
-
- if (TCPOutSize & 0x01)
- Checksum += (((uint16_t*)TCPHeaderOutStart)[TCPOutSize >> 1] & 0x00FF);
-
- while (Checksum & 0xFFFF0000)
- Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16));
-
- return ~Checksum;
-}
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 + * + * Transmission Control Protocol (TCP) packet handling routines. This protocol handles the reliable in-order transmission + * and reception of packets to and from devices on a network, to "ports" on the device. It is used in situations where data + * delivery must be reliable and correct, e.g. HTTP, TELNET and most other non-streaming protocols. + */ + +#define INCLUDE_FROM_TCP_C +#include "TCP.h" + +/** Port state table array. This contains the current status of TCP ports in the device. To save on space, only open ports are + * stored - closed ports may be overwritten at any time, and the system will assume any ports not present in the array are closed. This + * allows for MAX_OPEN_TCP_PORTS to be less than the number of ports used by the application if desired. + */ +TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS]; + +/** Connection state table array. This contains the current status of TCP connections in the device. To save on space, only active + * (non-closed) connections are stored - closed connections may be overwritten at any time, and the system will assume any connections + * not present in the array are closed. + */ +TCP_ConnectionState_t ConnectionStateTable[MAX_TCP_CONNECTIONS]; + + +/** Task to handle the calling of each registered application's callback function, to process and generate TCP packets at the application + * level. If an application produces a response, this task constructs the appropriate Ethernet frame and places it into the Ethernet OUT + * buffer for later transmission. + */ +void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* RNDISInterfaceInfo) +{ + /* Run each application in sequence, to process incoming and generate outgoing packets */ + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find the corresponding port entry in the port table */ + for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++) + { + /* Run the application handler for the port */ + if ((PortStateTable[PTableEntry].Port == ConnectionStateTable[CSTableEntry].Port) && + (PortStateTable[PTableEntry].State == TCP_Port_Open)) + { + PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry], + &ConnectionStateTable[CSTableEntry].Info.Buffer); + } + } + } + + /* Get pointer to the output frame info struct for convenience */ + Ethernet_Frame_Info_t* FrameOUT = &RNDISInterfaceInfo->State.FrameOUT; + + /* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */ + if (FrameOUT->FrameInBuffer) + return; + + /* Send response packets from each application as the TCP packet buffers are filled by the applications */ + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* For each completely received packet, pass it along to the listening application */ + if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) && + (ConnectionStateTable[CSTableEntry].Info.Buffer.Ready)) + { + Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT->FrameData; + IP_Header_t* IPHeaderOUT = (IP_Header_t*)&FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t)]; + TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t) + + sizeof(IP_Header_t)]; + void* TCPDataOUT = &FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t) + + sizeof(IP_Header_t) + + sizeof(TCP_Header_t)]; + + uint16_t PacketSize = ConnectionStateTable[CSTableEntry].Info.Buffer.Length; + + /* Fill out the TCP data */ + TCPHeaderOUT->SourcePort = ConnectionStateTable[CSTableEntry].Port; + TCPHeaderOUT->DestinationPort = ConnectionStateTable[CSTableEntry].RemotePort; + TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut); + TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberIn); + TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t)); + TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE); + + TCPHeaderOUT->Flags = TCP_FLAG_ACK; + TCPHeaderOUT->UrgentPointer = 0; + TCPHeaderOUT->Checksum = 0; + TCPHeaderOUT->Reserved = 0; + + memcpy(TCPDataOUT, ConnectionStateTable[CSTableEntry].Info.Buffer.Data, PacketSize); + + ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut += PacketSize; + + TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, ServerIPAddress, + ConnectionStateTable[CSTableEntry].RemoteAddress, + (sizeof(TCP_Header_t) + PacketSize)); + + PacketSize += sizeof(TCP_Header_t); + + /* Fill out the response IP header */ + IPHeaderOUT->TotalLength = SwapEndian_16(sizeof(IP_Header_t) + PacketSize); + 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 = PROTOCOL_TCP; + IPHeaderOUT->TTL = DEFAULT_TTL; + IPHeaderOUT->SourceAddress = ServerIPAddress; + IPHeaderOUT->DestinationAddress = ConnectionStateTable[CSTableEntry].RemoteAddress; + + IPHeaderOUT->HeaderChecksum = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t)); + + PacketSize += sizeof(IP_Header_t); + + /* Fill out the response Ethernet frame header */ + FrameOUTHeader->Source = ServerMACAddress; + FrameOUTHeader->Destination = (MAC_Address_t){{0x02, 0x00, 0x02, 0x00, 0x02, 0x00}}; + FrameOUTHeader->EtherType = SwapEndian_16(ETHERTYPE_IPV4); + + PacketSize += sizeof(Ethernet_Frame_Header_t); + + /* Set the response length in the buffer and indicate that a response is ready to be sent */ + FrameOUT->FrameLength = PacketSize; + FrameOUT->FrameInBuffer = true; + + ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false; + + break; + } + } +} + +/** Initializes the TCP protocol handler, clearing the port and connection state tables. This must be called before TCP packets are + * processed. + */ +void TCP_Init(void) +{ + /* Initialize the port state table with all CLOSED entries */ + for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++) + PortStateTable[PTableEntry].State = TCP_Port_Closed; + + /* Initialize the connection table with all CLOSED entries */ + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + ConnectionStateTable[CSTableEntry].State = TCP_Connection_Closed; +} + +/** Sets the state and callback handler of the given port, specified in big endian to the given state. + * + * \param[in] Port Port whose state and callback function to set, specified in big endian + * \param[in] State New state of the port, a value from the TCP_PortStates_t enum + * \param[in] Handler Application callback handler for the port + * + * \return Boolean true if the port state was set, false otherwise (no more space in the port state table) + */ +bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*)) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + /* Check to see if the port entry is already in the port state table */ + for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++) + { + /* Find existing entry for the port in the table, update it if found */ + if (PortStateTable[PTableEntry].Port == Port) + { + PortStateTable[PTableEntry].State = State; + PortStateTable[PTableEntry].ApplicationHandler = Handler; + return true; + } + } + + /* Check if trying to open the port -- if so we need to find an unused (closed) entry and replace it */ + if (State == TCP_Port_Open) + { + for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++) + { + /* Find a closed port entry in the table, change it to the given port and state */ + if (PortStateTable[PTableEntry].State == TCP_Port_Closed) + { + PortStateTable[PTableEntry].Port = Port; + PortStateTable[PTableEntry].State = State; + PortStateTable[PTableEntry].ApplicationHandler = Handler; + return true; + } + } + + /* Port not in table and no room to add it, return failure */ + return false; + } + else + { + /* Port not in table but trying to close it, so operation successful */ + return true; + } +} + +/** Retrieves the current state of a given TCP port, specified in big endian. + * + * \param[in] Port TCP port whose state is to be retrieved, given in big-endian + * + * \return A value from the TCP_PortStates_t enum + */ +uint8_t TCP_GetPortState(uint16_t Port) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++) + { + /* Find existing entry for the port in the table, return the port status if found */ + if (PortStateTable[PTableEntry].Port == Port) + return PortStateTable[PTableEntry].State; + } + + /* Port not in table, assume closed */ + return TCP_Port_Closed; +} + +/** Sets the connection state of the given port, remote address and remote port to the given TCP connection state. If the + * connection exists in the connection state table it is updated, otherwise it is created if possible. + * + * \param[in] Port TCP port of the connection on the device, specified in big endian + * \param[in] RemoteAddress Remote protocol IP address of the connected device + * \param[in] RemotePort TCP port of the remote device in the connection, specified in big endian + * \param[in] State TCP connection state, a value from the TCP_ConnectionStates_t enum + * + * \return Boolean true if the connection was updated or created, false otherwise (no more space in the connection state table) + */ +bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find port entry in the table */ + if ((ConnectionStateTable[CSTableEntry].Port == Port) && + IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) && + ConnectionStateTable[CSTableEntry].RemotePort == RemotePort) + { + ConnectionStateTable[CSTableEntry].State = State; + return true; + } + } + + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find empty entry in the table */ + if (ConnectionStateTable[CSTableEntry].State == TCP_Connection_Closed) + { + ConnectionStateTable[CSTableEntry].Port = Port; + ConnectionStateTable[CSTableEntry].RemoteAddress = RemoteAddress; + ConnectionStateTable[CSTableEntry].RemotePort = RemotePort; + ConnectionStateTable[CSTableEntry].State = State; + return true; + } + } + + return false; +} + +/** Retrieves the current state of a given TCP connection to a host. + * + * \param[in] Port TCP port on the device in the connection, specified in big endian + * \param[in] RemoteAddress Remote protocol IP address of the connected host + * \param[in] RemotePort Remote TCP port of the connected host, specified in big endian + * + * \return A value from the TCP_ConnectionStates_t enum + */ +uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find port entry in the table */ + if ((ConnectionStateTable[CSTableEntry].Port == Port) && + IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) && + ConnectionStateTable[CSTableEntry].RemotePort == RemotePort) + + { + return ConnectionStateTable[CSTableEntry].State; + } + } + + return TCP_Connection_Closed; +} + +/** Retrieves the connection info structure of a given connection to a host. + * + * \param[in] Port TCP port on the device in the connection, specified in big endian + * \param[in] RemoteAddress Remote protocol IP address of the connected host + * \param[in] RemotePort Remote TCP port of the connected host, specified in big endian + * + * \return ConnectionInfo structure of the connection if found, NULL otherwise + */ +TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find port entry in the table */ + if ((ConnectionStateTable[CSTableEntry].Port == Port) && + IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) && + ConnectionStateTable[CSTableEntry].RemotePort == RemotePort) + { + return &ConnectionStateTable[CSTableEntry].Info; + } + } + + return NULL; +} + +/** Processes a TCP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if one is created by a application handler. + * + * \param[in] IPHeaderInStart Pointer to the start of the incoming packet's IP header + * \param[in] TCPHeaderInStart Pointer to the start of the incoming packet's TCP header + * \param[out] TCPHeaderOutStart Pointer to the start of the outgoing packet's TCP 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 TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart) +{ + IP_Header_t* IPHeaderIN = (IP_Header_t*)IPHeaderInStart; + TCP_Header_t* TCPHeaderIN = (TCP_Header_t*)TCPHeaderInStart; + TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)TCPHeaderOutStart; + + TCP_ConnectionInfo_t* ConnectionInfo; + + DecodeTCPHeader(TCPHeaderInStart); + + bool PacketResponse = false; + + /* Check if the destination port is open and allows incoming connections */ + if (TCP_GetPortState(TCPHeaderIN->DestinationPort) == TCP_Port_Open) + { + /* Detect SYN from host to start a connection */ + if (TCPHeaderIN->Flags & TCP_FLAG_SYN) + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort, TCP_Connection_Listen); + + /* Detect RST from host to abort existing connection */ + if (TCPHeaderIN->Flags & TCP_FLAG_RST) + { + if (TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Closed)) + { + TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); + PacketResponse = true; + } + } + else + { + /* Process the incoming TCP packet based on the current connection state for the sender and port */ + switch (TCP_GetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort)) + { + case TCP_Connection_Listen: + if (TCPHeaderIN->Flags == TCP_FLAG_SYN) + { + /* SYN connection starts a connection with a peer */ + if (TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_SYNReceived)) + { + TCPHeaderOUT->Flags = (TCP_FLAG_SYN | TCP_FLAG_ACK); + + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort); + + ConnectionInfo->SequenceNumberIn = (SwapEndian_32(TCPHeaderIN->SequenceNumber) + 1); + ConnectionInfo->SequenceNumberOut = 0; + ConnectionInfo->Buffer.InUse = false; + } + else + { + TCPHeaderOUT->Flags = TCP_FLAG_RST; + } + + PacketResponse = true; + } + + break; + case TCP_Connection_SYNReceived: + if (TCPHeaderIN->Flags == TCP_FLAG_ACK) + { + /* ACK during the connection process completes the connection to a peer */ + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Established); + + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + ConnectionInfo->SequenceNumberOut++; + } + + break; + case TCP_Connection_Established: + if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK)) + { + /* FIN ACK when connected to a peer starts the finalization process */ + + TCPHeaderOUT->Flags = (TCP_FLAG_FIN | TCP_FLAG_ACK); + PacketResponse = true; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_CloseWait); + + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + ConnectionInfo->SequenceNumberIn++; + ConnectionInfo->SequenceNumberOut++; + } + else if ((TCPHeaderIN->Flags == TCP_FLAG_ACK) || (TCPHeaderIN->Flags == (TCP_FLAG_ACK | TCP_FLAG_PSH))) + { + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + /* Check if the buffer is currently in use either by a buffered data to send, or receive */ + if ((ConnectionInfo->Buffer.InUse == false) && (ConnectionInfo->Buffer.Ready == false)) + { + ConnectionInfo->Buffer.Direction = TCP_PACKETDIR_IN; + ConnectionInfo->Buffer.InUse = true; + ConnectionInfo->Buffer.Length = 0; + } + + /* Check if the buffer has been claimed by us to read in data from the peer */ + if ((ConnectionInfo->Buffer.Direction == TCP_PACKETDIR_IN) && + (ConnectionInfo->Buffer.Length != TCP_WINDOW_SIZE)) + { + uint16_t IPOffset = (IPHeaderIN->HeaderLength * sizeof(uint32_t)); + uint16_t TCPOffset = (TCPHeaderIN->DataOffset * sizeof(uint32_t)); + uint16_t DataLength = (SwapEndian_16(IPHeaderIN->TotalLength) - IPOffset - TCPOffset); + + /* Copy the packet data into the buffer */ + memcpy(&ConnectionInfo->Buffer.Data[ConnectionInfo->Buffer.Length], + &((uint8_t*)TCPHeaderInStart)[TCPOffset], + DataLength); + + ConnectionInfo->SequenceNumberIn += DataLength; + ConnectionInfo->Buffer.Length += DataLength; + + /* Check if the buffer is full or if the PSH flag is set, if so indicate buffer ready */ + if ((!(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length)) || (TCPHeaderIN->Flags & TCP_FLAG_PSH)) + { + ConnectionInfo->Buffer.InUse = false; + ConnectionInfo->Buffer.Ready = true; + + TCPHeaderOUT->Flags = TCP_FLAG_ACK; + PacketResponse = true; + } + } + else + { + /* Buffer is currently in use by the application, defer processing of the incoming packet */ + return NO_PROCESS; + } + } + + break; + case TCP_Connection_Closing: + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + TCPHeaderOUT->Flags = (TCP_FLAG_ACK | TCP_FLAG_FIN); + PacketResponse = true; + + ConnectionInfo->Buffer.InUse = false; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_FINWait1); + + break; + case TCP_Connection_FINWait1: + if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK)) + { + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + TCPHeaderOUT->Flags = TCP_FLAG_ACK; + PacketResponse = true; + + ConnectionInfo->SequenceNumberIn++; + ConnectionInfo->SequenceNumberOut++; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Closed); + } + else if (TCPHeaderIN->Flags == TCP_FLAG_ACK) + { + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_FINWait2); + } + + break; + case TCP_Connection_FINWait2: + if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK)) + { + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + TCPHeaderOUT->Flags = TCP_FLAG_ACK; + PacketResponse = true; + + ConnectionInfo->SequenceNumberIn++; + ConnectionInfo->SequenceNumberOut++; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Closed); + } + + break; + case TCP_Connection_CloseWait: + if (TCPHeaderIN->Flags == TCP_FLAG_ACK) + { + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Closed); + } + + break; + } + } + } + else + { + /* Port is not open, indicate via a RST/ACK response to the sender */ + TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); + PacketResponse = true; + } + + /* Check if we need to respond to the sent packet */ + if (PacketResponse) + { + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + TCPHeaderOUT->SourcePort = TCPHeaderIN->DestinationPort; + TCPHeaderOUT->DestinationPort = TCPHeaderIN->SourcePort; + TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionInfo->SequenceNumberOut); + TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionInfo->SequenceNumberIn); + TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t)); + + if (!(ConnectionInfo->Buffer.InUse)) + TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE); + else + TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length); + + TCPHeaderOUT->UrgentPointer = 0; + TCPHeaderOUT->Checksum = 0; + TCPHeaderOUT->Reserved = 0; + + TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, IPHeaderIN->DestinationAddress, + IPHeaderIN->SourceAddress, sizeof(TCP_Header_t)); + + return sizeof(TCP_Header_t); + } + + return NO_RESPONSE; +} + +/** Calculates the appropriate TCP checksum, consisting of the addition of the one's compliment of each word, + * complimented. + * + * \param[in] TCPHeaderOutStart Pointer to the start of the packet's outgoing TCP header + * \param[in] SourceAddress Source protocol IP address of the outgoing IP header + * \param[in] DestinationAddress Destination protocol IP address of the outgoing IP header + * \param[in] TCPOutSize Size in bytes of the TCP data header and payload + * + * \return A 16-bit TCP checksum value + */ +static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress, + IP_Address_t DestinationAddress, uint16_t TCPOutSize) +{ + uint32_t Checksum = 0; + + /* TCP/IP checksums are the addition of the one's compliment of each word including the IP pseudo-header, + complimented */ + + Checksum += ((uint16_t*)&SourceAddress)[0]; + Checksum += ((uint16_t*)&SourceAddress)[1]; + Checksum += ((uint16_t*)&DestinationAddress)[0]; + Checksum += ((uint16_t*)&DestinationAddress)[1]; + Checksum += SwapEndian_16(PROTOCOL_TCP); + Checksum += SwapEndian_16(TCPOutSize); + + for (uint8_t CurrWord = 0; CurrWord < (TCPOutSize >> 1); CurrWord++) + Checksum += ((uint16_t*)TCPHeaderOutStart)[CurrWord]; + + if (TCPOutSize & 0x01) + Checksum += (((uint16_t*)TCPHeaderOutStart)[TCPOutSize >> 1] & 0x00FF); + + while (Checksum & 0xFFFF0000) + Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16)); + + return ~Checksum; +} diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h index d84256024..4baa0898f 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h @@ -1,249 +1,249 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 TCP.c.
- */
-
-#ifndef _TCP_H_
-#define _TCP_H_
-
- /* Includes: */
- #include <avr/io.h>
- #include <stdbool.h>
-
- #include "EthernetProtocols.h"
- #include "Ethernet.h"
- #include "ProtocolDecoders.h"
-
- /* Macros: */
- /** Maximum number of TCP ports which can be open at the one time */
- #define MAX_OPEN_TCP_PORTS 1
-
- /** Maximum number of TCP connections which can be sustained at the one time */
- #define MAX_TCP_CONNECTIONS 3
-
- /** TCP window size, giving the maximum number of bytes which can be buffered at the one time */
- #define TCP_WINDOW_SIZE 512
-
- /** Port number for HTTP transmissions */
- #define TCP_PORT_HTTP SwapEndian_16(80)
-
- /** Data direction indicator for a TCP application buffer, indicating data from host-to-device */
- #define TCP_PACKETDIR_IN false
-
- /** Data direction indicator for a TCP application buffer, indicating data from device-to-host */
- #define TCP_PACKETDIR_OUT true
-
- /** Congestion Window Reduced TCP flag mask */
- #define TCP_FLAG_CWR (1 << 7)
-
- /** Explicit Congestion Notification TCP flag mask */
- #define TCP_FLAG_ECE (1 << 6)
-
- /** Urgent TCP flag mask */
- #define TCP_FLAG_URG (1 << 5)
-
- /** Data Acknowledge TCP flag mask */
- #define TCP_FLAG_ACK (1 << 4)
-
- /** Data Push TCP flag mask */
- #define TCP_FLAG_PSH (1 << 3)
-
- /** Reset TCP flag mask */
- #define TCP_FLAG_RST (1 << 2)
-
- /** Synchronize TCP flag mask */
- #define TCP_FLAG_SYN (1 << 1)
-
- /** Connection Finalize TCP flag mask */
- #define TCP_FLAG_FIN (1 << 0)
-
- /** Application macro: Determines if the given application buffer contains a packet received from the host
- *
- * \param[in] Buffer Application buffer to check
- *
- * \return Boolean true if the buffer contains a packet from the host, false otherwise
- */
- #define TCP_APP_HAS_RECEIVED_PACKET(Buffer) (Buffer->Ready && (Buffer->Direction == TCP_PACKETDIR_IN))
-
- /** Application macro: Indicates if the application buffer is currently locked by the application for device-to-host transfers.
- *
- * \param[in] Buffer Application buffer to check
- *
- * \return Boolean true if the buffer has been captured by the application for device-to-host transmissions, false otherwise
- */
- #define TCP_APP_HAVE_CAPTURED_BUFFER(Buffer) (!(Buffer->Ready) && Buffer->InUse && \
- (Buffer->Direction == TCP_PACKETDIR_OUT))
-
- /** Application macro: Indicates if the application can lock the buffer for multiple continued device-to-host transmissions.
- *
- * \param[in] Buffer Application buffer to check
- *
- * \return Boolean true if the buffer may be captured by the application for device-to-host transmissions, false otherwise
- */
- #define TCP_APP_CAN_CAPTURE_BUFFER(Buffer) Buffer->InUse
-
- /** Application macro: Captures the application buffer, locking it for device-to-host transmissions only. This should be
- * performed when the application needs to transmit several packets worth of data in succession with no interruptions from the host.
- *
- * \note The application must check that the buffer can be locked first using TCP_APP_CAN_CAPTURE_BUFFER().
- *
- * \param[in] Buffer Application buffer to lock
- */
- #define TCP_APP_CAPTURE_BUFFER(Buffer) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->InUse = true; }MACROE
-
- /** Application macro: Releases a captured application buffer, allowing for host-to-device packets to be received.
- *
- * \param[in] Buffer Application buffer to release
- */
- #define TCP_APP_RELEASE_BUFFER(Buffer) MACROS{ Buffer->InUse = false; }MACROE
-
- /** Application macro: Sends the contents of the given application buffer to the host.
- *
- * \param[in] Buffer Application buffer to send
- * \param[in] Len Length of data contained in the buffer
- */
- #define TCP_APP_SEND_BUFFER(Buffer, Len) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->Length = Len; Buffer->Ready = true; }MACROE
-
- /** Application macro: Clears the application buffer, ready for a packet to be written to it.
- *
- * \param[in] Buffer Application buffer to clear
- */
- #define TCP_APP_CLEAR_BUFFER(Buffer) MACROS{ Buffer->Ready = false; Buffer->Length = 0; }MACROE
-
- /** Application macro: Closes an open connection to a host.
- *
- * \param[in] Connection Open TCP connection to close
- */
- #define TCP_APP_CLOSECONNECTION(Connection) MACROS{ Connection->State = TCP_Connection_Closing; }MACROE
-
- /* Enums: */
- /** Enum for possible TCP port states */
- enum TCP_PortStates_t
- {
- TCP_Port_Closed = 0, /**< TCP port closed, no connections to a host may be made on this port. */
- TCP_Port_Open = 1, /**< TCP port open, connections to a host may be made on this port. */
- };
-
- /** Enum for possible TCP connection states */
- enum TCP_ConnectionStates_t
- {
- TCP_Connection_Listen = 0, /**< Listening for a connection from a host */
- TCP_Connection_SYNSent = 1, /**< Unused */
- TCP_Connection_SYNReceived = 2, /**< SYN received, waiting for ACK */
- TCP_Connection_Established = 3, /**< Connection established in both directions */
- TCP_Connection_FINWait1 = 4, /**< Closing, waiting for ACK */
- TCP_Connection_FINWait2 = 5, /**< Closing, waiting for FIN ACK */
- TCP_Connection_CloseWait = 6, /**< Closing, waiting for ACK */
- TCP_Connection_Closing = 7, /**< Unused */
- TCP_Connection_LastACK = 8, /**< Unused */
- TCP_Connection_TimeWait = 9, /**< Unused */
- TCP_Connection_Closed = 10, /**< Connection closed in both directions */
- };
-
- /* Type Defines: */
- /** Type define for a TCP connection buffer structure, including size, data and direction */
- typedef struct
- {
- uint16_t Length; /**< Length of data in the TCP application buffer */
- uint8_t Data[TCP_WINDOW_SIZE]; /**< TCP application data buffer */
- bool Direction; /**< Buffer transmission direction, either TCP_PACKETDIR_IN or TCP_PACKETDIR_OUT */
- bool Ready; /**< If data from host, indicates buffer ready to be read, otherwise indicates
- * buffer ready to be sent to the host
- */
- bool InUse; /** Indicates if the buffer is locked to to the current direction, and cannot be changed */
- } TCP_ConnectionBuffer_t;
-
- /** Type define for a TCP connection information structure */
- typedef struct
- {
- uint32_t SequenceNumberIn; /**< Current TCP sequence number for host-to-device */
- uint32_t SequenceNumberOut; /**< Current TCP sequence number for device-to-host */
- TCP_ConnectionBuffer_t Buffer; /**< Connection application data buffer */
- } TCP_ConnectionInfo_t;
-
- /** Type define for a complete TCP connection state */
- typedef struct
- {
- uint16_t Port; /**< Connection port number on the device */
- uint16_t RemotePort; /**< Connection port number on the host */
- IP_Address_t RemoteAddress; /**< Connection protocol IP address of the host */
- TCP_ConnectionInfo_t Info; /**< Connection information, including application buffer */
- uint8_t State; /**< Current connection state, a value from the TCP_ConnectionStates_t enum */
- } TCP_ConnectionState_t;
-
- /** Type define for a TCP port state */
- typedef struct
- {
- uint16_t Port; /**< TCP port number on the device */
- uint8_t State; /**< Current port state, a value from the TCP_PortStates_t enum */
- void (*ApplicationHandler) (TCP_ConnectionState_t* ConnectionState,
- TCP_ConnectionBuffer_t* Buffer); /**< Port application handler */
- } TCP_PortState_t;
-
- /** Type define for a TCP packet header */
- typedef struct
- {
- uint16_t SourcePort; /**< Source port of the TCP packet */
- uint16_t DestinationPort; /**< Destination port of the TCP packet */
-
- uint32_t SequenceNumber; /**< Data sequence number of the packet */
- uint32_t AcknowledgmentNumber; /**< Data acknowledgment number of the packet */
-
- unsigned char Reserved : 4; /**< Reserved, must be all 0 */
- unsigned char DataOffset : 4; /**< Offset of the data from the start of the header, in 4 byte chunks */
- uint8_t Flags; /**< TCP packet flags */
- uint16_t WindowSize; /**< Current data window size (bytes remaining in reception buffer) */
-
- uint16_t Checksum; /**< TCP checksum */
- uint16_t UrgentPointer; /**< Urgent data pointer */
- } TCP_Header_t;
-
- /* External Variables: */
- TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS];
-
- /* Function Prototypes: */
- void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* RNDISInterfaceInfo);
- void TCP_Init(void);
- bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*));
- uint8_t TCP_GetPortState(uint16_t Port);
- bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State);
- uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort);
- TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort);
- int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart);
-
- #if defined(INCLUDE_FROM_TCP_C)
- static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress,
- IP_Address_t DestinationAddress, uint16_t TCPOutSize);
- #endif
-
-#endif
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 TCP.c. + */ + +#ifndef _TCP_H_ +#define _TCP_H_ + + /* Includes: */ + #include <avr/io.h> + #include <stdbool.h> + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** Maximum number of TCP ports which can be open at the one time */ + #define MAX_OPEN_TCP_PORTS 1 + + /** Maximum number of TCP connections which can be sustained at the one time */ + #define MAX_TCP_CONNECTIONS 3 + + /** TCP window size, giving the maximum number of bytes which can be buffered at the one time */ + #define TCP_WINDOW_SIZE 512 + + /** Port number for HTTP transmissions */ + #define TCP_PORT_HTTP SwapEndian_16(80) + + /** Data direction indicator for a TCP application buffer, indicating data from host-to-device */ + #define TCP_PACKETDIR_IN false + + /** Data direction indicator for a TCP application buffer, indicating data from device-to-host */ + #define TCP_PACKETDIR_OUT true + + /** Congestion Window Reduced TCP flag mask */ + #define TCP_FLAG_CWR (1 << 7) + + /** Explicit Congestion Notification TCP flag mask */ + #define TCP_FLAG_ECE (1 << 6) + + /** Urgent TCP flag mask */ + #define TCP_FLAG_URG (1 << 5) + + /** Data Acknowledge TCP flag mask */ + #define TCP_FLAG_ACK (1 << 4) + + /** Data Push TCP flag mask */ + #define TCP_FLAG_PSH (1 << 3) + + /** Reset TCP flag mask */ + #define TCP_FLAG_RST (1 << 2) + + /** Synchronize TCP flag mask */ + #define TCP_FLAG_SYN (1 << 1) + + /** Connection Finalize TCP flag mask */ + #define TCP_FLAG_FIN (1 << 0) + + /** Application macro: Determines if the given application buffer contains a packet received from the host + * + * \param[in] Buffer Application buffer to check + * + * \return Boolean true if the buffer contains a packet from the host, false otherwise + */ + #define TCP_APP_HAS_RECEIVED_PACKET(Buffer) (Buffer->Ready && (Buffer->Direction == TCP_PACKETDIR_IN)) + + /** Application macro: Indicates if the application buffer is currently locked by the application for device-to-host transfers. + * + * \param[in] Buffer Application buffer to check + * + * \return Boolean true if the buffer has been captured by the application for device-to-host transmissions, false otherwise + */ + #define TCP_APP_HAVE_CAPTURED_BUFFER(Buffer) (!(Buffer->Ready) && Buffer->InUse && \ + (Buffer->Direction == TCP_PACKETDIR_OUT)) + + /** Application macro: Indicates if the application can lock the buffer for multiple continued device-to-host transmissions. + * + * \param[in] Buffer Application buffer to check + * + * \return Boolean true if the buffer may be captured by the application for device-to-host transmissions, false otherwise + */ + #define TCP_APP_CAN_CAPTURE_BUFFER(Buffer) Buffer->InUse + + /** Application macro: Captures the application buffer, locking it for device-to-host transmissions only. This should be + * performed when the application needs to transmit several packets worth of data in succession with no interruptions from the host. + * + * \note The application must check that the buffer can be locked first using TCP_APP_CAN_CAPTURE_BUFFER(). + * + * \param[in] Buffer Application buffer to lock + */ + #define TCP_APP_CAPTURE_BUFFER(Buffer) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->InUse = true; }MACROE + + /** Application macro: Releases a captured application buffer, allowing for host-to-device packets to be received. + * + * \param[in] Buffer Application buffer to release + */ + #define TCP_APP_RELEASE_BUFFER(Buffer) MACROS{ Buffer->InUse = false; }MACROE + + /** Application macro: Sends the contents of the given application buffer to the host. + * + * \param[in] Buffer Application buffer to send + * \param[in] Len Length of data contained in the buffer + */ + #define TCP_APP_SEND_BUFFER(Buffer, Len) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->Length = Len; Buffer->Ready = true; }MACROE + + /** Application macro: Clears the application buffer, ready for a packet to be written to it. + * + * \param[in] Buffer Application buffer to clear + */ + #define TCP_APP_CLEAR_BUFFER(Buffer) MACROS{ Buffer->Ready = false; Buffer->Length = 0; }MACROE + + /** Application macro: Closes an open connection to a host. + * + * \param[in] Connection Open TCP connection to close + */ + #define TCP_APP_CLOSECONNECTION(Connection) MACROS{ Connection->State = TCP_Connection_Closing; }MACROE + + /* Enums: */ + /** Enum for possible TCP port states */ + enum TCP_PortStates_t + { + TCP_Port_Closed = 0, /**< TCP port closed, no connections to a host may be made on this port. */ + TCP_Port_Open = 1, /**< TCP port open, connections to a host may be made on this port. */ + }; + + /** Enum for possible TCP connection states */ + enum TCP_ConnectionStates_t + { + TCP_Connection_Listen = 0, /**< Listening for a connection from a host */ + TCP_Connection_SYNSent = 1, /**< Unused */ + TCP_Connection_SYNReceived = 2, /**< SYN received, waiting for ACK */ + TCP_Connection_Established = 3, /**< Connection established in both directions */ + TCP_Connection_FINWait1 = 4, /**< Closing, waiting for ACK */ + TCP_Connection_FINWait2 = 5, /**< Closing, waiting for FIN ACK */ + TCP_Connection_CloseWait = 6, /**< Closing, waiting for ACK */ + TCP_Connection_Closing = 7, /**< Unused */ + TCP_Connection_LastACK = 8, /**< Unused */ + TCP_Connection_TimeWait = 9, /**< Unused */ + TCP_Connection_Closed = 10, /**< Connection closed in both directions */ + }; + + /* Type Defines: */ + /** Type define for a TCP connection buffer structure, including size, data and direction */ + typedef struct + { + uint16_t Length; /**< Length of data in the TCP application buffer */ + uint8_t Data[TCP_WINDOW_SIZE]; /**< TCP application data buffer */ + bool Direction; /**< Buffer transmission direction, either TCP_PACKETDIR_IN or TCP_PACKETDIR_OUT */ + bool Ready; /**< If data from host, indicates buffer ready to be read, otherwise indicates + * buffer ready to be sent to the host + */ + bool InUse; /** Indicates if the buffer is locked to to the current direction, and cannot be changed */ + } TCP_ConnectionBuffer_t; + + /** Type define for a TCP connection information structure */ + typedef struct + { + uint32_t SequenceNumberIn; /**< Current TCP sequence number for host-to-device */ + uint32_t SequenceNumberOut; /**< Current TCP sequence number for device-to-host */ + TCP_ConnectionBuffer_t Buffer; /**< Connection application data buffer */ + } TCP_ConnectionInfo_t; + + /** Type define for a complete TCP connection state */ + typedef struct + { + uint16_t Port; /**< Connection port number on the device */ + uint16_t RemotePort; /**< Connection port number on the host */ + IP_Address_t RemoteAddress; /**< Connection protocol IP address of the host */ + TCP_ConnectionInfo_t Info; /**< Connection information, including application buffer */ + uint8_t State; /**< Current connection state, a value from the TCP_ConnectionStates_t enum */ + } TCP_ConnectionState_t; + + /** Type define for a TCP port state */ + typedef struct + { + uint16_t Port; /**< TCP port number on the device */ + uint8_t State; /**< Current port state, a value from the TCP_PortStates_t enum */ + void (*ApplicationHandler) (TCP_ConnectionState_t* ConnectionState, + TCP_ConnectionBuffer_t* Buffer); /**< Port application handler */ + } TCP_PortState_t; + + /** Type define for a TCP packet header */ + typedef struct + { + uint16_t SourcePort; /**< Source port of the TCP packet */ + uint16_t DestinationPort; /**< Destination port of the TCP packet */ + + uint32_t SequenceNumber; /**< Data sequence number of the packet */ + uint32_t AcknowledgmentNumber; /**< Data acknowledgment number of the packet */ + + unsigned char Reserved : 4; /**< Reserved, must be all 0 */ + unsigned char DataOffset : 4; /**< Offset of the data from the start of the header, in 4 byte chunks */ + uint8_t Flags; /**< TCP packet flags */ + uint16_t WindowSize; /**< Current data window size (bytes remaining in reception buffer) */ + + uint16_t Checksum; /**< TCP checksum */ + uint16_t UrgentPointer; /**< Urgent data pointer */ + } TCP_Header_t; + + /* External Variables: */ + TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS]; + + /* Function Prototypes: */ + void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* RNDISInterfaceInfo); + void TCP_Init(void); + bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*)); + uint8_t TCP_GetPortState(uint16_t Port); + bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State); + uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort); + TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort); + int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart); + + #if defined(INCLUDE_FROM_TCP_C) + static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress, + IP_Address_t DestinationAddress, uint16_t TCPOutSize); + #endif + +#endif diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.c index 47b0ab87a..c9c523f71 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.c @@ -1,81 +1,81 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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
- *
- * User Datagram Protocol (UDP) packet handling routines. This protocol handles high throughput, low
- * reliability packets which are typically used to encapsulate streaming data.
- */
-
-#define INCLUDE_FROM_UDP_C
-#include "UDP.h"
-
-/** Processes a UDP packet inside an Ethernet frame, and writes the appropriate response
- * to the output Ethernet frame if a sub-protocol handler has created a response packet.
- *
- * \param[in] IPHeaderInStart Pointer to the start of the incoming packet's IP header
- * \param[in] UDPHeaderInStart Pointer to the start of the incoming packet's UDP header
- * \param[out] UDPHeaderOutStart Pointer to the start of the outgoing packet's UDP header
- *
- * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise
- */
-int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart)
-{
- UDP_Header_t* UDPHeaderIN = (UDP_Header_t*)UDPHeaderInStart;
- UDP_Header_t* UDPHeaderOUT = (UDP_Header_t*)UDPHeaderOutStart;
-
- int16_t RetSize = NO_RESPONSE;
-
- DecodeUDPHeader(UDPHeaderInStart);
-
- switch (SwapEndian_16(UDPHeaderIN->DestinationPort))
- {
- case UDP_PORT_DHCP_REQUEST:
- RetSize = DHCP_ProcessDHCPPacket(IPHeaderInStart,
- &((uint8_t*)UDPHeaderInStart)[sizeof(UDP_Header_t)],
- &((uint8_t*)UDPHeaderOutStart)[sizeof(UDP_Header_t)]);
- break;
- }
-
- /* Check to see if the protocol processing routine has filled out a response */
- if (RetSize > 0)
- {
- /* Fill out the response UDP packet header */
- UDPHeaderOUT->SourcePort = UDPHeaderIN->DestinationPort;
- UDPHeaderOUT->DestinationPort = UDPHeaderIN->SourcePort;
- UDPHeaderOUT->Checksum = 0;
- UDPHeaderOUT->Length = SwapEndian_16(sizeof(UDP_Header_t) + RetSize);
-
- /* Return the size of the response so far */
- return (sizeof(UDP_Header_t) + RetSize);
- }
-
- return NO_RESPONSE;
-}
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 + * + * User Datagram Protocol (UDP) packet handling routines. This protocol handles high throughput, low + * reliability packets which are typically used to encapsulate streaming data. + */ + +#define INCLUDE_FROM_UDP_C +#include "UDP.h" + +/** Processes a UDP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if a sub-protocol handler has created a response packet. + * + * \param[in] IPHeaderInStart Pointer to the start of the incoming packet's IP header + * \param[in] UDPHeaderInStart Pointer to the start of the incoming packet's UDP header + * \param[out] UDPHeaderOutStart Pointer to the start of the outgoing packet's UDP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise + */ +int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart) +{ + UDP_Header_t* UDPHeaderIN = (UDP_Header_t*)UDPHeaderInStart; + UDP_Header_t* UDPHeaderOUT = (UDP_Header_t*)UDPHeaderOutStart; + + int16_t RetSize = NO_RESPONSE; + + DecodeUDPHeader(UDPHeaderInStart); + + switch (SwapEndian_16(UDPHeaderIN->DestinationPort)) + { + case UDP_PORT_DHCP_REQUEST: + RetSize = DHCP_ProcessDHCPPacket(IPHeaderInStart, + &((uint8_t*)UDPHeaderInStart)[sizeof(UDP_Header_t)], + &((uint8_t*)UDPHeaderOutStart)[sizeof(UDP_Header_t)]); + break; + } + + /* Check to see if the protocol processing routine has filled out a response */ + if (RetSize > 0) + { + /* Fill out the response UDP packet header */ + UDPHeaderOUT->SourcePort = UDPHeaderIN->DestinationPort; + UDPHeaderOUT->DestinationPort = UDPHeaderIN->SourcePort; + UDPHeaderOUT->Checksum = 0; + UDPHeaderOUT->Length = SwapEndian_16(sizeof(UDP_Header_t) + RetSize); + + /* Return the size of the response so far */ + return (sizeof(UDP_Header_t) + RetSize); + } + + return NO_RESPONSE; +} diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.h index 7725d6c2f..73f7664f7 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.h @@ -1,67 +1,67 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 _UDP_H_
-#define _UDP_H_
-
- /* Includes: */
- #include <avr/io.h>
-
- #include "EthernetProtocols.h"
- #include "Ethernet.h"
- #include "ProtocolDecoders.h"
- #include "DHCP.h"
-
- /* Macros: */
- /** Source UDP port for a DHCP request */
- #define UDP_PORT_DHCP_REQUEST 67
-
- /** Destination UDP port for a DHCP reply */
- #define UDP_PORT_DHCP_REPLY 68
-
- /* Type Defines: */
- /** Type define for a UDP packet header */
- typedef struct
- {
- uint16_t SourcePort; /**< Packet source port */
- uint16_t DestinationPort; /**< Packet destination port */
- uint16_t Length; /**< Total packet length, in bytes */
- uint16_t Checksum; /**< Optional UDP packet checksum */
- } UDP_Header_t;
-
- /* Function Prototypes: */
- int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart);
-
-#endif
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 _UDP_H_ +#define _UDP_H_ + + /* Includes: */ + #include <avr/io.h> + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + #include "DHCP.h" + + /* Macros: */ + /** Source UDP port for a DHCP request */ + #define UDP_PORT_DHCP_REQUEST 67 + + /** Destination UDP port for a DHCP reply */ + #define UDP_PORT_DHCP_REPLY 68 + + /* Type Defines: */ + /** Type define for a UDP packet header */ + typedef struct + { + uint16_t SourcePort; /**< Packet source port */ + uint16_t DestinationPort; /**< Packet destination port */ + uint16_t Length; /**< Total packet length, in bytes */ + uint16_t Checksum; /**< Optional UDP packet checksum */ + } UDP_Header_t; + + /* Function Prototypes: */ + int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart); + +#endif diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.c index 7f2502027..7f90de3b8 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.c @@ -1,200 +1,200 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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
- *
- * Simple webserver application for demonstrating the RNDIS demo and TCP/IP stack. This
- * application will serve up a static HTTP web page when requested by the host.
- */
-
-#include "Webserver.h"
-
-/** HTTP server response header, for transmission before the page contents. This indicates to the host that a page exists at the
- * given location, and gives extra connection information.
- */
-char PROGMEM HTTP200Header[] = "HTTP/1.1 200 OK\r\n"
- "Server: LUFA RNDIS\r\n"
- "Content-type: text/html\r\n"
- "Connection: close\r\n\r\n";
-
-/** HTTP server response header, for transmission before a resource not found error. This indicates to the host that the given
- * given URL is invalid, and gives extra error information.
- */
-char PROGMEM HTTP404Header[] = "HTTP/1.1 404 Not Found\r\n"
- "Server: LUFA RNDIS\r\n"
- "Connection: close\r\n\r\n";
-
-/** HTTP page to serve to the host when a HTTP request is made. This page is too long for a single response, thus it is automatically
- * broken up into smaller blocks and sent as a series of packets each time the webserver application callback is run.
- */
-char PROGMEM HTTPPage[] =
- "<html>"
- " <head>"
- " <title>"
- " LUFA Webserver Demo"
- " </title>"
- " </head>"
- " <body>"
- " <h1>Hello from your USB AVR!</h1>"
- " <p>"
- " Hello! Welcome to the LUFA RNDIS Demo Webserver test page, running on your USB AVR via the LUFA library. This demonstrates the HTTP webserver, TCP/IP stack and RNDIS demo all running atop the LUFA USB stack."
- " <br /><br />"
- " <small>Project Information: <a href=\"http://www.fourwalledcubicle.com/LUFA.php\">http://www.fourwalledcubicle.com/LUFA.php</a>.</small>"
- " <hr />"
- " <i>LUFA Version: </i>" LUFA_VERSION_STRING
- " </p>"
- " </body>"
- "</html>";
-
-
-/** Initializes the Webserver application, opening the appropriate HTTP port in the TCP handler and registering the application
- * callback routine for packets sent to the HTTP protocol port.
- */
-void Webserver_Init(void)
-{
- /* Open the HTTP port in the TCP protocol so that HTTP connections to the device can be established */
- TCP_SetPortState(TCP_PORT_HTTP, TCP_Port_Open, Webserver_ApplicationCallback);
-}
-
-/** Indicates if a given request equals the given HTTP command.
- *
- * \param[in] RequestHeader HTTP request made by the host
- * \param[in] Command HTTP command to compare the request to
- *
- * \return Boolean true if the command matches the request, false otherwise
- */
-static bool IsHTTPCommand(uint8_t* RequestHeader, char* Command)
-{
- /* Returns true if the non null terminated string in RequestHeader matches the null terminated string Command */
- return (strncmp((char*)RequestHeader, Command, strlen(Command)) == 0);
-}
-
-/** Application callback routine, executed each time the TCP processing task runs. This callback determines what request
- * has been made (if any), and serves up appropriate responses.
- *
- * \param[in] ConnectionState Pointer to a TCP Connection State structure giving connection information
- * \param[in,out] Buffer Pointer to the application's send/receive packet buffer
- */
-void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer)
-{
- char* BufferDataStr = (char*)Buffer->Data;
- static uint8_t PageBlock = 0;
-
- /* Check to see if a packet has been received on the HTTP port from a remote host */
- if (TCP_APP_HAS_RECEIVED_PACKET(Buffer))
- {
- if (IsHTTPCommand(Buffer->Data, "GET"))
- {
- if (IsHTTPCommand(Buffer->Data, "GET / "))
- {
- PageBlock = 0;
-
- /* Copy the HTTP 200 response header into the packet buffer */
- strcpy_P(BufferDataStr, HTTP200Header);
-
- /* Send the buffer contents to the host */
- TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr));
-
- /* Lock the buffer to Device->Host transmissions only while we send the page contents */
- TCP_APP_CAPTURE_BUFFER(Buffer);
- }
- else
- {
- /* Copy the HTTP 404 response header into the packet buffer */
- strcpy_P(BufferDataStr, HTTP404Header);
-
- /* Send the buffer contents to the host */
- TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr));
-
- /* All data sent, close the connection */
- TCP_APP_CLOSECONNECTION(ConnectionState);
- }
- }
- else if (IsHTTPCommand(Buffer->Data, "HEAD"))
- {
- if (IsHTTPCommand(Buffer->Data, "HEAD / "))
- {
- /* Copy the HTTP response header into the packet buffer */
- strcpy_P(BufferDataStr, HTTP200Header);
-
- /* Send the buffer contents to the host */
- TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr));
- }
- else
- {
- /* Copy the HTTP response header into the packet buffer */
- strcpy_P(BufferDataStr, HTTP404Header);
-
- /* Send the buffer contents to the host */
- TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr));
- }
-
- /* All data sent, close the connection */
- TCP_APP_CLOSECONNECTION(ConnectionState);
- }
- else if (IsHTTPCommand(Buffer->Data, "TRACE"))
- {
- /* Echo the host's query back to the host */
- TCP_APP_SEND_BUFFER(Buffer, Buffer->Length);
-
- /* All data sent, close the connection */
- TCP_APP_CLOSECONNECTION(ConnectionState);
- }
- else
- {
- /* Unknown request, just clear the buffer (drop the packet) */
- TCP_APP_CLEAR_BUFFER(Buffer);
- }
- }
- else if (TCP_APP_HAVE_CAPTURED_BUFFER(Buffer))
- {
- uint16_t RemLength = strlen_P(&HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE]);
- uint16_t Length;
-
- /* Determine the length of the loaded block */
- Length = ((RemLength > HTTP_REPLY_BLOCK_SIZE) ? HTTP_REPLY_BLOCK_SIZE : RemLength);
-
- /* Copy the next buffer sized block of the page to the packet buffer */
- strncpy_P(BufferDataStr, &HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE], Length);
-
- /* Send the buffer contents to the host */
- TCP_APP_SEND_BUFFER(Buffer, Length);
-
- /* Check to see if the entire page has been sent */
- if (PageBlock++ == (sizeof(HTTPPage) / HTTP_REPLY_BLOCK_SIZE))
- {
- /* Unlock the buffer so that the host can fill it with future packets */
- TCP_APP_RELEASE_BUFFER(Buffer);
-
- /* Close the connection to the host */
- TCP_APP_CLOSECONNECTION(ConnectionState);
- }
- }
-}
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 + * + * Simple webserver application for demonstrating the RNDIS demo and TCP/IP stack. This + * application will serve up a static HTTP web page when requested by the host. + */ + +#include "Webserver.h" + +/** HTTP server response header, for transmission before the page contents. This indicates to the host that a page exists at the + * given location, and gives extra connection information. + */ +char PROGMEM HTTP200Header[] = "HTTP/1.1 200 OK\r\n" + "Server: LUFA RNDIS\r\n" + "Content-type: text/html\r\n" + "Connection: close\r\n\r\n"; + +/** HTTP server response header, for transmission before a resource not found error. This indicates to the host that the given + * given URL is invalid, and gives extra error information. + */ +char PROGMEM HTTP404Header[] = "HTTP/1.1 404 Not Found\r\n" + "Server: LUFA RNDIS\r\n" + "Connection: close\r\n\r\n"; + +/** HTTP page to serve to the host when a HTTP request is made. This page is too long for a single response, thus it is automatically + * broken up into smaller blocks and sent as a series of packets each time the webserver application callback is run. + */ +char PROGMEM HTTPPage[] = + "<html>" + " <head>" + " <title>" + " LUFA Webserver Demo" + " </title>" + " </head>" + " <body>" + " <h1>Hello from your USB AVR!</h1>" + " <p>" + " Hello! Welcome to the LUFA RNDIS Demo Webserver test page, running on your USB AVR via the LUFA library. This demonstrates the HTTP webserver, TCP/IP stack and RNDIS demo all running atop the LUFA USB stack." + " <br /><br />" + " <small>Project Information: <a href=\"http://www.fourwalledcubicle.com/LUFA.php\">http://www.fourwalledcubicle.com/LUFA.php</a>.</small>" + " <hr />" + " <i>LUFA Version: </i>" LUFA_VERSION_STRING + " </p>" + " </body>" + "</html>"; + + +/** Initializes the Webserver application, opening the appropriate HTTP port in the TCP handler and registering the application + * callback routine for packets sent to the HTTP protocol port. + */ +void Webserver_Init(void) +{ + /* Open the HTTP port in the TCP protocol so that HTTP connections to the device can be established */ + TCP_SetPortState(TCP_PORT_HTTP, TCP_Port_Open, Webserver_ApplicationCallback); +} + +/** Indicates if a given request equals the given HTTP command. + * + * \param[in] RequestHeader HTTP request made by the host + * \param[in] Command HTTP command to compare the request to + * + * \return Boolean true if the command matches the request, false otherwise + */ +static bool IsHTTPCommand(uint8_t* RequestHeader, char* Command) +{ + /* Returns true if the non null terminated string in RequestHeader matches the null terminated string Command */ + return (strncmp((char*)RequestHeader, Command, strlen(Command)) == 0); +} + +/** Application callback routine, executed each time the TCP processing task runs. This callback determines what request + * has been made (if any), and serves up appropriate responses. + * + * \param[in] ConnectionState Pointer to a TCP Connection State structure giving connection information + * \param[in,out] Buffer Pointer to the application's send/receive packet buffer + */ +void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer) +{ + char* BufferDataStr = (char*)Buffer->Data; + static uint8_t PageBlock = 0; + + /* Check to see if a packet has been received on the HTTP port from a remote host */ + if (TCP_APP_HAS_RECEIVED_PACKET(Buffer)) + { + if (IsHTTPCommand(Buffer->Data, "GET")) + { + if (IsHTTPCommand(Buffer->Data, "GET / ")) + { + PageBlock = 0; + + /* Copy the HTTP 200 response header into the packet buffer */ + strcpy_P(BufferDataStr, HTTP200Header); + + /* Send the buffer contents to the host */ + TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); + + /* Lock the buffer to Device->Host transmissions only while we send the page contents */ + TCP_APP_CAPTURE_BUFFER(Buffer); + } + else + { + /* Copy the HTTP 404 response header into the packet buffer */ + strcpy_P(BufferDataStr, HTTP404Header); + + /* Send the buffer contents to the host */ + TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); + + /* All data sent, close the connection */ + TCP_APP_CLOSECONNECTION(ConnectionState); + } + } + else if (IsHTTPCommand(Buffer->Data, "HEAD")) + { + if (IsHTTPCommand(Buffer->Data, "HEAD / ")) + { + /* Copy the HTTP response header into the packet buffer */ + strcpy_P(BufferDataStr, HTTP200Header); + + /* Send the buffer contents to the host */ + TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); + } + else + { + /* Copy the HTTP response header into the packet buffer */ + strcpy_P(BufferDataStr, HTTP404Header); + + /* Send the buffer contents to the host */ + TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); + } + + /* All data sent, close the connection */ + TCP_APP_CLOSECONNECTION(ConnectionState); + } + else if (IsHTTPCommand(Buffer->Data, "TRACE")) + { + /* Echo the host's query back to the host */ + TCP_APP_SEND_BUFFER(Buffer, Buffer->Length); + + /* All data sent, close the connection */ + TCP_APP_CLOSECONNECTION(ConnectionState); + } + else + { + /* Unknown request, just clear the buffer (drop the packet) */ + TCP_APP_CLEAR_BUFFER(Buffer); + } + } + else if (TCP_APP_HAVE_CAPTURED_BUFFER(Buffer)) + { + uint16_t RemLength = strlen_P(&HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE]); + uint16_t Length; + + /* Determine the length of the loaded block */ + Length = ((RemLength > HTTP_REPLY_BLOCK_SIZE) ? HTTP_REPLY_BLOCK_SIZE : RemLength); + + /* Copy the next buffer sized block of the page to the packet buffer */ + strncpy_P(BufferDataStr, &HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE], Length); + + /* Send the buffer contents to the host */ + TCP_APP_SEND_BUFFER(Buffer, Length); + + /* Check to see if the entire page has been sent */ + if (PageBlock++ == (sizeof(HTTPPage) / HTTP_REPLY_BLOCK_SIZE)) + { + /* Unlock the buffer so that the host can fill it with future packets */ + TCP_APP_RELEASE_BUFFER(Buffer); + + /* Close the connection to the host */ + TCP_APP_CLOSECONNECTION(ConnectionState); + } + } +} diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.h index be96f7f34..3ba4186ea 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.h +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.h @@ -1,55 +1,55 @@ -/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 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 disclaim 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 Webserver.c.
- */
-
-#ifndef _WEBSERVER_H_
-#define _WEBSERVER_H_
-
- /* Includes: */
- #include <avr/io.h>
- #include <avr/pgmspace.h>
-
- #include <LUFA/Version.h>
-
- #include "TCP.h"
-
- /* Macros: */
- /** Maximum size of a HTTP response per transmission */
- #define HTTP_REPLY_BLOCK_SIZE 128
-
- /* Function Prototypes: */
- void Webserver_Init(void);
- void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer);
-
-#endif
+/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 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 disclaim 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 Webserver.c. + */ + +#ifndef _WEBSERVER_H_ +#define _WEBSERVER_H_ + + /* Includes: */ + #include <avr/io.h> + #include <avr/pgmspace.h> + + #include <LUFA/Version.h> + + #include "TCP.h" + + /* Macros: */ + /** Maximum size of a HTTP response per transmission */ + #define HTTP_REPLY_BLOCK_SIZE 128 + + /* Function Prototypes: */ + void Webserver_Init(void); + void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer); + +#endif |