IP.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00028 /*********************************************************************
00029  * Software License Agreement
00030  *
00031  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights 
00032  * reserved.
00033  *
00034  * Microchip licenses to you the right to use, modify, copy, and 
00035  * distribute: 
00036  * (i)  the Software when embedded on a Microchip microcontroller or 
00037  *      digital signal controller product ("Device") which is 
00038  *      integrated into Licensee's product; or
00039  * (ii) ONLY the Software driver source files ENC28J60.c and 
00040  *      ENC28J60.h ported to a non-Microchip device used in 
00041  *      conjunction with a Microchip ethernet controller for the 
00042  *      sole purpose of interfacing with the ethernet controller. 
00043  *
00044  * You should refer to the license agreement accompanying this 
00045  * Software for additional information regarding your rights and 
00046  * obligations.
00047  *
00048  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT 
00049  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT 
00050  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A 
00051  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL 
00052  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR 
00053  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF 
00054  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS 
00055  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE 
00056  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER 
00057  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT 
00058  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00059  *
00060  *
00061  * Author               Date    Comment
00062  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00063  * Nilesh Rajbharti     4/27/01 Original        (Rev 1.0)
00064  * Nilesh Rajbharti     2/9/02  Cleanup
00065  * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
00066  * Howard Schlunder     8/31/04 Beta Rev 0.9 (See version.log for detail)
00067  * Howard Schlunder     1/5/06  Improved DMA checksum efficiency
00068  * Darren Rook          9/21/06 Corrected IPHeaderLen not being 
00069  *                              initialized when NON_MCHP_MAC defined.
00070  ********************************************************************/
00071 #define __IP_C
00072 
00073 #include "TCPIP.h"
00074 
00075 // This is left shifted by 4.  Actual value is 0x04.
00076 #define IPv4                (0x40u)
00077 #define IP_VERSION          IPv4
00078 
00079 // IHL (Internet Header Length) is # of DWORDs in a header.
00080 // Since, we do not support options, our IP header length will be
00081 // minimum i.e. 20 bytes : IHL = 20 / 4 = 5.
00082 #define IP_IHL              (0x05)
00083 
00084 #define IP_SERVICE_NW_CTRL  (0x07)
00085 #define IP_SERVICE_IN_CTRL  (0x06)
00086 #define IP_SERVICE_ECP      (0x05)
00087 #define IP_SERVICE_OVR      (0x04)
00088 #define IP_SERVICE_FLASH    (0x03)
00089 #define IP_SERVICE_IMM      (0x02)
00090 #define IP_SERVICE_PRIOR    (0x01)
00091 #define IP_SERVICE_ROUTINE  (0x00)
00092 
00093 #define IP_SERVICE_N_DELAY  (0x00)
00094 #define IP_SERCICE_L_DELAY  (0x08)
00095 #define IP_SERVICE_N_THRPT  (0x00)
00096 #define IP_SERVICE_H_THRPT  (0x10)
00097 #define IP_SERVICE_N_RELIB  (0x00)
00098 #define IP_SERVICE_H_RELIB  (0x20)
00099 
00100 #define IP_SERVICE          (IP_SERVICE_ROUTINE | IP_SERVICE_N_DELAY)
00101 
00102 #define MY_IP_TTL           (255)  // Time-To-Live in hops
00103 
00104 
00105 
00106 
00107 static WORD _Identifier = 0;
00108 static BYTE IPHeaderLen;
00109 
00110 
00111 static void SwapIPHeader(IP_HEADER* h);
00112 
00113 
00114 
00115 
00116 /*********************************************************************
00117  * Function:        BOOL IPGetHeader( IP_ADDR    *localIP,
00118  *                                    NODE_INFO  *remote,
00119  *                                    BYTE        *Protocol,
00120  *                                    WORD        *len)
00121  *
00122  * PreCondition:    MACGetHeader() == TRUE
00123  *
00124  * Input:           localIP     - Local node IP Address as received
00125  *                                in current IP header.
00126  *                                If this information is not required
00127  *                                caller may pass NULL value.
00128  *                  remote      - Remote node info
00129  *                  Protocol    - Current packet protocol
00130  *                  len         - Current packet data length
00131  *
00132  * Output:          TRUE, if valid packet was received
00133  *                  FALSE otherwise
00134  *
00135  * Side Effects:    None
00136  *
00137  * Note:            Only one IP message can be received.
00138  *                  Caller may not transmit and receive a message
00139  *                  at the same time.
00140  *
00141  ********************************************************************/
00142 BOOL IPGetHeader(IP_ADDR *localIP,
00143                  NODE_INFO *remote,
00144                  BYTE *protocol,
00145                  WORD *len)
00146 {
00147     WORD_VAL    CalcChecksum;
00148     IP_HEADER   header;
00149 
00150 #if defined(NON_MCHP_MAC)
00151     WORD_VAL    ReceivedChecksum;
00152     WORD        checksums[2];
00153     BYTE        optionsLen;
00154     #define MAX_OPTIONS_LEN     (40)            // As per RFC 791.
00155     BYTE        options[MAX_OPTIONS_LEN];
00156 #endif
00157 
00158     // Read IP header.
00159     MACGetArray((BYTE*)&header, sizeof(header));
00160 
00161     // Make sure that this is an IPv4 packet.
00162     if ( (header.VersionIHL & 0xf0) != IP_VERSION )
00163         return FALSE;
00164 
00165     // Throw this packet away if it is a fragment.  
00166     // We don't have enough RAM for IP fragment reconstruction.
00167     if(header.FragmentInfo & 0xFF1F)
00168         return FALSE;
00169 
00170     IPHeaderLen = (header.VersionIHL & 0x0f) << 2;
00171 
00172 #if !defined(NON_MCHP_MAC)
00173     // Validate the IP header.  If it is correct, the checksum 
00174     // will come out to 0x0000 (because the header contains a 
00175     // precomputed checksum).  A corrupt header will have a 
00176     // nonzero checksum.
00177     CalcChecksum.Val = MACCalcRxChecksum(0, IPHeaderLen);
00178 
00179     // Seek to the end of the IP header
00180     MACSetReadPtrInRx(IPHeaderLen);
00181 
00182     if(CalcChecksum.Val)
00183 #else
00184     // Calculate options length in this header, if there is any.
00185     // IHL is in terms of numbers of 32-bit DWORDs; i.e. actual
00186     // length is 4 times IHL.
00187     optionsLen = IPHeaderLen - sizeof(header);
00188 
00189     // If there is any option(s), read it so that we can include them
00190     // in checksum calculation.
00191     if ( optionsLen > MAX_OPTIONS_LEN )
00192         return FALSE;
00193 
00194     if ( optionsLen > 0 )
00195         MACGetArray(options, optionsLen);
00196 
00197     // Save header checksum; clear it and recalculate it ourselves.
00198     ReceivedChecksum.Val = header.HeaderChecksum;
00199     header.HeaderChecksum = 0;
00200 
00201     // Calculate checksum of header including options bytes.
00202     checksums[0] = ~CalcIPChecksum((BYTE*)&header, sizeof(header));
00203 
00204     // Calculate Options checksum too, if they are present.
00205     if ( optionsLen > 0 )
00206         checksums[1] = ~CalcIPChecksum((BYTE*)options, optionsLen);
00207     else
00208         checksums[1] = 0;
00209 
00210     CalcChecksum.Val  = CalcIPChecksum((BYTE*)checksums,
00211                                             2 * sizeof(WORD));
00212 
00213     // Make sure that checksum is correct
00214     if ( ReceivedChecksum.Val != CalcChecksum.Val )
00215 #endif
00216     {
00217         // Bad packet. The function caller will be notified by means of the FALSE 
00218         // return value and it should discard the packet.
00219         return FALSE;
00220     }
00221 
00222     // Network to host conversion.
00223     SwapIPHeader(&header);
00224 
00225     // If caller is interested, return destination IP address
00226     // as seen in this IP header.
00227     if (localIP)
00228         localIP->Val    = header.DestAddress.Val;
00229 
00230     remote->IPAddr.Val  = header.SourceAddress.Val;
00231     *protocol           = header.Protocol;
00232     *len                = header.TotalLength - IPHeaderLen;
00233 
00234     return TRUE;
00235 }
00236 
00237 
00238 
00239 
00240 /*********************************************************************
00241  * Function: WORD IPPutHeader(NODE_INFO *remote,
00242  *                            BYTE protocol,
00243  *                            WORD len)
00244  *
00245  * PreCondition:    IPIsTxReady() == TRUE
00246  *
00247  * Input:           *remote     - Destination node address
00248  *                  protocol    - Current packet protocol
00249  *                  len         - Current packet data length
00250  *
00251  * Output:          (WORD)0
00252  *
00253  * Side Effects:    None
00254  *
00255  * Note:            Only one IP message can be transmitted at any
00256  *                  time.
00257  ********************************************************************/
00258 WORD IPPutHeader(NODE_INFO *remote,
00259                  BYTE protocol,
00260                  WORD len)
00261 {
00262     IP_HEADER   header;
00263     
00264     IPHeaderLen = sizeof(IP_HEADER);
00265 
00266     header.VersionIHL       = IP_VERSION | IP_IHL;
00267     header.TypeOfService    = IP_SERVICE;
00268     header.TotalLength      = sizeof(header) + len;
00269     header.Identification   = ++_Identifier;
00270     header.FragmentInfo     = 0;
00271     header.TimeToLive       = MY_IP_TTL;
00272     header.Protocol         = protocol;
00273     header.HeaderChecksum   = 0;
00274 // MODIFIX: Use the eWicht structure sIPConfig instead of AppConfig
00275     header.SourceAddress    = sIPConfig.MyIPAddr;   
00276 
00277     header.DestAddress.Val = remote->IPAddr.Val;
00278 
00279     SwapIPHeader(&header);
00280 
00281     header.HeaderChecksum   = CalcIPChecksum((BYTE*)&header, sizeof(header));
00282 
00283     MACPutHeader(&remote->MACAddr, MAC_IP, (sizeof(header)+len));
00284     MACPutArray((BYTE*)&header, sizeof(header));
00285 
00286     return 0x0000;
00287 
00288 }
00289 
00290 /*********************************************************************
00291  * Function:        IPSetRxBuffer(WORD Offset)
00292  *
00293  * PreCondition:    IPHeaderLen must have been intialized by 
00294  *                  IPGetHeader() or IPPutHeader()
00295  *
00296  * Input:           Offset from beginning of IP data field
00297  *
00298  * Output:          Next Read/Write access to receive buffer is
00299  *                  set to Offset 
00300  *
00301  * Side Effects:    None
00302  *
00303  * Note:            None
00304  *
00305  ********************************************************************/
00306 void IPSetRxBuffer(WORD Offset) 
00307 {
00308     MACSetReadPtrInRx(Offset+IPHeaderLen);
00309 }
00310 
00311 
00312 
00313 static void SwapIPHeader(IP_HEADER* h)
00314 {
00315     h->TotalLength      = swaps(h->TotalLength);
00316     h->Identification   = swaps(h->Identification);
00317     h->HeaderChecksum   = swaps(h->HeaderChecksum);
00318 }
00319 
00320 // MODIFIX: Added the following functions.
00321 DWORD IPConvertSubnetToMask(BYTE Subnet)
00322 {
00323     int i = 0;
00324     DWORD mask = 0x80000000ul;
00325     for (i = 1; i < Subnet; i++)
00326     {
00327         mask |= mask >> 1;  
00328     }
00329 
00330     mask = swapl(mask); 
00331     return mask;
00332 }
00333 
00334 BYTE IPConvertMaskToSubnet(BYTE * MaskArray)
00335 {
00336     BYTE subnet = 0;
00337 
00338     DWORD mask = swapl(*((DWORD *)MaskArray));
00339     while(mask & 0x80000000ul)
00340     {
00341         mask = mask << 1;
00342         subnet++;
00343     }
00344 
00345     return subnet;
00346 }
00347 
00348 // MODIFIX: END

Generated on Sun Nov 27 20:02:38 2011 for eWicht by  doxygen 1.5.5