/[H8]/trunk/docs/Microchip TCP_IP stack/TCPIP Stack/ICMP.c
ViewVC logotype

Contents of /trunk/docs/Microchip TCP_IP stack/TCPIP Stack/ICMP.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (show annotations) (download)
Thu Apr 19 09:01:15 2007 UTC (17 years, 1 month ago) by hedin
File MIME type: text/plain
File size: 10823 byte(s)
added the TCP/IP stack, source code.
1 /*********************************************************************
2 *
3 * Internet Control Message Protocol (ICMP) Server
4 * Module for Microchip TCP/IP Stack
5 * -Provides "ping" diagnostics
6 * -Reference: RFC 792
7 *
8 *********************************************************************
9 * FileName: ICMP.c
10 * Dependencies: ICMP.h
11 * string.h
12 * StackTsk.h
13 * Helpers.h
14 * IP.h
15 * MAC.h
16 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
17 * Complier: Microchip C18 v3.10 or higher
18 * Microchip C30 v2.05 or higher
19 * Company: Microchip Technology, Inc.
20 *
21 * Software License Agreement
22 *
23 * Copyright © 2002-2007 Microchip Technology Inc. All rights
24 * reserved.
25 *
26 * Microchip licenses to you the right to use, modify, copy, and
27 * distribute:
28 * (i) the Software when embedded on a Microchip microcontroller or
29 * digital signal controller product (“Device”) which is
30 * integrated into Licensee’s product; or
31 * (ii) ONLY the Software driver source files ENC28J60.c and
32 * ENC28J60.h ported to a non-Microchip device used in
33 * conjunction with a Microchip ethernet controller for the
34 * sole purpose of interfacing with the ethernet controller.
35 *
36 * You should refer to the license agreement accompanying this
37 * Software for additional information regarding your rights and
38 * obligations.
39 *
40 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT
41 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
42 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
43 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
44 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
45 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
46 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
47 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
48 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
49 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
50 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
51 *
52 *
53 * Author Date Comment
54 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
55 * Howard Schlunder 03/16/07 Original
56 ********************************************************************/
57 #define __ICMP_C
58
59 #include "TCPIP Stack/TCPIP.h"
60
61 #if defined(STACK_USE_ICMP_SERVER) || defined(STACK_USE_ICMP_CLIENT)
62
63 #if defined(STACK_USE_ICMP_CLIENT)
64
65 #define ICMP_TIMEOUT (4*TICK_SECOND)
66
67 typedef struct _ICMP_HEADER
68 {
69 BYTE vType;
70 BYTE vCode;
71 WORD_VAL wvChecksum;
72 WORD_VAL wvIdentifier;
73 WORD_VAL wvSequenceNumber;
74 } ICMP_HEADER;
75
76 static ICMP_HEADER ICMPHeader;
77 static WORD ICMPTimer;
78 static struct
79 {
80 unsigned char bICMPInUse:1;
81 unsigned char bReplyValid:1;
82 } ICMPFlags = {0x00};
83 static NODE_INFO ICMPRemote;
84 static enum
85 {
86 SM_IDLE = 0,
87 SM_ARP_RESOLVE,
88 SM_GET_ECHO
89 } ICMPState;
90 #endif //#if defined(STACK_USE_ICMP_CLIENT)
91
92 /*********************************************************************
93 * Function: void ICMPProcess(void)
94 *
95 * PreCondition: MAC buffer contains ICMP type packet.
96 *
97 * Input: *remote: Pointer to a NODE_INFO structure of the
98 * ping requester
99 * len: Count of how many bytes the ping header and
100 * payload are in this IP packet
101 *
102 * Output: Generates an echo reply, if requested
103 * Validates and sets ICMPFlags.bReplyValid if a
104 * correct ping response to one of ours is received.
105 *
106 * Side Effects: None
107 *
108 * Overview: None
109 *
110 * Note: None
111 ********************************************************************/
112 void ICMPProcess(NODE_INFO *remote, WORD len)
113 {
114 DWORD_VAL dwVal;
115
116 // Obtain the ICMP header Type, Code, and Checksum fields
117 MACGetArray((BYTE*)&dwVal, sizeof(dwVal));
118
119 // See if this is an ICMP echo (ping) request
120 if(dwVal.w[0] == 0x0008)
121 {
122 // Validate the checksum using the Microchip MAC's DMA module
123 // The checksum data includes the precomputed checksum in the
124 // header, so a valid packet will always have a checksum of
125 // 0x0000 if the packet is not disturbed.
126 if(MACCalcRxChecksum(0+sizeof(IP_HEADER), len))
127 return;
128
129 // Calculate new Type, Code, and Checksum values
130 dwVal.v[0] = 0x00; // Type: 0 (ICMP echo/ping reply)
131 dwVal.v[2] += 8; // Subtract 0x0800 from the checksum
132 if(dwVal.v[2] < 8)
133 {
134 dwVal.v[3]++;
135 if(dwVal.v[3] == 0)
136 dwVal.v[2]++;
137 }
138
139 // Position the write pointer for the next IPPutHeader operation
140 MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
141
142 // Wait for TX hardware to become available (finish transmitting
143 // any previous packet)
144 while(!IPIsTxReady());
145
146 // Create IP header in TX memory
147 IPPutHeader(remote, IP_PROT_ICMP, len);
148
149 // Copy ICMP response into the TX memory
150 MACPutArray((BYTE*)&dwVal, sizeof(dwVal));
151 MACMemCopyAsync(-1, -1, len-4);
152 while(!MACIsMemCopyDone());
153
154 // Transmit the echo reply packet
155 MACFlush();
156 }
157 #if defined(STACK_USE_ICMP_CLIENT)
158 else if(dwVal.w[0] == 0x0000) // See if this an ICMP Echo reply to our request
159 {
160 // Get the sequence number and identifier fields
161 MACGetArray((BYTE*)&dwVal, sizeof(dwVal));
162
163 // See if the identifier matches the one we sent
164 if(dwVal.w[0] != 0xEFBE)
165 return;
166
167 if(dwVal.w[1] != ICMPHeader.wvSequenceNumber.Val)
168 return;
169
170 // Validate the ICMP checksum field
171 IPSetRxBuffer(0);
172 if(CalcIPBufferChecksum(sizeof(ICMP_HEADER)))
173 return;
174
175 // Flag that we received the response and stop the timer ticking
176 ICMPFlags.bReplyValid = 1;
177 ICMPTimer = TickGet() - ICMPTimer;
178 }
179 #endif
180 }
181
182 /*********************************************************************
183 * Function: void ICMPSendPing(DWORD dwRemoteIP)
184 *
185 * PreCondition: ICMPBeginUsage() returned TRUE
186 *
187 * Input: dwRemoteIP: IP Address to ping. Must be stored
188 * big endian. Ex: 192.168.0.1 should be
189 * passed as 0xC0A80001.
190 *
191 * Output: Begins the process of transmitting an ICMP echo
192 * request. This normally involves an ARP
193 * resolution procedure first.
194 *
195 * Side Effects: None
196 *
197 * Overview: None
198 *
199 * Note: None
200 ********************************************************************/
201 #if defined(STACK_USE_ICMP_CLIENT)
202 void ICMPSendPing(DWORD dwRemoteIP)
203 {
204 // Figure out the MAC address to send to
205 ICMPRemote.IPAddr.Val = dwRemoteIP;
206 ARPResolve(&ICMPRemote.IPAddr);
207
208 // Set up the ping packet
209 ICMPHeader.vType = 0x08; // 0x08: Echo (ping) request
210 ICMPHeader.vCode = 0x00;
211 ICMPHeader.wvChecksum.Val = 0x0000;
212 ICMPHeader.wvIdentifier.Val = 0xEFBE;
213 ICMPHeader.wvSequenceNumber.Val++;
214 ICMPHeader.wvChecksum.Val = CalcIPChecksum((BYTE*)&ICMPHeader, sizeof(ICMPHeader));
215
216 // Kick off the ICMPGetReply() state machine
217 ICMPTimer = (WORD)TickGet();
218 ICMPFlags.bReplyValid = 0;
219 ICMPState = SM_ARP_RESOLVE;
220 }
221
222
223 /*********************************************************************
224 * Function: SHORT ICMPGetReply(void)
225 *
226 * PreCondition: ICMPBeginUsage() returned TRUE and ICMPSendPing()
227 * was called
228 *
229 * Input: None
230 *
231 * Output: -2: No response received yet
232 * -1: Operation timed out (longer than ICMP_TIMEOUT)
233 * has elapsed.
234 * >=0: Number of TICKs that elapsed between
235 * initial ICMP transmission and reception of
236 * a valid echo.
237 *
238 * Side Effects: None
239 *
240 * Overview: None
241 *
242 * Note: None
243 ********************************************************************/
244 SHORT ICMPGetReply(void)
245 {
246 switch(ICMPState)
247 {
248 case SM_IDLE:
249 return -1;
250
251 case SM_ARP_RESOLVE:
252 // See if the ARP reponse was successfully received
253 if(ARPIsResolved(&ICMPRemote.IPAddr, &ICMPRemote.MACAddr))
254 {
255 // Position the write pointer for the next IPPutHeader operation
256 MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
257
258 // Wait for TX hardware to become available (finish transmitting
259 // any previous packet)
260 while(!IPIsTxReady());
261
262 // Create IP header in TX memory
263 IPPutHeader(&ICMPRemote, IP_PROT_ICMP, sizeof(ICMP_HEADER));
264 MACPutArray((BYTE*)&ICMPHeader, sizeof(ICMPHeader));
265 MACFlush();
266
267 // MAC Address resolved and echo sent, advance state
268 ICMPState = SM_GET_ECHO;
269 return -2;
270 }
271
272 // See if the ARP/echo request timed out
273 if((WORD)TickGet() - ICMPTimer > ICMP_TIMEOUT)
274 {
275 ICMPState = SM_IDLE;
276 return -1;
277 }
278
279 // No ARP response back yet
280 return -2;
281
282 case SM_GET_ECHO:
283 // See if the echo was successfully received
284 if(ICMPFlags.bReplyValid)
285 {
286 return (SHORT)ICMPTimer;
287 }
288
289 // See if the ARP/echo request timed out
290 if((WORD)TickGet() - ICMPTimer > ICMP_TIMEOUT)
291 {
292 ICMPState = SM_IDLE;
293 return -1;
294 }
295
296 // No echo response back yet
297 return -2;
298 }
299 }
300
301
302 /*********************************************************************
303 * Function: BOOL ICMPBeginUsage(void)
304 *
305 * PreCondition: None
306 *
307 * Input: None
308 *
309 * Output: TRUE: You have successfully gained ownership of
310 * the ICMP client module and can now use the
311 * ICMPSendPing() and ICMPGetReply() functions.
312 * FALSE: Some other application is using the ICMP
313 * client module. Calling ICMPSendPing()
314 * will corrupt the other application's ping
315 * result.
316 *
317 * Side Effects: None
318 *
319 * Overview: None
320 *
321 * Note: None
322 ********************************************************************/
323 BOOL ICMPBeginUsage(void)
324 {
325 if(ICMPFlags.bICMPInUse)
326 return FALSE;
327
328 ICMPFlags.bICMPInUse = TRUE;
329 return TRUE;
330 }
331
332
333 /*********************************************************************
334 * Function: void ICMPEndUsage(void)
335 *
336 * PreCondition: ICMPBeginUsage() was called by you and it
337 * returned TRUE.
338 *
339 * Input: None
340 *
341 * Output: Your ownership of the ICMP module is released.
342 * You can no longer use ICMPSendPing().
343 *
344 * Side Effects: None
345 *
346 * Overview: None
347 *
348 * Note: None
349 ********************************************************************/
350 void ICMPEndUsage(void)
351 {
352 ICMPFlags.bICMPInUse = FALSE;
353 }
354 #endif //#if defined(STACK_USE_ICMP_CLIENT)
355
356 #endif //#if defined(STACK_USE_ICMP_SERVER) || defined(STACK_USE_ICMP_CLIENT)

  ViewVC Help
Powered by ViewVC 1.1.20