?? ip.c
字號(hào):
/**---------------------版權(quán) (c)----------------------------------------------------------***
*** 作者:顏章健 ***
*** 郵件:jenkinyan@163.com ***
*** ***
***---------------------File Info---------------------------------------------------------***
*** 創(chuàng) 建 人: 顏章健 ***
*** 創(chuàng)建日期: 2008-03-14 ***
*** 創(chuàng)建版本: ***
*** 文件描述: ***
***---------------------------------------------------------------------------------------***
*** 修 訂 人: ***
*** 修訂日期: ***
*** 修訂版本: ***
*** 修訂描述: ***
***---------------------------------------------------------------------------------------**/
#include "config.h"
NET_LAYER NetLayer;
#if MAX_IP_PACKETS > 0
static uint8 IpPacketBuffer[MAX_IP_PACKETS][MAX_IP_PACKET_LENGTH]; // IP包重組緩沖區(qū)
static uint16 IpPacketLength[MAX_IP_PACKETS]; // IP包已經(jīng)獲取的有效數(shù)據(jù)長(zhǎng)度
static uint8 IpPacketStatus[MAX_IP_PACKETS]; // IP包狀態(tài)
#endif
static void IpPacketProcess(uint8 *Rxd);
/********************************************************************************************
*** 函數(shù)名稱:
*** 函數(shù)描述:
*** 入 口:
*** 出 口:
********************************************************************************************/
void IpPutPacket(uint8 Protocol, uint8 *DestIp, NET_PKT *Packet)
{
static uint16 Id=0;
uint8 i;
uint16 len = 20;
uint16 crc;
NET_PKT *pkt;
NET_PKT packet;
IP_HEAD head;
pkt = Packet;
while(pkt != NULL)
{
len += pkt->Length;
pkt = pkt->Next;
}
head.s.VerAndHeadLen = 0x45;
head.s.Service = 0x00;
//head.s.TotalLen = len;
head.b[2] = len >> 8;
head.b[3] = (uint8)len;
//head.s.Id = Id++;
head.b[4] = Id >> 8;
head.b[5] = (uint8)Id;
Id++;
//head.s.FlagAndOffset = 0x0000;
head.b[6] = 0x00;
head.b[7] = 0x00;
head.s.TTL = 255;
head.s.Protocol = Protocol;
//head.s.CRC = 0x0000;
head.b[10] = 0x00;
head.b[11] = 0x00;
for(i=0; i<4; i++)
{
head.s.SourceIp[i] = LinkLayer.Config.Ip[i];
head.s.DestIp[i] = *DestIp++;
}
crc = 0xffff - InetCheckSum(head.b,20);
head.b[11] = crc >> 8;
head.b[10] = (uint8)crc;
packet.Data = head.b;
packet.Length = 20;
packet.Next = Packet;
LinkLayer.PutFrame(PPPF_IP,&packet);
}
/********************************************************************************************
*** 函數(shù)名稱: IpReOrgProcess
*** 函數(shù)描述: 對(duì)已經(jīng)被分片了的數(shù)據(jù)包進(jìn)行重組
*** 入 口: IP包指針
*** 出 口: 完成重組的數(shù)據(jù)包緩沖區(qū)下標(biāo),如果為"0xff",則表明未重組完成
********************************************************************************************/
#if MAX_IP_PACKETS > 0
uint8 IpReOrgProcess(uint8 *Rxd)
{
uint8 *ptr,*pWrite;
uint8 i;
uint8 redy = 0;
uint8 HeadLength;
uint16 value16;
uint16 j,DataLength;
// 檢索該分片是否已經(jīng)申請(qǐng)了緩沖區(qū)
for(i=0; i<MAX_IP_PACKETS; i++)
{
if( IpPacketStatus[i] == IPPS_BUSY && // 正在等待中的緩沖區(qū)
(InetMemCmp(Rxd+4, IpPacketBuffer[i]+4, 2)) && // 具有相同標(biāo)識(shí)
(InetMemCmp(Rxd+12,IpPacketBuffer[i]+12,4)) ) // 具有相同源IP地址
{
HeadLength = ((*Rxd) & 0x0f) << 2; // 計(jì)算頭部長(zhǎng)度
ptr = Rxd + 2; // 指向總長(zhǎng)度字段
value16 = *(uint16 *)ptr; // 獲取總長(zhǎng)度
DataLength = value16 - HeadLength; // 計(jì)算有效數(shù)據(jù)長(zhǎng)度
IpPacketLength[i] += DataLength; // 記錄有效數(shù)據(jù)長(zhǎng)度
ptr = Rxd + 6; // 指向標(biāo)志及片偏移字段
value16 = *(uint16 *)ptr; // 讀取標(biāo)志及片偏移字段
if((value16 & 0xc000) == 0) // 分片是數(shù)據(jù)包的最后分片
{
redy = 1; // 設(shè)置重組完成標(biāo)志
}
value16 &= 0x1fff; // 計(jì)算片偏移量
pWrite = IpPacketBuffer[i] + value16; // 寫(xiě)指針指向緩沖區(qū)對(duì)應(yīng)偏移量地址
ptr = Rxd + HeadLength; // 讀指針指向分片的數(shù)據(jù)段
for(j=0; j<DataLength; j++) // 搬運(yùn)數(shù)據(jù)到緩沖區(qū)中
{
*pWrite = *ptr;
pWrite++;
ptr++;
}
if(redy == 1) // 已經(jīng)完成數(shù)據(jù)包重組
{
IpPacketStatus[i] = IPPS_REDY; // 設(shè)置重組完成標(biāo)志
return i;
}
}
}
// 分片未申請(qǐng)有緩沖區(qū),開(kāi)始申請(qǐng)緩沖區(qū)
for(i=0; i<MAX_IP_PACKETS; i++) // 檢索未用緩沖區(qū)
{
if(IpPacketStatus[i] == IPPS_DUMMY) // 檢索到空緩沖區(qū)
{
IpPacketStatus[i] = IPPS_BUSY; // 注冊(cè)緩沖區(qū)
IpPacketLength[i] = 0; // 初始化緩沖區(qū)長(zhǎng)度
ptr = Rxd;
HeadLength = ((*ptr) & 0x0f) << 2; // 計(jì)算頭部長(zhǎng)度
pWrite = IpPacketBuffer[i];
for(i=0; i<20; i++) // 保存頭部(丟棄選項(xiàng)部分)
{
*pWrite = *ptr;
pWrite++;
ptr++;
}
ptr = Rxd + 2; // 指向總長(zhǎng)度字段
value16 = *(uint16 *)ptr; // 獲取總長(zhǎng)度
DataLength = value16 - HeadLength; // 計(jì)算有效數(shù)據(jù)長(zhǎng)度
IpPacketLength[i] += DataLength; // 記錄有效數(shù)據(jù)長(zhǎng)度
ptr = Rxd + 6; // 指向標(biāo)志及片偏移字段
value16 = (*(uint16 *)ptr) & 0x1fff; // 計(jì)算片偏移量
pWrite = IpPacketBuffer[i] + value16; // 寫(xiě)指針指向緩沖區(qū)對(duì)應(yīng)偏移量地址
ptr = Rxd + HeadLength; // 讀指針指向分片的數(shù)據(jù)段
for(j=0; j<DataLength; j++) // 搬運(yùn)數(shù)據(jù)到緩沖區(qū)中
{
*pWrite = *ptr;
pWrite++;
ptr++;
}
}
}
return 0xff;
}
#endif
/********************************************************************************************
*** 函數(shù)名稱: IpPacketProcess
*** 函數(shù)描述: IP包解析處理
*** 入 口: Rxd:IP包指針,指向完整IP包第一個(gè)字節(jié)
*** 出 口: 無(wú)
********************************************************************************************/
static void IpPacketProcess(uint8 *Rxd)
{
uint8 *ptr;
uint8 value8;
NetLayer.Rxd = Rxd;
ptr = Rxd + 9; // 獲取協(xié)議字段
value8 = *ptr;
switch(value8)
{
case IPF_ICMP: // ICMP處理
IcmpProcess();
break;
case IPF_TCP: // TCP處理
if(InetMemCmp(Rxd+16,LinkLayer.Config.Ip,4))// 數(shù)據(jù)包目的地址為本機(jī)地址
{
TcpReceiveTask();
}
break;
case IPF_UDP: // UDP處理
if(InetMemCmp(Rxd+16,LinkLayer.Config.Ip,4))// 數(shù)據(jù)包目的地址為本機(jī)地址
{
UdpReceiveTask();
}
break;
default:
//_printf("Receive unknow ip packet\r\n");
break;
}
}
/********************************************************************************************
*** 函數(shù)名稱: IpReceiveTask
*** 函數(shù)描述: 處理從數(shù)據(jù)鏈路層上來(lái)的數(shù)據(jù)包
*** 入 口: 無(wú)
*** 出 口: 無(wú)
********************************************************************************************/
//void IpReceiveTask(void)
void IpReceiveTask(uint8 *Rxd, uint16 Rxl) // changed by Yan Zhangjian @ 2008-04-10
{
uint8 *ptr;
uint8 value8;
uint16 value16;
NetLayer.Rxd = Rxd; // added by Yan Zhangjian @ 2008-04-10
NetLayer.Rxl = Rxl; // added by Yan Zhangjian @ 2008-04-10
if(NetLayer.Rxl < 20) return;
value8 = *NetLayer.Rxd; // 處理版本及頭部長(zhǎng)度
if((value8 >> 4) != 4) return; // 版本不支持
ptr = NetLayer.Rxd + 2; // 指向總長(zhǎng)字段
value16 = *ptr++;
value16 <<= 8;
value16 |= ((*ptr) & 0xff);
if(value16 > MAX_IP_PACKET_LENGTH) return; // 總長(zhǎng)過(guò)大
ptr = NetLayer.Rxd + 6; // 指向標(biāo)志及片偏移
value16 = *ptr++;
value16 <<= 8;
value16 |= ((*ptr) & 0xff);
value16 &= 0x3fff;
if(value16) // IP包已經(jīng)被分片
{
#if MAX_IP_PACKETS > 0
//_printf("Ip packet is reorgnizing...\r\n");
value8 = IpReOrgProcess(NetLayer.Rxd); // 重組數(shù)據(jù)包
if(value8 != 0xff) // 重組完成
{
IpPacketProcess(IpPacketBuffer[value8]); // 處理數(shù)據(jù)包
IpPacketStatus[value8] = IPPS_DUMMY; // 釋放緩沖區(qū)
}
#else
return;
#endif
}
else // 數(shù)據(jù)包未被分片,直接處理
{
IpPacketProcess(NetLayer.Rxd);
}
}
/********************************************************************************************
*** 函數(shù)名稱:
*** 函數(shù)描述:
*** 入 口:
*** 出 口:
********************************************************************************************/
void NetLayerInit(void)
{
if(LinkLayer.Config.MRU != 0)
{
NetLayer.MTU = LinkLayer.Config.MRU;
}
else
{
NetLayer.MTU = 1500;
}
NetLayer.Rxd = NULL;
NetLayer.Rxl = 0;
NetLayer.SendPacket = IpPutPacket;
LinkLayer.Hook = IpReceiveTask; // added by Yan Zhangjian @ 2008-04-10
}
/********************************************************************************************
*** 文件結(jié)束 ***
********************************************************************************************/
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -