--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/* Protocol decoders for Ethernet, TCP, IP, ICMP and ARP. Each of these routines\r
+ accepts a header to the appropriate protocol and prints out pertinent information\r
+ on the packet through the serial port.\r
+ \r
+ To disable printing of a specific protocol, define the token NO_DECODE_{Protocol}\r
+ in the project makefile, and pass it to the compiler using the -D switch.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Protocol decoding routines, for the plain-text decoding of Ethernet frames for debugging purposes.\r
+ * Enabled protocol decoders will print incoming Ethernet frame contents through the USART in a human\r
+ * readable format.\r
+ *\r
+ * Note that the USART is a slow transmission medium, and will slow down packet processing considerably.\r
+ * Packet decoding routines can be disabled by defining NO_DECODE_{Protocol Name} in the project makefile\r
+ * and passing it to the compiler via the -D switch.\r
+ */\r
+ \r
+#include "ProtocolDecoders.h"\r
+\r
+/** Decodes an Ethernet frame header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of an Ethernet frame header\r
+ */\r
+void DecodeEthernetFrameHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_ETHERNET)\r
+ Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)InDataStart;\r
+ \r
+ printf_P(PSTR("\r\n"));\r
+ \r
+ printf_P(PSTR(" ETHERNET\r\n"));\r
+ printf_P(PSTR(" + Frame Size: %u\r\n"), FrameIN.FrameLength);\r
+\r
+ if (!(MAC_COMPARE(&FrameHeader->Destination, &ServerMACAddress)) &&\r
+ !(MAC_COMPARE(&FrameHeader->Destination, &BroadcastMACAddress)))\r
+ {\r
+ printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n"));\r
+ return;\r
+ }\r
+\r
+ printf_P(PSTR(" + MAC Source : %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Source.Octets[0],\r
+ FrameHeader->Source.Octets[1],\r
+ FrameHeader->Source.Octets[2],\r
+ FrameHeader->Source.Octets[3],\r
+ FrameHeader->Source.Octets[4],\r
+ FrameHeader->Source.Octets[5]);\r
+\r
+ printf_P(PSTR(" + MAC Dest: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Destination.Octets[0],\r
+ FrameHeader->Destination.Octets[1],\r
+ FrameHeader->Destination.Octets[2],\r
+ FrameHeader->Destination.Octets[3],\r
+ FrameHeader->Destination.Octets[4],\r
+ FrameHeader->Destination.Octets[5]);\r
+\r
+ if (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE)\r
+ printf_P(PSTR(" + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType));\r
+ else\r
+ printf_P(PSTR(" + Protocol: UNKNOWN E1\r\n"));\r
+ #endif\r
+}\r
+\r
+/** Decodes an ARP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of an ARP packet header\r
+ */\r
+void DecodeARPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_ARP)\r
+ ARP_Header_t* ARPHeader = (ARP_Header_t*)InDataStart; \r
+\r
+ printf_P(PSTR(" \\\r\n ARP\r\n"));\r
+\r
+ if (!(IP_COMPARE(&ARPHeader->TPA, &ServerIPAddress)) &&\r
+ !(MAC_COMPARE(&ARPHeader->THA, &ServerMACAddress)))\r
+ {\r
+ printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n"));\r
+ return; \r
+ }\r
+\r
+ printf_P(PSTR(" + Protocol: %x\r\n"), SwapEndian_16(ARPHeader->ProtocolType));\r
+ printf_P(PSTR(" + Operation: %u\r\n"), SwapEndian_16(ARPHeader->Operation));\r
+ \r
+ if (SwapEndian_16(ARPHeader->ProtocolType) == ETHERTYPE_IPV4)\r
+ {\r
+ printf_P(PSTR(" + SHA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->SHA.Octets[0],\r
+ ARPHeader->SHA.Octets[1],\r
+ ARPHeader->SHA.Octets[2],\r
+ ARPHeader->SHA.Octets[3],\r
+ ARPHeader->SHA.Octets[4],\r
+ ARPHeader->SHA.Octets[5]);\r
+\r
+ printf_P(PSTR(" + SPA IP: %u.%u.%u.%u\r\n"), ARPHeader->SPA.Octets[0],\r
+ ARPHeader->SPA.Octets[1],\r
+ ARPHeader->SPA.Octets[2],\r
+ ARPHeader->SPA.Octets[3]);\r
+\r
+ printf_P(PSTR(" + THA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->THA.Octets[0],\r
+ ARPHeader->THA.Octets[1],\r
+ ARPHeader->THA.Octets[2],\r
+ ARPHeader->THA.Octets[3],\r
+ ARPHeader->THA.Octets[4],\r
+ ARPHeader->THA.Octets[5]);\r
+\r
+ printf_P(PSTR(" + TPA IP: %u.%u.%u.%u\r\n"), ARPHeader->TPA.Octets[0],\r
+ ARPHeader->TPA.Octets[1],\r
+ ARPHeader->TPA.Octets[2],\r
+ ARPHeader->TPA.Octets[3]);\r
+ }\r
+ #endif\r
+}\r
+\r
+/** Decodes an IP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of an IP packet header\r
+ */\r
+void DecodeIPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_IP)\r
+ IP_Header_t* IPHeader = (IP_Header_t*)InDataStart;\r
+\r
+ uint16_t HeaderLengthBytes = (IPHeader->HeaderLength * sizeof(uint32_t));\r
+\r
+ printf_P(PSTR(" \\\r\n IP\r\n"));\r
+\r
+ if (!(IP_COMPARE(&IPHeader->DestinationAddress, &ServerIPAddress)))\r
+ {\r
+ printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n"));\r
+ return;\r
+ }\r
+\r
+ printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes);\r
+ printf_P(PSTR(" + Packet Version: %u\r\n"), IPHeader->Version);\r
+ printf_P(PSTR(" + Total Length: %u\r\n"), SwapEndian_16(IPHeader->TotalLength));\r
+ \r
+ printf_P(PSTR(" + Protocol: %u\r\n"), IPHeader->Protocol);\r
+ printf_P(PSTR(" + TTL: %u\r\n"), IPHeader->TTL);\r
+ \r
+ printf_P(PSTR(" + IP Src: %u.%u.%u.%u\r\n"), IPHeader->SourceAddress.Octets[0],\r
+ IPHeader->SourceAddress.Octets[1],\r
+ IPHeader->SourceAddress.Octets[2],\r
+ IPHeader->SourceAddress.Octets[3]); \r
+\r
+ printf_P(PSTR(" + IP Dst: %u.%u.%u.%u\r\n"), IPHeader->DestinationAddress.Octets[0],\r
+ IPHeader->DestinationAddress.Octets[1],\r
+ IPHeader->DestinationAddress.Octets[2],\r
+ IPHeader->DestinationAddress.Octets[3]);\r
+ #endif\r
+}\r
+\r
+/** Decodes an ICMP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of an ICMP packet header\r
+ */\r
+void DecodeICMPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_ICMP)\r
+ ICMP_Header_t* ICMPHeader = (ICMP_Header_t*)InDataStart;\r
+\r
+ printf_P(PSTR(" \\\r\n ICMP\r\n"));\r
+\r
+ printf_P(PSTR(" + Type: %u\r\n"), ICMPHeader->Type);\r
+ printf_P(PSTR(" + Code: %u\r\n"), ICMPHeader->Code);\r
+ #endif\r
+}\r
+\r
+/** Decodes a TCP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of a TCP packet header\r
+ */\r
+void DecodeTCPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_TCP)\r
+ TCP_Header_t* TCPHeader = (TCP_Header_t*)InDataStart;\r
+\r
+ uint16_t HeaderLengthBytes = (TCPHeader->DataOffset * sizeof(uint32_t));\r
+\r
+ printf_P(PSTR(" \\\r\n TCP\r\n"));\r
+\r
+ printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes);\r
+\r
+ printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(TCPHeader->SourcePort));\r
+ printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(TCPHeader->DestinationPort));\r
+\r
+ printf_P(PSTR(" + Sequence Number: %lu\r\n"), SwapEndian_32(TCPHeader->SequenceNumber));\r
+ printf_P(PSTR(" + Acknowledgment Number: %lu\r\n"), SwapEndian_32(TCPHeader->AcknowledgmentNumber));\r
+ \r
+ printf_P(PSTR(" + Flags: 0x%02X\r\n"), TCPHeader->Flags);\r
+ \r
+ if (TCP_GetPortState(TCPHeader->DestinationPort) == TCP_Port_Closed)\r
+ printf_P(PSTR(" + NOT LISTENING ON DESTINATION PORT\r\n"));\r
+ #endif\r
+}\r
+\r
+/** Decodes an UDP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of a UDP packet header\r
+ */\r
+void DecodeUDPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_UDP)\r
+ UDP_Header_t* UDPHeader = (UDP_Header_t*)InDataStart;\r
+\r
+ printf_P(PSTR(" \\\r\n UDP\r\n"));\r
+\r
+ printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(UDPHeader->SourcePort));\r
+ printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(UDPHeader->DestinationPort));\r
+\r
+ printf_P(PSTR(" + Data Length: %d\r\n"), SwapEndian_16(UDPHeader->Length));\r
+ #endif\r
+}\r
+\r
+/** Decodes an DHCP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of a DHCP packet header\r
+ */\r
+void DecodeDHCPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_DHCP)\r
+ uint8_t* DHCPOptions = (InDataStart + sizeof(DHCP_Header_t));\r
+\r
+ printf_P(PSTR(" \\\r\n DHCP\r\n"));\r
+\r
+ while (DHCPOptions[0] != DHCP_OPTION_END)\r
+ {\r
+ if (DHCPOptions[0] == DHCP_OPTION_MESSAGETYPE)\r
+ {\r
+ switch (DHCPOptions[2])\r
+ {\r
+ case DHCP_MESSAGETYPE_DISCOVER:\r
+ printf_P(PSTR(" + DISCOVER\r\n"));\r
+ break;\r
+ case DHCP_MESSAGETYPE_REQUEST:\r
+ printf_P(PSTR(" + REQUEST\r\n"));\r
+ break;\r
+ case DHCP_MESSAGETYPE_RELEASE:\r
+ printf_P(PSTR(" + RELEASE\r\n"));\r
+ break;\r
+ case DHCP_MESSAGETYPE_DECLINE:\r
+ printf_P(PSTR(" + DECLINE\r\n"));\r
+ break;\r
+ }\r
+ }\r
+ \r
+ DHCPOptions += ((DHCPOptions[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptions[1] + 2));\r
+ }\r
+\r
+ #endif\r
+}\r