3      Copyright (C) Dean Camera, 2009. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, and distribute this software 
  13   and its documentation for any purpose and without fee is hereby 
  14   granted, provided that the above copyright notice appear in all 
  15   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] FrameINData  Pointer to the start of an Ethernet frame information structure 
  56 void DecodeEthernetFrameHeader(Ethernet_Frame_Info_t
* FrameINData
) 
  58         #if !defined(NO_DECODE_ETHERNET) 
  59         Ethernet_Frame_Header_t
* FrameHeader 
= (Ethernet_Frame_Header_t
*)FrameINData
->FrameData
; 
  61         printf_P(PSTR("\r\n")); 
  63         printf_P(PSTR("  ETHERNET\r\n")); 
  64         printf_P(PSTR("  + Frame Size: %u\r\n"), FrameINData
->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         if (SwapEndian_16(FrameINData
->FrameLength
) > ETHERNET_VER2_MINSIZE
) 
  88           printf_P(PSTR("  + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader
->EtherType
)); 
  90           printf_P(PSTR("  + Protocol: UNKNOWN E1\r\n")); 
  94 /** Decodes an ARP header and prints its contents to through the USART in a human readable format. 
  96  *  \param[in] InDataStart  Pointer to the start of an ARP packet header 
  98 void DecodeARPHeader(void* InDataStart
) 
 100         #if !defined(NO_DECODE_ARP) 
 101         ARP_Header_t
* ARPHeader 
= (ARP_Header_t
*)InDataStart
;    
 103         printf_P(PSTR("   \\\r\n    ARP\r\n")); 
 105         if (!(IP_COMPARE(&ARPHeader
->TPA
, &ServerIPAddress
)) && 
 106             !(MAC_COMPARE(&ARPHeader
->THA
, &ServerMACAddress
))) 
 108                 printf_P(PSTR("    + NOT ADDRESSED TO DEVICE\r\n")); 
 112         printf_P(PSTR("    + Protocol: %x\r\n"), SwapEndian_16(ARPHeader
->ProtocolType
)); 
 113         printf_P(PSTR("    + Operation: %u\r\n"), SwapEndian_16(ARPHeader
->Operation
)); 
 115         if (SwapEndian_16(ARPHeader
->ProtocolType
) == ETHERTYPE_IPV4
) 
 117                 printf_P(PSTR("    + SHA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader
->SHA
.Octets
[0], 
 118                                                                                    ARPHeader
->SHA
.Octets
[1], 
 119                                                                                    ARPHeader
->SHA
.Octets
[2], 
 120                                                                                    ARPHeader
->SHA
.Octets
[3], 
 121                                                                                    ARPHeader
->SHA
.Octets
[4], 
 122                                                                                    ARPHeader
->SHA
.Octets
[5]); 
 124                 printf_P(PSTR("    + SPA IP: %u.%u.%u.%u\r\n"), ARPHeader
->SPA
.Octets
[0], 
 125                                                                 ARPHeader
->SPA
.Octets
[1], 
 126                                                                 ARPHeader
->SPA
.Octets
[2], 
 127                                                                 ARPHeader
->SPA
.Octets
[3]); 
 129                 printf_P(PSTR("    + THA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader
->THA
.Octets
[0], 
 130                                                                                    ARPHeader
->THA
.Octets
[1], 
 131                                                                                    ARPHeader
->THA
.Octets
[2], 
 132                                                                                    ARPHeader
->THA
.Octets
[3], 
 133                                                                                    ARPHeader
->THA
.Octets
[4], 
 134                                                                                    ARPHeader
->THA
.Octets
[5]); 
 136                 printf_P(PSTR("    + TPA IP: %u.%u.%u.%u\r\n"), ARPHeader
->TPA
.Octets
[0], 
 137                                                                 ARPHeader
->TPA
.Octets
[1], 
 138                                                                 ARPHeader
->TPA
.Octets
[2], 
 139                                                                 ARPHeader
->TPA
.Octets
[3]); 
 144 /** Decodes an IP header and prints its contents to through the USART in a human readable format. 
 146  *  \param[in] InDataStart  Pointer to the start of an IP packet header 
 148 void DecodeIPHeader(void* InDataStart
) 
 150         #if !defined(NO_DECODE_IP) 
 151         IP_Header_t
* IPHeader  
= (IP_Header_t
*)InDataStart
; 
 153         uint16_t HeaderLengthBytes 
= (IPHeader
->HeaderLength 
* sizeof(uint32_t)); 
 155         printf_P(PSTR("   \\\r\n    IP\r\n")); 
 157         if (!(IP_COMPARE(&IPHeader
->DestinationAddress
, &ServerIPAddress
))) 
 159                 printf_P(PSTR("    + NOT ADDRESSED TO DEVICE\r\n")); 
 163         printf_P(PSTR("    + Header Length: %u Bytes\r\n"), HeaderLengthBytes
); 
 164         printf_P(PSTR("    + Packet Version: %u\r\n"), IPHeader
->Version
); 
 165         printf_P(PSTR("    + Total Length: %u\r\n"), SwapEndian_16(IPHeader
->TotalLength
)); 
 167         printf_P(PSTR("    + Protocol: %u\r\n"), IPHeader
->Protocol
); 
 168         printf_P(PSTR("    + TTL: %u\r\n"), IPHeader
->TTL
); 
 170         printf_P(PSTR("    + IP Src: %u.%u.%u.%u\r\n"), IPHeader
->SourceAddress
.Octets
[0], 
 171                                                         IPHeader
->SourceAddress
.Octets
[1], 
 172                                                         IPHeader
->SourceAddress
.Octets
[2], 
 173                                                         IPHeader
->SourceAddress
.Octets
[3]);      
 175         printf_P(PSTR("    + IP Dst: %u.%u.%u.%u\r\n"), IPHeader
->DestinationAddress
.Octets
[0], 
 176                                                         IPHeader
->DestinationAddress
.Octets
[1], 
 177                                                         IPHeader
->DestinationAddress
.Octets
[2], 
 178                                                         IPHeader
->DestinationAddress
.Octets
[3]); 
 182 /** Decodes an ICMP header and prints its contents to through the USART in a human readable format. 
 184  *  \param[in] InDataStart  Pointer to the start of an ICMP packet header 
 186 void DecodeICMPHeader(void* InDataStart
) 
 188         #if !defined(NO_DECODE_ICMP) 
 189         ICMP_Header_t
* ICMPHeader  
= (ICMP_Header_t
*)InDataStart
; 
 191         printf_P(PSTR("    \\\r\n     ICMP\r\n")); 
 193         printf_P(PSTR("     + Type: %u\r\n"), ICMPHeader
->Type
); 
 194         printf_P(PSTR("     + Code: %u\r\n"), ICMPHeader
->Code
); 
 198 /** Decodes a TCP header and prints its contents to through the USART in a human readable format. 
 200  *  \param[in] InDataStart  Pointer to the start of a TCP packet header 
 202 void DecodeTCPHeader(void* InDataStart
) 
 204         #if !defined(NO_DECODE_TCP) 
 205         TCP_Header_t
* TCPHeader  
= (TCP_Header_t
*)InDataStart
; 
 207         uint16_t               HeaderLengthBytes 
= (TCPHeader
->DataOffset 
* sizeof(uint32_t)); 
 209         printf_P(PSTR("    \\\r\n     TCP\r\n")); 
 211         printf_P(PSTR("     + Header Length: %u Bytes\r\n"), HeaderLengthBytes
); 
 213         printf_P(PSTR("     + Source Port: %u\r\n"), SwapEndian_16(TCPHeader
->SourcePort
)); 
 214         printf_P(PSTR("     + Destination Port: %u\r\n"), SwapEndian_16(TCPHeader
->DestinationPort
)); 
 216         printf_P(PSTR("     + Sequence Number: %lu\r\n"), SwapEndian_32(TCPHeader
->SequenceNumber
)); 
 217         printf_P(PSTR("     + Acknowledgment Number: %lu\r\n"), SwapEndian_32(TCPHeader
->AcknowledgmentNumber
)); 
 219         printf_P(PSTR("     + Flags: 0x%02X\r\n"), TCPHeader
->Flags
); 
 221         if (TCP_GetPortState(TCPHeader
->DestinationPort
) == TCP_Port_Closed
) 
 222           printf_P(PSTR("     + NOT LISTENING ON DESTINATION PORT\r\n")); 
 226 /** Decodes an UDP header and prints its contents to through the USART in a human readable format. 
 228  *  \param[in] InDataStart  Pointer to the start of a UDP packet header 
 230 void DecodeUDPHeader(void* InDataStart
) 
 232         #if !defined(NO_DECODE_UDP) 
 233         UDP_Header_t
* UDPHeader 
= (UDP_Header_t
*)InDataStart
; 
 235         printf_P(PSTR("    \\\r\n     UDP\r\n")); 
 237         printf_P(PSTR("     + Source Port: %u\r\n"), SwapEndian_16(UDPHeader
->SourcePort
)); 
 238         printf_P(PSTR("     + Destination Port: %u\r\n"), SwapEndian_16(UDPHeader
->DestinationPort
)); 
 240         printf_P(PSTR("     + Data Length: %d\r\n"), SwapEndian_16(UDPHeader
->Length
)); 
 244 /** Decodes an DHCP header and prints its contents to through the USART in a human readable format. 
 246  *  \param[in] InDataStart  Pointer to the start of a DHCP packet header 
 248 void DecodeDHCPHeader(void* InDataStart
) 
 250         #if !defined(NO_DECODE_DHCP) 
 251         uint8_t* DHCPOptions 
= (InDataStart 
+ sizeof(DHCP_Header_t
)); 
 253         printf_P(PSTR("     \\\r\n      DHCP\r\n")); 
 255         while (DHCPOptions
[0] != DHCP_OPTION_END
) 
 257                 if (DHCPOptions
[0] == DHCP_OPTION_MESSAGETYPE
) 
 259                         switch (DHCPOptions
[2]) 
 261                                 case DHCP_MESSAGETYPE_DISCOVER
: 
 262                                         printf_P(PSTR("      + DISCOVER\r\n")); 
 264                                 case DHCP_MESSAGETYPE_REQUEST
: 
 265                                         printf_P(PSTR("      + REQUEST\r\n")); 
 267                                 case DHCP_MESSAGETYPE_RELEASE
: 
 268                                         printf_P(PSTR("      + RELEASE\r\n")); 
 270                                 case DHCP_MESSAGETYPE_DECLINE
: 
 271                                         printf_P(PSTR("      + DECLINE\r\n")); 
 276                 DHCPOptions 
+= ((DHCPOptions
[0] == DHCP_OPTION_PAD
) ? 
1 : (DHCPOptions
[1] + 2));