📄 ip.c
字号:
#include <string.h>
#include "tcptask.h"
// This is left shifted by 4. Actual value is 0x04.
#define IPv4 (0x40)
#define IP_VERSION IPv4
/*
* IHL (Internet Header Length) is # of DWORDs in a header.
* Since, we do not support options, our IP header length will be
* minimum i.e. 20 bytes : IHL = 20 / 4 = 5.
*/
#define IP_IHL (0x05)
#define IP_SERVICE_NW_CTRL (0x07)
#define IP_SERVICE_IN_CTRL (0x06)
#define IP_SERVICE_ECP (0x05)
#define IP_SERVICE_OVR (0x04)
#define IP_SERVICE_FLASH (0x03)
#define IP_SERVICE_IMM (0x02)
#define IP_SERVICE_PRIOR (0x01)
#define IP_SERVICE_ROUTINE (0x00)
#define IP_SERVICE_N_DELAY (0x00)
#define IP_SERCICE_L_DELAY (0x08)
#define IP_SERVICE_N_THRPT (0x00)
#define IP_SERVICE_H_THRPT (0x10)
#define IP_SERVICE_N_RELIB (0x00)
#define IP_SERVICE_H_RELIB (0x20)
#define IP_SERVICE (IP_SERVICE_ROUTINE | IP_SERVICE_N_DELAY)
#define MY_IP_TTL (100) /* Time-To-Live in Seconds */
static WORD _Identifier = 0;
static void SwapIPHeader(IP_HEADER* h);
/*********************************************************************
* Function: BOOL IPGetHeader( IP_ADDR *localIP,
* NODE_INFO *remote,
* BYTE *Protocol,
* WORD *len)
*
* PreCondition: MACGetHeader() == TRUE
*
* Input: localIP - Local node IP Address as received
* in current IP header.
* If this information is not required
* caller may pass NULL value.
* remote - Remote node info
* Protocol - Current packet protocol
* len - Current packet data length
*
* Output: TRUE, if valid packet was received
* FALSE otherwise
*
* Side Effects: None
*
* Note: Only one IP message can be received.
* Caller may not transmit and receive a message
* at the same time.
*
********************************************************************/
BOOL IPGetHeader(IP_ADDR *localIP,
NODE_INFO *remote,
BYTE *protocol,
WORD *len)
{
WORD_VAL ReceivedChecksum;
WORD_VAL CalcChecksum;
WORD checksums[2];
IP_HEADER header;
BYTE optionsLen;
char i;
BYTE *c;
#define MAX_OPTIONS_LEN (20) // As per RFC 791.
BYTE options[MAX_OPTIONS_LEN];
// Read IP header.
MACGetArray((BYTE*)&header, sizeof(header));
c=(BYTE*)&header;
for(i=0;i<20;i++)
{
while(!TXSTAbits.TRMT);
putcUSART(*(c++));
}
// Make sure that this IPv4 packet.
if ( (header.VersionIHL & 0xf0) != IP_VERSION )
{
goto IPGetHeader_Discard;
}
/*
* Calculate options length in this header, if there is any.
* IHL is in terms of numbers of 32-bit DWORDs; i.e. actual
* length is 4 times IHL.
*/
optionsLen = ((header.VersionIHL & 0x0f) << 2) - sizeof(header);
/*
* If there is any option(s), read it so that we can include them
* in checksum calculation.
*/
if ( optionsLen > MAX_OPTIONS_LEN )
{
goto IPGetHeader_Discard;
}
if ( optionsLen > 0 )
MACGetArray(options, optionsLen);
// Save header checksum; clear it and recalculate it ourselves.
ReceivedChecksum.Val = header.HeaderChecksum;
header.HeaderChecksum = 0;
// Calculate checksum of header including options bytes.
checksums[0] = ~CalcIPChecksum((BYTE*)&header, sizeof(header));
// Calculate Options checksum too, if they are present.
if ( optionsLen > 0 )
checksums[1] = ~CalcIPChecksum((BYTE*)options, optionsLen);
else
checksums[1] = 0;
CalcChecksum.Val = CalcIPChecksum((BYTE*)checksums,
2 * sizeof(WORD));
// Network to host conversion.
SwapIPHeader(&header);
// Make sure that checksum is correct and IP version is supported.
if ( ReceivedChecksum.Val != CalcChecksum.Val ||
(header.VersionIHL & 0xf0) != IP_VERSION )
{
// Bad/Unknown packet. Discard it.
goto IPGetHeader_Discard;
}
/*
* If caller is intrested, return destination IP address
* as seen in this IP header.
*/
if ( localIP )
localIP->Val = header.DestAddress.Val;
remote->IPAddr.Val = header.SourceAddress.Val;
*protocol = header.Protocol;
*len = header.TotalLength - optionsLen -
sizeof(header);
return TRUE;
IPGetHeader_Discard:
MACDiscardRx();
return FALSE;
}
/*********************************************************************
* Function: WORD IPPutHeader( IP_ADDR *Dest,
* BYTE Protocol,
* WORD Identifier,
* WORD DataLen)
*
* PreCondition: IPIsTxReady() == TRUE
*
* Input: Src - Destination node address
* Protocol - Current packet protocol
* Identifier - Current packet identifier
* DataLen - Current packet data length
*
* Output: Handle to current packet - For use by
* IPSendByte() function.
*
* Side Effects: None
*
* Note: Only one IP message can be transmitted at any
* time.
* Caller may not transmit and receive a message
* at the same time.
*
********************************************************************/
WORD IPPutHeader(NODE_INFO *remote,
BYTE protocol,
WORD len)
{
IP_HEADER header;
header.VersionIHL = IP_VERSION | IP_IHL;
header.TypeOfService = IP_SERVICE;
header.TotalLength = sizeof(header) + len;
header.Identification = ++_Identifier;
header.FragmentInfo = 0;
header.TimeToLive = MY_IP_TTL;
header.Protocol = protocol;
header.HeaderChecksum = 0;
header.SourceAddress.v[0] = MY_IP_BYTE1;
header.SourceAddress.v[1] = MY_IP_BYTE2;
header.SourceAddress.v[2] = MY_IP_BYTE3;
header.SourceAddress.v[3] = MY_IP_BYTE4;
header.DestAddress.Val = remote->IPAddr.Val;
SwapIPHeader(&header);
header.HeaderChecksum = CalcIPChecksum((BYTE*)&header,
sizeof(header));
MACPutHeader(&remote->MACAddr, MAC_IP, (sizeof(header)+len));
MACPutArray((BYTE*)&header, sizeof(header));
return 0x0;
}
static void SwapIPHeader(IP_HEADER* h)
{
h->TotalLength = swaps(h->TotalLength);
h->Identification = swaps(h->Identification);
h->HeaderChecksum = swaps(h->HeaderChecksum);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -