Details | Last modification | View Log | SVN | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 363 | johboh | 1 | /********************************************************************* |
| 2 | * |
||
| 3 | * PIC IP Module for Microchip TCP/IP Stack |
||
| 4 | * |
||
| 5 | ********************************************************************* |
||
| 6 | * FileName: IP.C |
||
| 7 | * Dependencies: string.h |
||
| 8 | * StackTsk.h |
||
| 9 | * Helpers.h |
||
| 10 | * IP.h |
||
| 11 | * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F |
||
| 12 | * Complier: Microchip C18 v3.02 or higher |
||
| 13 | * Microchip C30 v2.01 or higher |
||
| 14 | * Company: Microchip Technology, Inc. |
||
| 15 | * |
||
| 16 | * Software License Agreement |
||
| 17 | * |
||
| 18 | * This software is owned by Microchip Technology Inc. ("Microchip") |
||
| 19 | * and is supplied to you for use exclusively as described in the |
||
| 20 | * associated software agreement. This software is protected by |
||
| 21 | * software and other intellectual property laws. Any use in |
||
| 22 | * violation of the software license may subject the user to criminal |
||
| 23 | * sanctions as well as civil liability. Copyright 2006 Microchip |
||
| 24 | * Technology Inc. All rights reserved. |
||
| 25 | * |
||
| 26 | * This software is provided "AS IS." MICROCHIP DISCLAIMS ALL |
||
| 27 | * WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED |
||
| 28 | * TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND |
||
| 29 | * INFRINGEMENT. Microchip shall in no event be liable for special, |
||
| 30 | * incidental, or consequential damages. |
||
| 31 | * |
||
| 32 | * |
||
| 33 | * Author Date Comment |
||
| 34 | *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
| 35 | * Nilesh Rajbharti 4/27/01 Original (Rev 1.0) |
||
| 36 | * Nilesh Rajbharti 2/9/02 Cleanup |
||
| 37 | * Nilesh Rajbharti 5/22/02 Rev 2.0 (See version.log for detail) |
||
| 38 | * Howard Schlunder 8/31/04 Beta Rev 0.9 (See version.log for detail) |
||
| 39 | * Howard Schlunder 1/5/06 Improved DMA checksum efficiency |
||
| 40 | ********************************************************************/ |
||
| 41 | |||
| 42 | #include <string.h> |
||
| 43 | |||
| 44 | #include "..\Include\StackTsk.h" |
||
| 45 | #include "..\Include\Helpers.h" |
||
| 46 | #include "..\Include\MAC.h" |
||
| 47 | #include "..\Include\IP.h" |
||
| 48 | |||
| 49 | // This is left shifted by 4. Actual value is 0x04. |
||
| 50 | #define IPv4 (0x40u) |
||
| 51 | #define IP_VERSION IPv4 |
||
| 52 | |||
| 53 | // IHL (Internet Header Length) is # of DWORDs in a header. |
||
| 54 | // Since, we do not support options, our IP header length will be |
||
| 55 | // minimum i.e. 20 bytes : IHL = 20 / 4 = 5. |
||
| 56 | #define IP_IHL (0x05) |
||
| 57 | |||
| 58 | #define IP_SERVICE_NW_CTRL (0x07) |
||
| 59 | #define IP_SERVICE_IN_CTRL (0x06) |
||
| 60 | #define IP_SERVICE_ECP (0x05) |
||
| 61 | #define IP_SERVICE_OVR (0x04) |
||
| 62 | #define IP_SERVICE_FLASH (0x03) |
||
| 63 | #define IP_SERVICE_IMM (0x02) |
||
| 64 | #define IP_SERVICE_PRIOR (0x01) |
||
| 65 | #define IP_SERVICE_ROUTINE (0x00) |
||
| 66 | |||
| 67 | #define IP_SERVICE_N_DELAY (0x00) |
||
| 68 | #define IP_SERCICE_L_DELAY (0x08) |
||
| 69 | #define IP_SERVICE_N_THRPT (0x00) |
||
| 70 | #define IP_SERVICE_H_THRPT (0x10) |
||
| 71 | #define IP_SERVICE_N_RELIB (0x00) |
||
| 72 | #define IP_SERVICE_H_RELIB (0x20) |
||
| 73 | |||
| 74 | #define IP_SERVICE (IP_SERVICE_ROUTINE | IP_SERVICE_N_DELAY) |
||
| 75 | |||
| 76 | #define MY_IP_TTL (100) // Time-To-Live in Seconds |
||
| 77 | |||
| 78 | |||
| 79 | |||
| 80 | |||
| 81 | static WORD _Identifier = 0; |
||
| 82 | static BYTE IPHeaderLen; |
||
| 83 | |||
| 84 | |||
| 85 | static void SwapIPHeader(IP_HEADER* h); |
||
| 86 | |||
| 87 | |||
| 88 | |||
| 89 | |||
| 90 | /********************************************************************* |
||
| 91 | * Function: BOOL IPGetHeader( IP_ADDR *localIP, |
||
| 92 | * NODE_INFO *remote, |
||
| 93 | * BYTE *Protocol, |
||
| 94 | * WORD *len) |
||
| 95 | * |
||
| 96 | * PreCondition: MACGetHeader() == TRUE |
||
| 97 | * |
||
| 98 | * Input: localIP - Local node IP Address as received |
||
| 99 | * in current IP header. |
||
| 100 | * If this information is not required |
||
| 101 | * caller may pass NULL value. |
||
| 102 | * remote - Remote node info |
||
| 103 | * Protocol - Current packet protocol |
||
| 104 | * len - Current packet data length |
||
| 105 | * |
||
| 106 | * Output: TRUE, if valid packet was received |
||
| 107 | * FALSE otherwise |
||
| 108 | * |
||
| 109 | * Side Effects: None |
||
| 110 | * |
||
| 111 | * Note: Only one IP message can be received. |
||
| 112 | * Caller may not transmit and receive a message |
||
| 113 | * at the same time. |
||
| 114 | * |
||
| 115 | ********************************************************************/ |
||
| 116 | BOOL IPGetHeader(IP_ADDR *localIP, |
||
| 117 | NODE_INFO *remote, |
||
| 118 | BYTE *protocol, |
||
| 119 | WORD *len) |
||
| 120 | { |
||
| 121 | WORD_VAL CalcChecksum; |
||
| 122 | IP_HEADER header; |
||
| 123 | |||
| 124 | #if defined(NON_MCHP_MAC) |
||
| 125 | WORD_VAL ReceivedChecksum; |
||
| 126 | WORD checksums[2]; |
||
| 127 | BYTE optionsLen; |
||
| 128 | #define MAX_OPTIONS_LEN (40) // As per RFC 791. |
||
| 129 | BYTE options[MAX_OPTIONS_LEN]; |
||
| 130 | #endif |
||
| 131 | |||
| 132 | // Read IP header. |
||
| 133 | MACGetArray((BYTE*)&header, sizeof(header)); |
||
| 134 | |||
| 135 | // Make sure that this is an IPv4 packet. |
||
| 136 | if ( (header.VersionIHL & 0xf0) != IP_VERSION ) |
||
| 137 | return FALSE; |
||
| 138 | |||
| 139 | #if !defined(NON_MCHP_MAC) |
||
| 140 | IPHeaderLen = (header.VersionIHL & 0x0f) << 2; |
||
| 141 | |||
| 142 | // Validate the IP header. If it is correct, the checksum |
||
| 143 | // will come out to 0x0000 (because the header contains a |
||
| 144 | // precomputed checksum). A corrupt header will have a |
||
| 145 | // nonzero checksum. |
||
| 146 | CalcChecksum.Val = MACCalcRxChecksum(0, IPHeaderLen); |
||
| 147 | |||
| 148 | // Seek to the end of the IP header |
||
| 149 | MACSetRxBuffer(IPHeaderLen); |
||
| 150 | |||
| 151 | if(CalcChecksum.Val) |
||
| 152 | #else |
||
| 153 | |||
| 154 | // Calculate options length in this header, if there is any. |
||
| 155 | // IHL is in terms of numbers of 32-bit DWORDs; i.e. actual |
||
| 156 | // length is 4 times IHL. |
||
| 157 | optionsLen = ((header.VersionIHL & 0x0f) << 2) - sizeof(header); |
||
| 158 | |||
| 159 | // If there is any option(s), read it so that we can include them |
||
| 160 | // in checksum calculation. |
||
| 161 | if ( optionsLen > MAX_OPTIONS_LEN ) |
||
| 162 | return FALSE; |
||
| 163 | |||
| 164 | if ( optionsLen > 0 ) |
||
| 165 | MACGetArray(options, optionsLen); |
||
| 166 | |||
| 167 | // Save header checksum; clear it and recalculate it ourselves. |
||
| 168 | ReceivedChecksum.Val = header.HeaderChecksum; |
||
| 169 | header.HeaderChecksum = 0; |
||
| 170 | |||
| 171 | // Calculate checksum of header including options bytes. |
||
| 172 | checksums[0] = ~CalcIPChecksum((BYTE*)&header, sizeof(header)); |
||
| 173 | |||
| 174 | // Calculate Options checksum too, if they are present. |
||
| 175 | if ( optionsLen > 0 ) |
||
| 176 | checksums[1] = ~CalcIPChecksum((BYTE*)options, optionsLen); |
||
| 177 | else |
||
| 178 | checksums[1] = 0; |
||
| 179 | |||
| 180 | CalcChecksum.Val = CalcIPChecksum((BYTE*)checksums, |
||
| 181 | 2 * sizeof(WORD)); |
||
| 182 | |||
| 183 | // Make sure that checksum is correct |
||
| 184 | if ( ReceivedChecksum.Val != CalcChecksum.Val ) |
||
| 185 | #endif |
||
| 186 | { |
||
| 187 | // Bad packet. The function caller will be notified by means of the FALSE |
||
| 188 | // return value and it should discard the packet. |
||
| 189 | return FALSE; |
||
| 190 | } |
||
| 191 | |||
| 192 | // Network to host conversion. |
||
| 193 | SwapIPHeader(&header); |
||
| 194 | |||
| 195 | // If caller is intrested, return destination IP address |
||
| 196 | // as seen in this IP header. |
||
| 197 | if ( localIP ) |
||
| 198 | localIP->Val = header.DestAddress.Val; |
||
| 199 | |||
| 200 | remote->IPAddr.Val = header.SourceAddress.Val; |
||
| 201 | *protocol = header.Protocol; |
||
| 202 | #if !defined(NON_MCHP_MAC) |
||
| 203 | *len = header.TotalLength - IPHeaderLen; |
||
| 204 | #else |
||
| 205 | *len = header.TotalLength - optionsLen - |
||
| 206 | sizeof(header); |
||
| 207 | #endif |
||
| 208 | |||
| 209 | return TRUE; |
||
| 210 | } |
||
| 211 | |||
| 212 | |||
| 213 | |||
| 214 | |||
| 215 | /********************************************************************* |
||
| 216 | * Function: WORD IPPutHeader(NODE_INFO *remote, |
||
| 217 | * BYTE protocol, |
||
| 218 | * WORD len) |
||
| 219 | * |
||
| 220 | * PreCondition: IPIsTxReady() == TRUE |
||
| 221 | * |
||
| 222 | * Input: *remote - Destination node address |
||
| 223 | * protocol - Current packet protocol |
||
| 224 | * len - Current packet data length |
||
| 225 | * |
||
| 226 | * Output: (WORD)0 |
||
| 227 | * |
||
| 228 | * Side Effects: None |
||
| 229 | * |
||
| 230 | * Note: Only one IP message can be transmitted at any |
||
| 231 | * time. |
||
| 232 | ********************************************************************/ |
||
| 233 | WORD IPPutHeader(NODE_INFO *remote, |
||
| 234 | BYTE protocol, |
||
| 235 | WORD len) |
||
| 236 | { |
||
| 237 | IP_HEADER header; |
||
| 238 | |||
| 239 | IPHeaderLen = sizeof(IP_HEADER); |
||
| 240 | |||
| 241 | header.VersionIHL = IP_VERSION | IP_IHL; |
||
| 242 | header.TypeOfService = IP_SERVICE; |
||
| 243 | header.TotalLength = sizeof(header) + len; |
||
| 244 | header.Identification = ++_Identifier; |
||
| 245 | header.FragmentInfo = 0; |
||
| 246 | header.TimeToLive = MY_IP_TTL; |
||
| 247 | header.Protocol = protocol; |
||
| 248 | header.HeaderChecksum = 0; |
||
| 249 | header.SourceAddress = AppConfig.MyIPAddr; |
||
| 250 | |||
| 251 | header.DestAddress.Val = remote->IPAddr.Val; |
||
| 252 | |||
| 253 | SwapIPHeader(&header); |
||
| 254 | |||
| 255 | #if defined(NON_MCHP_MAC) |
||
| 256 | header.HeaderChecksum = CalcIPChecksum((BYTE*)&header, |
||
| 257 | sizeof(header)); |
||
| 258 | #endif |
||
| 259 | |||
| 260 | MACPutHeader(&remote->MACAddr, MAC_IP, (sizeof(header)+len)); |
||
| 261 | MACPutArray((BYTE*)&header, sizeof(header)); |
||
| 262 | |||
| 263 | #if !defined(NON_MCHP_MAC) |
||
| 264 | header.HeaderChecksum = MACCalcTxChecksum(0, sizeof(header)); |
||
| 265 | MACSetTxBuffer(CurrentTxBuffer, 10); // 10 is the offset in header to the HeaderChecksum member |
||
| 266 | MACPutArray((BYTE*)&header.HeaderChecksum, 2); |
||
| 267 | MACSetTxBuffer(CurrentTxBuffer, sizeof(header)); // Seek back to the end of the packet |
||
| 268 | #endif |
||
| 269 | |||
| 270 | return 0x0; |
||
| 271 | |||
| 272 | } |
||
| 273 | |||
| 274 | /********************************************************************* |
||
| 275 | * Function: IPSetRxBuffer(WORD Offset) |
||
| 276 | * |
||
| 277 | * PreCondition: IPHeaderLen must have been intialized by |
||
| 278 | * IPGetHeader() or IPPutHeader() |
||
| 279 | * |
||
| 280 | * Input: Offset from beginning of IP data field |
||
| 281 | * |
||
| 282 | * Output: Next Read/Write access to receive buffer is |
||
| 283 | * set to Offset |
||
| 284 | * |
||
| 285 | * Side Effects: None |
||
| 286 | * |
||
| 287 | * Note: None |
||
| 288 | * |
||
| 289 | ********************************************************************/ |
||
| 290 | void IPSetRxBuffer(WORD Offset) |
||
| 291 | { |
||
| 292 | MACSetRxBuffer(Offset+IPHeaderLen); |
||
| 293 | } |
||
| 294 | |||
| 295 | |||
| 296 | |||
| 297 | static void SwapIPHeader(IP_HEADER* h) |
||
| 298 | { |
||
| 299 | h->TotalLength = swaps(h->TotalLength); |
||
| 300 | h->Identification = swaps(h->Identification); |
||
| 301 | h->HeaderChecksum = swaps(h->HeaderChecksum); |
||
| 302 | } |