| Line No. | Rev | Author | Line |
|---|---|---|---|
| 1 | 32 | kaklik | /********************************************************************* |
| 2 | * |
||
| 3 | * Internet Protocol (IP) Version 4 Communications Layer |
||
| 4 | * Module for Microchip TCP/IP Stack |
||
| 5 | * -Provides a transport for TCP, UDP, and ICMP messages |
||
| 6 | * -Reference: RFC 791 |
||
| 7 | * |
||
| 8 | ********************************************************************* |
||
| 9 | * FileName: IP.c |
||
| 10 | * Dependencies: Network Layer interface (ENC28J60.c, ETH97J60.c, |
||
| 11 | * ENCX24J600.c or WFMac.c) |
||
| 12 | * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32 |
||
| 13 | * Compiler: Microchip C32 v1.05 or higher |
||
| 14 | * Microchip C30 v3.12 or higher |
||
| 15 | * Microchip C18 v3.30 or higher |
||
| 16 | * HI-TECH PICC-18 PRO 9.63PL2 or higher |
||
| 17 | * Company: Microchip Technology, Inc. |
||
| 18 | * |
||
| 19 | * Software License Agreement |
||
| 20 | * |
||
| 21 | * Copyright (C) 2002-2009 Microchip Technology Inc. All rights |
||
| 22 | * reserved. |
||
| 23 | * |
||
| 24 | * Microchip licenses to you the right to use, modify, copy, and |
||
| 25 | * distribute: |
||
| 26 | * (i) the Software when embedded on a Microchip microcontroller or |
||
| 27 | * digital signal controller product ("Device") which is |
||
| 28 | * integrated into Licensee's product; or |
||
| 29 | * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h, |
||
| 30 | * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device |
||
| 31 | * used in conjunction with a Microchip ethernet controller for |
||
| 32 | * the sole purpose of interfacing with the ethernet controller. |
||
| 33 | * |
||
| 34 | * You should refer to the license agreement accompanying this |
||
| 35 | * Software for additional information regarding your rights and |
||
| 36 | * obligations. |
||
| 37 | * |
||
| 38 | * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT |
||
| 39 | * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT |
||
| 40 | * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A |
||
| 41 | * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
| 42 | * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR |
||
| 43 | * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF |
||
| 44 | * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS |
||
| 45 | * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE |
||
| 46 | * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER |
||
| 47 | * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT |
||
| 48 | * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE. |
||
| 49 | * |
||
| 50 | * |
||
| 51 | * Author Date Comment |
||
| 52 | *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
| 53 | * Nilesh Rajbharti 4/27/01 Original (Rev 1.0) |
||
| 54 | * Nilesh Rajbharti 2/9/02 Cleanup |
||
| 55 | * Nilesh Rajbharti 5/22/02 Rev 2.0 (See version.log for detail) |
||
| 56 | * Howard Schlunder 8/31/04 Beta Rev 0.9 (See version.log for detail) |
||
| 57 | * Howard Schlunder 1/5/06 Improved DMA checksum efficiency |
||
| 58 | * Darren Rook 9/21/06 Corrected IPHeaderLen not being |
||
| 59 | * initialized when NON_MCHP_MAC defined. |
||
| 60 | ********************************************************************/ |
||
| 61 | #define __IP_C |
||
| 62 | |||
| 63 | #include "TCPIP Stack/TCPIP.h" |
||
| 64 | |||
| 65 | // This is left shifted by 4. Actual value is 0x04. |
||
| 66 | #define IPv4 (0x40u) |
||
| 67 | #define IP_VERSION IPv4 |
||
| 68 | |||
| 69 | // IHL (Internet Header Length) is # of DWORDs in a header. |
||
| 70 | // Since, we do not support options, our IP header length will be |
||
| 71 | // minimum i.e. 20 bytes : IHL = 20 / 4 = 5. |
||
| 72 | #define IP_IHL (0x05) |
||
| 73 | |||
| 74 | #define IP_SERVICE_NW_CTRL (0x07) |
||
| 75 | #define IP_SERVICE_IN_CTRL (0x06) |
||
| 76 | #define IP_SERVICE_ECP (0x05) |
||
| 77 | #define IP_SERVICE_OVR (0x04) |
||
| 78 | #define IP_SERVICE_FLASH (0x03) |
||
| 79 | #define IP_SERVICE_IMM (0x02) |
||
| 80 | #define IP_SERVICE_PRIOR (0x01) |
||
| 81 | #define IP_SERVICE_ROUTINE (0x00) |
||
| 82 | |||
| 83 | #define IP_SERVICE_N_DELAY (0x00) |
||
| 84 | #define IP_SERCICE_L_DELAY (0x08) |
||
| 85 | #define IP_SERVICE_N_THRPT (0x00) |
||
| 86 | #define IP_SERVICE_H_THRPT (0x10) |
||
| 87 | #define IP_SERVICE_N_RELIB (0x00) |
||
| 88 | #define IP_SERVICE_H_RELIB (0x20) |
||
| 89 | |||
| 90 | #define IP_SERVICE (IP_SERVICE_ROUTINE | IP_SERVICE_N_DELAY) |
||
| 91 | |||
| 92 | #if defined(STACK_USE_ZEROCONF_MDNS_SD) |
||
| 93 | #define MY_IP_TTL (255) // Time-To-Live in hops |
||
| 94 | // IP TTL is set to 255 for Multicast DNS compatibility. See mDNS-draft-08, section 4. |
||
| 95 | #else |
||
| 96 | #define MY_IP_TTL (100) // Time-To-Live in hops |
||
| 97 | #endif |
||
| 98 | |||
| 99 | |||
| 100 | |||
| 101 | static WORD _Identifier = 0; |
||
| 102 | static BYTE IPHeaderLen; |
||
| 103 | |||
| 104 | |||
| 105 | static void SwapIPHeader(IP_HEADER* h); |
||
| 106 | |||
| 107 | |||
| 108 | |||
| 109 | |||
| 110 | /********************************************************************* |
||
| 111 | * Function: BOOL IPGetHeader( IP_ADDR *localIP, |
||
| 112 | * NODE_INFO *remote, |
||
| 113 | * BYTE *Protocol, |
||
| 114 | * WORD *len) |
||
| 115 | * |
||
| 116 | * PreCondition: MACGetHeader() == TRUE |
||
| 117 | * |
||
| 118 | * Input: localIP - Local node IP Address as received |
||
| 119 | * in current IP header. |
||
| 120 | * If this information is not required |
||
| 121 | * caller may pass NULL value. |
||
| 122 | * remote - Remote node info |
||
| 123 | * Protocol - Current packet protocol |
||
| 124 | * len - Current packet data length |
||
| 125 | * |
||
| 126 | * Output: TRUE, if valid packet was received |
||
| 127 | * FALSE otherwise |
||
| 128 | * |
||
| 129 | * Side Effects: None |
||
| 130 | * |
||
| 131 | * Note: Only one IP message can be received. |
||
| 132 | * Caller may not transmit and receive a message |
||
| 133 | * at the same time. |
||
| 134 | * |
||
| 135 | ********************************************************************/ |
||
| 136 | BOOL IPGetHeader(IP_ADDR *localIP, |
||
| 137 | NODE_INFO *remote, |
||
| 138 | BYTE *protocol, |
||
| 139 | WORD *len) |
||
| 140 | { |
||
| 141 | WORD_VAL CalcChecksum; |
||
| 142 | IP_HEADER header; |
||
| 143 | |||
| 144 | #if defined(NON_MCHP_MAC) |
||
| 145 | WORD_VAL ReceivedChecksum; |
||
| 146 | WORD checksums[2]; |
||
| 147 | BYTE optionsLen; |
||
| 148 | #define MAX_OPTIONS_LEN (40u) // As per RFC 791. |
||
| 149 | BYTE options[MAX_OPTIONS_LEN]; |
||
| 150 | #endif |
||
| 151 | |||
| 152 | // Read IP header. |
||
| 153 | MACGetArray((BYTE*)&header, sizeof(header)); |
||
| 154 | |||
| 155 | // Make sure that this is an IPv4 packet. |
||
| 156 | if((header.VersionIHL & 0xf0) != IP_VERSION) |
||
| 157 | return FALSE; |
||
| 158 | |||
| 159 | // Throw this packet away if it is a fragment. |
||
| 160 | // We don't have enough RAM for IP fragment reconstruction. |
||
| 161 | if(header.FragmentInfo & 0xFF1F) |
||
| 162 | return FALSE; |
||
| 163 | |||
| 164 | IPHeaderLen = (header.VersionIHL & 0x0f) << 2; |
||
| 165 | |||
| 166 | #if !defined(NON_MCHP_MAC) |
||
| 167 | // Validate the IP header. If it is correct, the checksum |
||
| 168 | // will come out to 0x0000 (because the header contains a |
||
| 169 | // precomputed checksum). A corrupt header will have a |
||
| 170 | // nonzero checksum. |
||
| 171 | CalcChecksum.Val = MACCalcRxChecksum(0, IPHeaderLen); |
||
| 172 | |||
| 173 | // Seek to the end of the IP header |
||
| 174 | MACSetReadPtrInRx(IPHeaderLen); |
||
| 175 | |||
| 176 | if(CalcChecksum.Val) |
||
| 177 | #else |
||
| 178 | // Calculate options length in this header, if there is any. |
||
| 179 | // IHL is in terms of numbers of 32-bit DWORDs; i.e. actual |
||
| 180 | // length is 4 times IHL. |
||
| 181 | optionsLen = IPHeaderLen - sizeof(header); |
||
| 182 | |||
| 183 | // If there is any option(s), read it so that we can include them |
||
| 184 | // in checksum calculation. |
||
| 185 | if ( optionsLen > MAX_OPTIONS_LEN ) |
||
| 186 | return FALSE; |
||
| 187 | |||
| 188 | if ( optionsLen > 0u ) |
||
| 189 | MACGetArray(options, optionsLen); |
||
| 190 | |||
| 191 | // Save header checksum; clear it and recalculate it ourselves. |
||
| 192 | ReceivedChecksum.Val = header.HeaderChecksum; |
||
| 193 | header.HeaderChecksum = 0; |
||
| 194 | |||
| 195 | // Calculate checksum of header including options bytes. |
||
| 196 | checksums[0] = ~CalcIPChecksum((BYTE*)&header, sizeof(header)); |
||
| 197 | |||
| 198 | // Calculate Options checksum too, if they are present. |
||
| 199 | if ( optionsLen > 0u ) |
||
| 200 | checksums[1] = ~CalcIPChecksum((BYTE*)options, optionsLen); |
||
| 201 | else |
||
| 202 | checksums[1] = 0; |
||
| 203 | |||
| 204 | CalcChecksum.Val = CalcIPChecksum((BYTE*)checksums, |
||
| 205 | 2 * sizeof(WORD)); |
||
| 206 | |||
| 207 | // Make sure that checksum is correct |
||
| 208 | if ( ReceivedChecksum.Val != CalcChecksum.Val ) |
||
| 209 | #endif |
||
| 210 | { |
||
| 211 | // Bad packet. The function caller will be notified by means of the FALSE |
||
| 212 | // return value and it should discard the packet. |
||
| 213 | return FALSE; |
||
| 214 | } |
||
| 215 | |||
| 216 | // Network to host conversion. |
||
| 217 | SwapIPHeader(&header); |
||
| 218 | |||
| 219 | // If caller is intrested, return destination IP address |
||
| 220 | // as seen in this IP header. |
||
| 221 | if ( localIP ) |
||
| 222 | localIP->Val = header.DestAddress.Val; |
||
| 223 | |||
| 224 | remote->IPAddr.Val = header.SourceAddress.Val; |
||
| 225 | *protocol = header.Protocol; |
||
| 226 | *len = header.TotalLength - IPHeaderLen; |
||
| 227 | |||
| 228 | return TRUE; |
||
| 229 | } |
||
| 230 | |||
| 231 | |||
| 232 | |||
| 233 | |||
| 234 | /********************************************************************* |
||
| 235 | * Function: WORD IPPutHeader(NODE_INFO *remote, |
||
| 236 | * BYTE protocol, |
||
| 237 | * WORD len) |
||
| 238 | * |
||
| 239 | * PreCondition: IPIsTxReady() == TRUE |
||
| 240 | * |
||
| 241 | * Input: *remote - Destination node address |
||
| 242 | * protocol - Current packet protocol |
||
| 243 | * len - Current packet data length |
||
| 244 | * |
||
| 245 | * Output: (WORD)0 |
||
| 246 | * |
||
| 247 | * Side Effects: None |
||
| 248 | * |
||
| 249 | * Note: Only one IP message can be transmitted at any |
||
| 250 | * time. |
||
| 251 | ********************************************************************/ |
||
| 252 | WORD IPPutHeader(NODE_INFO *remote, |
||
| 253 | BYTE protocol, |
||
| 254 | WORD len) |
||
| 255 | { |
||
| 256 | IP_HEADER header; |
||
| 257 | |||
| 258 | IPHeaderLen = sizeof(IP_HEADER); |
||
| 259 | |||
| 260 | header.VersionIHL = IP_VERSION | IP_IHL; |
||
| 261 | header.TypeOfService = IP_SERVICE; |
||
| 262 | header.TotalLength = sizeof(header) + len; |
||
| 263 | header.Identification = ++_Identifier; |
||
| 264 | header.FragmentInfo = 0; |
||
| 265 | header.TimeToLive = MY_IP_TTL; |
||
| 266 | header.Protocol = protocol; |
||
| 267 | header.HeaderChecksum = 0; |
||
| 268 | header.SourceAddress = AppConfig.MyIPAddr; |
||
| 269 | |||
| 270 | header.DestAddress.Val = remote->IPAddr.Val; |
||
| 271 | |||
| 272 | SwapIPHeader(&header); |
||
| 273 | |||
| 274 | header.HeaderChecksum = CalcIPChecksum((BYTE*)&header, sizeof(header)); |
||
| 275 | |||
| 276 | MACPutHeader(&remote->MACAddr, MAC_IP, (sizeof(header)+len)); |
||
| 277 | MACPutArray((BYTE*)&header, sizeof(header)); |
||
| 278 | |||
| 279 | return 0x0000; |
||
| 280 | |||
| 281 | } |
||
| 282 | |||
| 283 | /********************************************************************* |
||
| 284 | * Function: IPSetRxBuffer(WORD Offset) |
||
| 285 | * |
||
| 286 | * PreCondition: IPHeaderLen must have been intialized by |
||
| 287 | * IPGetHeader() or IPPutHeader() |
||
| 288 | * |
||
| 289 | * Input: Offset from beginning of IP data field |
||
| 290 | * |
||
| 291 | * Output: Next Read/Write access to receive buffer is |
||
| 292 | * set to Offset |
||
| 293 | * |
||
| 294 | * Side Effects: None |
||
| 295 | * |
||
| 296 | * Note: None |
||
| 297 | * |
||
| 298 | ********************************************************************/ |
||
| 299 | void IPSetRxBuffer(WORD Offset) |
||
| 300 | { |
||
| 301 | MACSetReadPtrInRx(Offset+IPHeaderLen); |
||
| 302 | } |
||
| 303 | |||
| 304 | |||
| 305 | |||
| 306 | static void SwapIPHeader(IP_HEADER* h) |
||
| 307 | { |
||
| 308 | h->TotalLength = swaps(h->TotalLength); |
||
| 309 | h->Identification = swaps(h->Identification); |
||
| 310 | h->HeaderChecksum = swaps(h->HeaderChecksum); |
||
| 311 | } |
Powered by WebSVN v2.8.3