]> git.donarmstrong.com Git - qmk_firmware.git/blob - Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c
Squashed 'lib/lufa/' content from commit 385d40300
[qmk_firmware.git] / Demos / Device / ClassDriver / RNDISEthernet / Lib / ProtocolDecoders.c
1 /*
2              LUFA Library
3      Copyright (C) Dean Camera, 2017.
4
5   dean [at] fourwalledcubicle [dot] com
6            www.lufa-lib.org
7 */
8
9 /*
10   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
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.
20
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
28   this software.
29 */
30
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.
34
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.
37 */
38
39 /** \file
40  *
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
43  *  readable format.
44  *
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.
48  */
49
50 #include "ProtocolDecoders.h"
51
52 /** Decodes an Ethernet frame header and prints its contents to through the USART in a human readable format.
53  *
54  *  \param[in] InDataStart  Pointer to the start of an Ethernet frame of data
55  */
56 void DecodeEthernetFrameHeader(void* InDataStart)
57 {
58         #if !defined(NO_DECODE_ETHERNET)
59         Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)InDataStart;
60
61         printf_P(PSTR("\r\n"));
62
63         printf_P(PSTR("  ETHERNET\r\n"));
64
65         if (!(MAC_COMPARE(&FrameHeader->Destination, &ServerMACAddress)) &&
66             !(MAC_COMPARE(&FrameHeader->Destination, &BroadcastMACAddress)))
67         {
68                 printf_P(PSTR("  + NOT ADDRESSED TO DEVICE\r\n"));
69                 return;
70         }
71
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]);
78
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]);
85
86         printf_P(PSTR("  + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType));
87         #endif
88 }
89
90 /** Decodes an ARP header and prints its contents to through the USART in a human readable format.
91  *
92  *  \param[in] InDataStart  Pointer to the start of an ARP packet header
93  */
94 void DecodeARPHeader(void* InDataStart)
95 {
96         #if !defined(NO_DECODE_ARP)
97         ARP_Header_t* ARPHeader = (ARP_Header_t*)InDataStart;
98
99         printf_P(PSTR("   \\\r\n    ARP\r\n"));
100
101         if (!(IP_COMPARE(&ARPHeader->TPA, &ServerIPAddress)) &&
102             !(MAC_COMPARE(&ARPHeader->THA, &ServerMACAddress)))
103         {
104                 printf_P(PSTR("    + NOT ADDRESSED TO DEVICE\r\n"));
105                 return;
106         }
107
108         printf_P(PSTR("    + Protocol: %x\r\n"), SwapEndian_16(ARPHeader->ProtocolType));
109         printf_P(PSTR("    + Operation: %u\r\n"), SwapEndian_16(ARPHeader->Operation));
110
111         if (SwapEndian_16(ARPHeader->ProtocolType) == ETHERTYPE_IPV4)
112         {
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]);
119
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]);
124
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]);
131
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]);
136         }
137         #endif
138 }
139
140 /** Decodes an IP header and prints its contents to through the USART in a human readable format.
141  *
142  *  \param[in] InDataStart  Pointer to the start of an IP packet header
143  */
144 void DecodeIPHeader(void* InDataStart)
145 {
146         #if !defined(NO_DECODE_IP)
147         IP_Header_t* IPHeader  = (IP_Header_t*)InDataStart;
148
149         uint16_t HeaderLengthBytes = (IPHeader->HeaderLength * sizeof(uint32_t));
150
151         printf_P(PSTR("   \\\r\n    IP\r\n"));
152
153         if (!(IP_COMPARE(&IPHeader->DestinationAddress, &ServerIPAddress)))
154         {
155                 printf_P(PSTR("    + NOT ADDRESSED TO DEVICE\r\n"));
156                 return;
157         }
158
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));
162
163         printf_P(PSTR("    + Protocol: %u\r\n"), IPHeader->Protocol);
164         printf_P(PSTR("    + TTL: %u\r\n"), IPHeader->TTL);
165
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]);
170
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]);
175         #endif
176 }
177
178 /** Decodes an ICMP header and prints its contents to through the USART in a human readable format.
179  *
180  *  \param[in] InDataStart  Pointer to the start of an ICMP packet header
181  */
182 void DecodeICMPHeader(void* InDataStart)
183 {
184         #if !defined(NO_DECODE_ICMP)
185         ICMP_Header_t* ICMPHeader  = (ICMP_Header_t*)InDataStart;
186
187         printf_P(PSTR("    \\\r\n     ICMP\r\n"));
188
189         printf_P(PSTR("     + Type: %u\r\n"), ICMPHeader->Type);
190         printf_P(PSTR("     + Code: %u\r\n"), ICMPHeader->Code);
191         #endif
192 }
193
194 /** Decodes a TCP header and prints its contents to through the USART in a human readable format.
195  *
196  *  \param[in] InDataStart  Pointer to the start of a TCP packet header
197  */
198 void DecodeTCPHeader(void* InDataStart)
199 {
200         #if !defined(NO_DECODE_TCP)
201         TCP_Header_t* TCPHeader  = (TCP_Header_t*)InDataStart;
202
203         uint16_t               HeaderLengthBytes = (TCPHeader->DataOffset * sizeof(uint32_t));
204
205         printf_P(PSTR("    \\\r\n     TCP\r\n"));
206
207         printf_P(PSTR("     + Header Length: %u Bytes\r\n"), HeaderLengthBytes);
208
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));
211
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));
214
215         printf_P(PSTR("     + Flags: 0x%02X\r\n"), TCPHeader->Flags);
216
217         if (TCP_GetPortState(TCPHeader->DestinationPort) == TCP_Port_Closed)
218           printf_P(PSTR("     + NOT LISTENING ON DESTINATION PORT\r\n"));
219         #endif
220 }
221
222 /** Decodes an UDP header and prints its contents to through the USART in a human readable format.
223  *
224  *  \param[in] InDataStart  Pointer to the start of a UDP packet header
225  */
226 void DecodeUDPHeader(void* InDataStart)
227 {
228         #if !defined(NO_DECODE_UDP)
229         UDP_Header_t* UDPHeader = (UDP_Header_t*)InDataStart;
230
231         printf_P(PSTR("    \\\r\n     UDP\r\n"));
232
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));
235
236         printf_P(PSTR("     + Data Length: %d\r\n"), SwapEndian_16(UDPHeader->Length));
237         #endif
238 }
239
240 /** Decodes an DHCP header and prints its contents to through the USART in a human readable format.
241  *
242  *  \param[in] InDataStart  Pointer to the start of a DHCP packet header
243  */
244 void DecodeDHCPHeader(void* InDataStart)
245 {
246         #if !defined(NO_DECODE_DHCP)
247         uint8_t* DHCPOptions = ((uint8_t*)InDataStart + sizeof(DHCP_Header_t));
248
249         printf_P(PSTR("     \\\r\n      DHCP\r\n"));
250
251         while (DHCPOptions[0] != DHCP_OPTION_END)
252         {
253                 if (DHCPOptions[0] == DHCP_OPTION_MESSAGETYPE)
254                 {
255                         switch (DHCPOptions[2])
256                         {
257                                 case DHCP_MESSAGETYPE_DISCOVER:
258                                         printf_P(PSTR("      + DISCOVER\r\n"));
259                                         break;
260                                 case DHCP_MESSAGETYPE_REQUEST:
261                                         printf_P(PSTR("      + REQUEST\r\n"));
262                                         break;
263                                 case DHCP_MESSAGETYPE_RELEASE:
264                                         printf_P(PSTR("      + RELEASE\r\n"));
265                                         break;
266                                 case DHCP_MESSAGETYPE_DECLINE:
267                                         printf_P(PSTR("      + DECLINE\r\n"));
268                                         break;
269                         }
270                 }
271
272                 DHCPOptions += ((DHCPOptions[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptions[1] + 2));
273         }
274
275         #endif
276 }
277