3      Copyright (C) Dean Camera, 2011. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2011  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 disclaim 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 header 
  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")); 
  64         printf_P(PSTR("  + Frame Size: %u\r\n"), FrameIN
.FrameLength
); 
  66         if (!(MAC_COMPARE(&FrameHeader
->Destination
, &ServerMACAddress
)) && 
  67             !(MAC_COMPARE(&FrameHeader
->Destination
, &BroadcastMACAddress
))) 
  69                 printf_P(PSTR("  + NOT ADDRESSED TO DEVICE\r\n")); 
  73         printf_P(PSTR("  + MAC Source : %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader
->Source
.Octets
[0], 
  74                                                                              FrameHeader
->Source
.Octets
[1], 
  75                                                                              FrameHeader
->Source
.Octets
[2], 
  76                                                                              FrameHeader
->Source
.Octets
[3], 
  77                                                                              FrameHeader
->Source
.Octets
[4], 
  78                                                                              FrameHeader
->Source
.Octets
[5]); 
  80         printf_P(PSTR("  + MAC Dest: %02X:%02X:%02X:%02X:%02X:%02X\r\n"),    FrameHeader
->Destination
.Octets
[0], 
  81                                                                              FrameHeader
->Destination
.Octets
[1], 
  82                                                                              FrameHeader
->Destination
.Octets
[2], 
  83                                                                              FrameHeader
->Destination
.Octets
[3], 
  84                                                                              FrameHeader
->Destination
.Octets
[4], 
  85                                                                              FrameHeader
->Destination
.Octets
[5]); 
  87         printf_P(PSTR("  + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader
->EtherType
)); 
  91 /** Decodes an ARP header and prints its contents to through the USART in a human readable format. 
  93  *  \param[in] InDataStart  Pointer to the start of an ARP packet header 
  95 void DecodeARPHeader(void* InDataStart
) 
  97         #if !defined(NO_DECODE_ARP) 
  98         ARP_Header_t
* ARPHeader 
= (ARP_Header_t
*)InDataStart
; 
 100         printf_P(PSTR("   \\\r\n    ARP\r\n")); 
 102         if (!(IP_COMPARE(&ARPHeader
->TPA
, &ServerIPAddress
)) && 
 103             !(MAC_COMPARE(&ARPHeader
->THA
, &ServerMACAddress
))) 
 105                 printf_P(PSTR("    + NOT ADDRESSED TO DEVICE\r\n")); 
 109         printf_P(PSTR("    + Protocol: %x\r\n"), SwapEndian_16(ARPHeader
->ProtocolType
)); 
 110         printf_P(PSTR("    + Operation: %u\r\n"), SwapEndian_16(ARPHeader
->Operation
)); 
 112         if (SwapEndian_16(ARPHeader
->ProtocolType
) == ETHERTYPE_IPV4
) 
 114                 printf_P(PSTR("    + SHA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader
->SHA
.Octets
[0], 
 115                                                                                    ARPHeader
->SHA
.Octets
[1], 
 116                                                                                    ARPHeader
->SHA
.Octets
[2], 
 117                                                                                    ARPHeader
->SHA
.Octets
[3], 
 118                                                                                    ARPHeader
->SHA
.Octets
[4], 
 119                                                                                    ARPHeader
->SHA
.Octets
[5]); 
 121                 printf_P(PSTR("    + SPA IP: %u.%u.%u.%u\r\n"), ARPHeader
->SPA
.Octets
[0], 
 122                                                                 ARPHeader
->SPA
.Octets
[1], 
 123                                                                 ARPHeader
->SPA
.Octets
[2], 
 124                                                                 ARPHeader
->SPA
.Octets
[3]); 
 126                 printf_P(PSTR("    + THA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader
->THA
.Octets
[0], 
 127                                                                                    ARPHeader
->THA
.Octets
[1], 
 128                                                                                    ARPHeader
->THA
.Octets
[2], 
 129                                                                                    ARPHeader
->THA
.Octets
[3], 
 130                                                                                    ARPHeader
->THA
.Octets
[4], 
 131                                                                                    ARPHeader
->THA
.Octets
[5]); 
 133                 printf_P(PSTR("    + TPA IP: %u.%u.%u.%u\r\n"), ARPHeader
->TPA
.Octets
[0], 
 134                                                                 ARPHeader
->TPA
.Octets
[1], 
 135                                                                 ARPHeader
->TPA
.Octets
[2], 
 136                                                                 ARPHeader
->TPA
.Octets
[3]); 
 141 /** Decodes an IP header and prints its contents to through the USART in a human readable format. 
 143  *  \param[in] InDataStart  Pointer to the start of an IP packet header 
 145 void DecodeIPHeader(void* InDataStart
) 
 147         #if !defined(NO_DECODE_IP) 
 148         IP_Header_t
* IPHeader  
= (IP_Header_t
*)InDataStart
; 
 150         uint16_t HeaderLengthBytes 
= (IPHeader
->HeaderLength 
* sizeof(uint32_t)); 
 152         printf_P(PSTR("   \\\r\n    IP\r\n")); 
 154         if (!(IP_COMPARE(&IPHeader
->DestinationAddress
, &ServerIPAddress
))) 
 156                 printf_P(PSTR("    + NOT ADDRESSED TO DEVICE\r\n")); 
 160         printf_P(PSTR("    + Header Length: %u Bytes\r\n"), HeaderLengthBytes
); 
 161         printf_P(PSTR("    + Packet Version: %u\r\n"), IPHeader
->Version
); 
 162         printf_P(PSTR("    + Total Length: %u\r\n"), SwapEndian_16(IPHeader
->TotalLength
)); 
 164         printf_P(PSTR("    + Protocol: %u\r\n"), IPHeader
->Protocol
); 
 165         printf_P(PSTR("    + TTL: %u\r\n"), IPHeader
->TTL
); 
 167         printf_P(PSTR("    + IP Src: %u.%u.%u.%u\r\n"), IPHeader
->SourceAddress
.Octets
[0], 
 168                                                         IPHeader
->SourceAddress
.Octets
[1], 
 169                                                         IPHeader
->SourceAddress
.Octets
[2], 
 170                                                         IPHeader
->SourceAddress
.Octets
[3]); 
 172         printf_P(PSTR("    + IP Dst: %u.%u.%u.%u\r\n"), IPHeader
->DestinationAddress
.Octets
[0], 
 173                                                         IPHeader
->DestinationAddress
.Octets
[1], 
 174                                                         IPHeader
->DestinationAddress
.Octets
[2], 
 175                                                         IPHeader
->DestinationAddress
.Octets
[3]); 
 179 /** Decodes an ICMP header and prints its contents to through the USART in a human readable format. 
 181  *  \param[in] InDataStart  Pointer to the start of an ICMP packet header 
 183 void DecodeICMPHeader(void* InDataStart
) 
 185         #if !defined(NO_DECODE_ICMP) 
 186         ICMP_Header_t
* ICMPHeader  
= (ICMP_Header_t
*)InDataStart
; 
 188         printf_P(PSTR("    \\\r\n     ICMP\r\n")); 
 190         printf_P(PSTR("     + Type: %u\r\n"), ICMPHeader
->Type
); 
 191         printf_P(PSTR("     + Code: %u\r\n"), ICMPHeader
->Code
); 
 195 /** Decodes a TCP header and prints its contents to through the USART in a human readable format. 
 197  *  \param[in] InDataStart  Pointer to the start of a TCP packet header 
 199 void DecodeTCPHeader(void* InDataStart
) 
 201         #if !defined(NO_DECODE_TCP) 
 202         TCP_Header_t
* TCPHeader  
= (TCP_Header_t
*)InDataStart
; 
 204         uint16_t               HeaderLengthBytes 
= (TCPHeader
->DataOffset 
* sizeof(uint32_t)); 
 206         printf_P(PSTR("    \\\r\n     TCP\r\n")); 
 208         printf_P(PSTR("     + Header Length: %u Bytes\r\n"), HeaderLengthBytes
); 
 210         printf_P(PSTR("     + Source Port: %u\r\n"), SwapEndian_16(TCPHeader
->SourcePort
)); 
 211         printf_P(PSTR("     + Destination Port: %u\r\n"), SwapEndian_16(TCPHeader
->DestinationPort
)); 
 213         printf_P(PSTR("     + Sequence Number: %lu\r\n"), SwapEndian_32(TCPHeader
->SequenceNumber
)); 
 214         printf_P(PSTR("     + Acknowledgment Number: %lu\r\n"), SwapEndian_32(TCPHeader
->AcknowledgmentNumber
)); 
 216         printf_P(PSTR("     + Flags: 0x%02X\r\n"), TCPHeader
->Flags
); 
 218         if (TCP_GetPortState(TCPHeader
->DestinationPort
) == TCP_Port_Closed
) 
 219           printf_P(PSTR("     + NOT LISTENING ON DESTINATION PORT\r\n")); 
 223 /** Decodes an UDP header and prints its contents to through the USART in a human readable format. 
 225  *  \param[in] InDataStart  Pointer to the start of a UDP packet header 
 227 void DecodeUDPHeader(void* InDataStart
) 
 229         #if !defined(NO_DECODE_UDP) 
 230         UDP_Header_t
* UDPHeader 
= (UDP_Header_t
*)InDataStart
; 
 232         printf_P(PSTR("    \\\r\n     UDP\r\n")); 
 234         printf_P(PSTR("     + Source Port: %u\r\n"), SwapEndian_16(UDPHeader
->SourcePort
)); 
 235         printf_P(PSTR("     + Destination Port: %u\r\n"), SwapEndian_16(UDPHeader
->DestinationPort
)); 
 237         printf_P(PSTR("     + Data Length: %d\r\n"), SwapEndian_16(UDPHeader
->Length
)); 
 241 /** Decodes an DHCP header and prints its contents to through the USART in a human readable format. 
 243  *  \param[in] InDataStart  Pointer to the start of a DHCP packet header 
 245 void DecodeDHCPHeader(void* InDataStart
) 
 247         #if !defined(NO_DECODE_DHCP) 
 248         uint8_t* DHCPOptions 
= (InDataStart 
+ sizeof(DHCP_Header_t
)); 
 250         printf_P(PSTR("     \\\r\n      DHCP\r\n")); 
 252         while (DHCPOptions
[0] != DHCP_OPTION_END
) 
 254                 if (DHCPOptions
[0] == DHCP_OPTION_MESSAGETYPE
) 
 256                         switch (DHCPOptions
[2]) 
 258                                 case DHCP_MESSAGETYPE_DISCOVER
: 
 259                                         printf_P(PSTR("      + DISCOVER\r\n")); 
 261                                 case DHCP_MESSAGETYPE_REQUEST
: 
 262                                         printf_P(PSTR("      + REQUEST\r\n")); 
 264                                 case DHCP_MESSAGETYPE_RELEASE
: 
 265                                         printf_P(PSTR("      + RELEASE\r\n")); 
 267                                 case DHCP_MESSAGETYPE_DECLINE
: 
 268                                         printf_P(PSTR("      + DECLINE\r\n")); 
 273                 DHCPOptions 
+= ((DHCPOptions
[0] == DHCP_OPTION_PAD
) ? 
1 : (DHCPOptions
[1] + 2));