Subversion Repositories HomeAutomation

Rev

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
}