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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (hide annotations) (download)
Thu Apr 19 09:01:15 2007 UTC (17 years, 2 months ago) by hedin
File MIME type: text/plain
File size: 10823 byte(s)
added the TCP/IP stack, source code.
1 hedin 15 /*********************************************************************
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