📄 ip.c
字号:
/**---------------------版权 (c)----------------------------------------------------------***
*** 作者:颜章健 ***
*** 邮件:jenkinyan@163.com ***
*** ***
***---------------------File Info---------------------------------------------------------***
*** 创 建 人: 颜章健 ***
*** 创建日期: 2008-03-14 ***
*** 创建版本: ***
*** 文件描述: ***
***---------------------------------------------------------------------------------------***
*** 修 订 人: ***
*** 修订日期: ***
*** 修订版本: ***
*** 修订描述: ***
***---------------------------------------------------------------------------------------**/
#include "config.h"
NET_LAYER NetLayer;
#if MAX_IP_PACKETS > 0
static uint8 IpPacketBuffer[MAX_IP_PACKETS][MAX_IP_PACKET_LENGTH]; // IP包重组缓冲区
static uint16 IpPacketLength[MAX_IP_PACKETS]; // IP包已经获取的有效数据长度
static uint8 IpPacketStatus[MAX_IP_PACKETS]; // IP包状态
#endif
static void IpPacketProcess(uint8 *Rxd);
/********************************************************************************************
*** 函数名称:
*** 函数描述:
*** 入 口:
*** 出 口:
********************************************************************************************/
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);
}
/********************************************************************************************
*** 函数名称: IpReOrgProcess
*** 函数描述: 对已经被分片了的数据包进行重组
*** 入 口: IP包指针
*** 出 口: 完成重组的数据包缓冲区下标,如果为"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;
// 检索该分片是否已经申请了缓冲区
for(i=0; i<MAX_IP_PACKETS; i++)
{
if( IpPacketStatus[i] == IPPS_BUSY && // 正在等待中的缓冲区
(InetMemCmp(Rxd+4, IpPacketBuffer[i]+4, 2)) && // 具有相同标识
(InetMemCmp(Rxd+12,IpPacketBuffer[i]+12,4)) ) // 具有相同源IP地址
{
HeadLength = ((*Rxd) & 0x0f) << 2; // 计算头部长度
ptr = Rxd + 2; // 指向总长度字段
value16 = *(uint16 *)ptr; // 获取总长度
DataLength = value16 - HeadLength; // 计算有效数据长度
IpPacketLength[i] += DataLength; // 记录有效数据长度
ptr = Rxd + 6; // 指向标志及片偏移字段
value16 = *(uint16 *)ptr; // 读取标志及片偏移字段
if((value16 & 0xc000) == 0) // 分片是数据包的最后分片
{
redy = 1; // 设置重组完成标志
}
value16 &= 0x1fff; // 计算片偏移量
pWrite = IpPacketBuffer[i] + value16; // 写指针指向缓冲区对应偏移量地址
ptr = Rxd + HeadLength; // 读指针指向分片的数据段
for(j=0; j<DataLength; j++) // 搬运数据到缓冲区中
{
*pWrite = *ptr;
pWrite++;
ptr++;
}
if(redy == 1) // 已经完成数据包重组
{
IpPacketStatus[i] = IPPS_REDY; // 设置重组完成标志
return i;
}
}
}
// 分片未申请有缓冲区,开始申请缓冲区
for(i=0; i<MAX_IP_PACKETS; i++) // 检索未用缓冲区
{
if(IpPacketStatus[i] == IPPS_DUMMY) // 检索到空缓冲区
{
IpPacketStatus[i] = IPPS_BUSY; // 注册缓冲区
IpPacketLength[i] = 0; // 初始化缓冲区长度
ptr = Rxd;
HeadLength = ((*ptr) & 0x0f) << 2; // 计算头部长度
pWrite = IpPacketBuffer[i];
for(i=0; i<20; i++) // 保存头部(丢弃选项部分)
{
*pWrite = *ptr;
pWrite++;
ptr++;
}
ptr = Rxd + 2; // 指向总长度字段
value16 = *(uint16 *)ptr; // 获取总长度
DataLength = value16 - HeadLength; // 计算有效数据长度
IpPacketLength[i] += DataLength; // 记录有效数据长度
ptr = Rxd + 6; // 指向标志及片偏移字段
value16 = (*(uint16 *)ptr) & 0x1fff; // 计算片偏移量
pWrite = IpPacketBuffer[i] + value16; // 写指针指向缓冲区对应偏移量地址
ptr = Rxd + HeadLength; // 读指针指向分片的数据段
for(j=0; j<DataLength; j++) // 搬运数据到缓冲区中
{
*pWrite = *ptr;
pWrite++;
ptr++;
}
}
}
return 0xff;
}
#endif
/********************************************************************************************
*** 函数名称: IpPacketProcess
*** 函数描述: IP包解析处理
*** 入 口: Rxd:IP包指针,指向完整IP包第一个字节
*** 出 口: 无
********************************************************************************************/
static void IpPacketProcess(uint8 *Rxd)
{
uint8 *ptr;
uint8 value8;
NetLayer.Rxd = Rxd;
ptr = Rxd + 9; // 获取协议字段
value8 = *ptr;
switch(value8)
{
case IPF_ICMP: // ICMP处理
IcmpProcess();
break;
case IPF_TCP: // TCP处理
if(InetMemCmp(Rxd+16,LinkLayer.Config.Ip,4))// 数据包目的地址为本机地址
{
TcpReceiveTask();
}
break;
case IPF_UDP: // UDP处理
if(InetMemCmp(Rxd+16,LinkLayer.Config.Ip,4))// 数据包目的地址为本机地址
{
UdpReceiveTask();
}
break;
default:
//_printf("Receive unknow ip packet\r\n");
break;
}
}
/********************************************************************************************
*** 函数名称: IpReceiveTask
*** 函数描述: 处理从数据链路层上来的数据包
*** 入 口: 无
*** 出 口: 无
********************************************************************************************/
//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; // 处理版本及头部长度
if((value8 >> 4) != 4) return; // 版本不支持
ptr = NetLayer.Rxd + 2; // 指向总长字段
value16 = *ptr++;
value16 <<= 8;
value16 |= ((*ptr) & 0xff);
if(value16 > MAX_IP_PACKET_LENGTH) return; // 总长过大
ptr = NetLayer.Rxd + 6; // 指向标志及片偏移
value16 = *ptr++;
value16 <<= 8;
value16 |= ((*ptr) & 0xff);
value16 &= 0x3fff;
if(value16) // IP包已经被分片
{
#if MAX_IP_PACKETS > 0
//_printf("Ip packet is reorgnizing...\r\n");
value8 = IpReOrgProcess(NetLayer.Rxd); // 重组数据包
if(value8 != 0xff) // 重组完成
{
IpPacketProcess(IpPacketBuffer[value8]); // 处理数据包
IpPacketStatus[value8] = IPPS_DUMMY; // 释放缓冲区
}
#else
return;
#endif
}
else // 数据包未被分片,直接处理
{
IpPacketProcess(NetLayer.Rxd);
}
}
/********************************************************************************************
*** 函数名称:
*** 函数描述:
*** 入 口:
*** 出 口:
********************************************************************************************/
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
}
/********************************************************************************************
*** 文件结束 ***
********************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -