3      Copyright (C) Dean Camera, 2013. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, distribute, and sell this 
  13   software and its documentation for any purpose is hereby granted 
  14   without fee, provided that the above copyright notice appear in 
  15   all copies and that both that the copyright notice and this 
  16   permission notice and warranty disclaimer appear in supporting 
  17   documentation, and that the name of the author not be used in 
  18   advertising or publicity pertaining to distribution of the 
  19   software without specific, written prior permission. 
  21   The author disclaims all warranties with regard to this 
  22   software, including all implied warranties of merchantability 
  23   and fitness.  In no event shall the author be liable for any 
  24   special, indirect or consequential damages or any damages 
  25   whatsoever resulting from loss of use, data or profits, whether 
  26   in an action of contract, negligence or other tortious action, 
  27   arising out of or in connection with the use or performance of 
  31 /* Protocol decoders for Ethernet, TCP, IP, ICMP and ARP. Each of these routines 
  32    accepts a header to the appropriate protocol and prints out pertinent information 
  33    on the packet through the serial port. 
  35    To disable printing of a specific protocol, define the token NO_DECODE_{Protocol} 
  36    in the project makefile, and pass it to the compiler using the -D switch. 
  41  *  Protocol decoding routines, for the plain-text decoding of Ethernet frames for debugging purposes. 
  42  *  Enabled protocol decoders will print incoming Ethernet frame contents through the USART in a human 
  45  *  Note that the USART is a slow transmission medium, and will slow down packet processing considerably. 
  46  *  Packet decoding routines can be disabled by defining NO_DECODE_{Protocol Name} in the project makefile 
  47  *  and passing it to the compiler via the -D switch. 
  50 #include "ProtocolDecoders.h" 
  52 /** Decodes an Ethernet frame header and prints its contents to through the USART in a human readable format. 
  54  *  \param[in] InDataStart  Pointer to the start of an Ethernet frame of data 
  56 void DecodeEthernetFrameHeader(void* InDataStart
) 
  58         #if !defined(NO_DECODE_ETHERNET) 
  59         Ethernet_Frame_Header_t
* FrameHeader 
= (Ethernet_Frame_Header_t
*)InDataStart
; 
  61         printf_P(PSTR("\r\n")); 
  63         printf_P(PSTR("  ETHERNET\r\n")); 
  65         if (!(MAC_COMPARE(&FrameHeader
->Destination
, &ServerMACAddress
)) && 
  66             !(MAC_COMPARE(&FrameHeader
->Destination
, &BroadcastMACAddress
))) 
  68                 printf_P(PSTR("  + NOT ADDRESSED TO DEVICE\r\n")); 
  72         printf_P(PSTR("  + MAC Source : %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader
->Source
.Octets
[0], 
  73                                                                              FrameHeader
->Source
.Octets
[1], 
  74                                                                              FrameHeader
->Source
.Octets
[2], 
  75                                                                              FrameHeader
->Source
.Octets
[3], 
  76                                                                              FrameHeader
->Source
.Octets
[4], 
  77                                                                              FrameHeader
->Source
.Octets
[5]); 
  79         printf_P(PSTR("  + MAC Dest: %02X:%02X:%02X:%02X:%02X:%02X\r\n"),    FrameHeader
->Destination
.Octets
[0], 
  80                                                                              FrameHeader
->Destination
.Octets
[1], 
  81                                                                              FrameHeader
->Destination
.Octets
[2], 
  82                                                                              FrameHeader
->Destination
.Octets
[3], 
  83                                                                              FrameHeader
->Destination
.Octets
[4], 
  84                                                                              FrameHeader
->Destination
.Octets
[5]); 
  86         printf_P(PSTR("  + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader
->EtherType
)); 
  90 /** Decodes an ARP header and prints its contents to through the USART in a human readable format. 
  92  *  \param[in] InDataStart  Pointer to the start of an ARP packet header 
  94 void DecodeARPHeader(void* InDataStart
) 
  96         #if !defined(NO_DECODE_ARP) 
  97         ARP_Header_t
* ARPHeader 
= (ARP_Header_t
*)InDataStart
; 
  99         printf_P(PSTR("   \\\r\n    ARP\r\n")); 
 101         if (!(IP_COMPARE(&ARPHeader
->TPA
, &ServerIPAddress
)) && 
 102             !(MAC_COMPARE(&ARPHeader
->THA
, &ServerMACAddress
))) 
 104                 printf_P(PSTR("    + NOT ADDRESSED TO DEVICE\r\n")); 
 108         printf_P(PSTR("    + Protocol: %x\r\n"), SwapEndian_16(ARPHeader
->ProtocolType
)); 
 109         printf_P(PSTR("    + Operation: %u\r\n"), SwapEndian_16(ARPHeader
->Operation
)); 
 111         if (SwapEndian_16(ARPHeader
->ProtocolType
) == ETHERTYPE_IPV4
) 
 113                 printf_P(PSTR("    + SHA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader
->SHA
.Octets
[0], 
 114                                                                                    ARPHeader
->SHA
.Octets
[1], 
 115                                                                                    ARPHeader
->SHA
.Octets
[2], 
 116                                                                                    ARPHeader
->SHA
.Octets
[3], 
 117                                                                                    ARPHeader
->SHA
.Octets
[4], 
 118                                                                                    ARPHeader
->SHA
.Octets
[5]); 
 120                 printf_P(PSTR("    + SPA IP: %u.%u.%u.%u\r\n"), ARPHeader
->SPA
.Octets
[0], 
 121                                                                 ARPHeader
->SPA
.Octets
[1], 
 122                                                                 ARPHeader
->SPA
.Octets
[2], 
 123                                                                 ARPHeader
->SPA
.Octets
[3]); 
 125                 printf_P(PSTR("    + THA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader
->THA
.Octets
[0], 
 126                                                                                    ARPHeader
->THA
.Octets
[1], 
 127                                                                                    ARPHeader
->THA
.Octets
[2], 
 128                                                                                    ARPHeader
->THA
.Octets
[3], 
 129                                                                                    ARPHeader
->THA
.Octets
[4], 
 130                                                                                    ARPHeader
->THA
.Octets
[5]); 
 132                 printf_P(PSTR("    + TPA IP: %u.%u.%u.%u\r\n"), ARPHeader
->TPA
.Octets
[0], 
 133                                                                 ARPHeader
->TPA
.Octets
[1], 
 134                                                                 ARPHeader
->TPA
.Octets
[2], 
 135                                                                 ARPHeader
->TPA
.Octets
[3]); 
 140 /** Decodes an IP header and prints its contents to through the USART in a human readable format. 
 142  *  \param[in] InDataStart  Pointer to the start of an IP packet header 
 144 void DecodeIPHeader(void* InDataStart
) 
 146         #if !defined(NO_DECODE_IP) 
 147         IP_Header_t
* IPHeader  
= (IP_Header_t
*)InDataStart
; 
 149         uint16_t HeaderLengthBytes 
= (IPHeader
->HeaderLength 
* sizeof(uint32_t)); 
 151         printf_P(PSTR("   \\\r\n    IP\r\n")); 
 153         if (!(IP_COMPARE(&IPHeader
->DestinationAddress
, &ServerIPAddress
))) 
 155                 printf_P(PSTR("    + NOT ADDRESSED TO DEVICE\r\n")); 
 159         printf_P(PSTR("    + Header Length: %u Bytes\r\n"), HeaderLengthBytes
); 
 160         printf_P(PSTR("    + Packet Version: %u\r\n"), IPHeader
->Version
); 
 161         printf_P(PSTR("    + Total Length: %u\r\n"), SwapEndian_16(IPHeader
->TotalLength
)); 
 163         printf_P(PSTR("    + Protocol: %u\r\n"), IPHeader
->Protocol
); 
 164         printf_P(PSTR("    + TTL: %u\r\n"), IPHeader
->TTL
); 
 166         printf_P(PSTR("    + IP Src: %u.%u.%u.%u\r\n"), IPHeader
->SourceAddress
.Octets
[0], 
 167                                                         IPHeader
->SourceAddress
.Octets
[1], 
 168                                                         IPHeader
->SourceAddress
.Octets
[2], 
 169                                                         IPHeader
->SourceAddress
.Octets
[3]); 
 171         printf_P(PSTR("    + IP Dst: %u.%u.%u.%u\r\n"), IPHeader
->DestinationAddress
.Octets
[0], 
 172                                                         IPHeader
->DestinationAddress
.Octets
[1], 
 173                                                         IPHeader
->DestinationAddress
.Octets
[2], 
 174                                                         IPHeader
->DestinationAddress
.Octets
[3]); 
 178 /** Decodes an ICMP header and prints its contents to through the USART in a human readable format. 
 180  *  \param[in] InDataStart  Pointer to the start of an ICMP packet header 
 182 void DecodeICMPHeader(void* InDataStart
) 
 184         #if !defined(NO_DECODE_ICMP) 
 185         ICMP_Header_t
* ICMPHeader  
= (ICMP_Header_t
*)InDataStart
; 
 187         printf_P(PSTR("    \\\r\n     ICMP\r\n")); 
 189         printf_P(PSTR("     + Type: %u\r\n"), ICMPHeader
->Type
); 
 190         printf_P(PSTR("     + Code: %u\r\n"), ICMPHeader
->Code
); 
 194 /** Decodes a TCP header and prints its contents to through the USART in a human readable format. 
 196  *  \param[in] InDataStart  Pointer to the start of a TCP packet header 
 198 void DecodeTCPHeader(void* InDataStart
) 
 200         #if !defined(NO_DECODE_TCP) 
 201         TCP_Header_t
* TCPHeader  
= (TCP_Header_t
*)InDataStart
; 
 203         uint16_t               HeaderLengthBytes 
= (TCPHeader
->DataOffset 
* sizeof(uint32_t)); 
 205         printf_P(PSTR("    \\\r\n     TCP\r\n")); 
 207         printf_P(PSTR("     + Header Length: %u Bytes\r\n"), HeaderLengthBytes
); 
 209         printf_P(PSTR("     + Source Port: %u\r\n"), SwapEndian_16(TCPHeader
->SourcePort
)); 
 210         printf_P(PSTR("     + Destination Port: %u\r\n"), SwapEndian_16(TCPHeader
->DestinationPort
)); 
 212         printf_P(PSTR("     + Sequence Number: %lu\r\n"), SwapEndian_32(TCPHeader
->SequenceNumber
)); 
 213         printf_P(PSTR("     + Acknowledgment Number: %lu\r\n"), SwapEndian_32(TCPHeader
->AcknowledgmentNumber
)); 
 215         printf_P(PSTR("     + Flags: 0x%02X\r\n"), TCPHeader
->Flags
); 
 217         if (TCP_GetPortState(TCPHeader
->DestinationPort
) == TCP_Port_Closed
) 
 218           printf_P(PSTR("     + NOT LISTENING ON DESTINATION PORT\r\n")); 
 222 /** Decodes an UDP header and prints its contents to through the USART in a human readable format. 
 224  *  \param[in] InDataStart  Pointer to the start of a UDP packet header 
 226 void DecodeUDPHeader(void* InDataStart
) 
 228         #if !defined(NO_DECODE_UDP) 
 229         UDP_Header_t
* UDPHeader 
= (UDP_Header_t
*)InDataStart
; 
 231         printf_P(PSTR("    \\\r\n     UDP\r\n")); 
 233         printf_P(PSTR("     + Source Port: %u\r\n"), SwapEndian_16(UDPHeader
->SourcePort
)); 
 234         printf_P(PSTR("     + Destination Port: %u\r\n"), SwapEndian_16(UDPHeader
->DestinationPort
)); 
 236         printf_P(PSTR("     + Data Length: %d\r\n"), SwapEndian_16(UDPHeader
->Length
)); 
 240 /** Decodes an DHCP header and prints its contents to through the USART in a human readable format. 
 242  *  \param[in] InDataStart  Pointer to the start of a DHCP packet header 
 244 void DecodeDHCPHeader(void* InDataStart
) 
 246         #if !defined(NO_DECODE_DHCP) 
 247         uint8_t* DHCPOptions 
= (InDataStart 
+ sizeof(DHCP_Header_t
)); 
 249         printf_P(PSTR("     \\\r\n      DHCP\r\n")); 
 251         while (DHCPOptions
[0] != DHCP_OPTION_END
) 
 253                 if (DHCPOptions
[0] == DHCP_OPTION_MESSAGETYPE
) 
 255                         switch (DHCPOptions
[2]) 
 257                                 case DHCP_MESSAGETYPE_DISCOVER
: 
 258                                         printf_P(PSTR("      + DISCOVER\r\n")); 
 260                                 case DHCP_MESSAGETYPE_REQUEST
: 
 261                                         printf_P(PSTR("      + REQUEST\r\n")); 
 263                                 case DHCP_MESSAGETYPE_RELEASE
: 
 264                                         printf_P(PSTR("      + RELEASE\r\n")); 
 266                                 case DHCP_MESSAGETYPE_DECLINE
: 
 267                                         printf_P(PSTR("      + DECLINE\r\n")); 
 272                 DHCPOptions 
+= ((DHCPOptions
[0] == DHCP_OPTION_PAD
) ? 
1 : (DHCPOptions
[1] + 2));