📄 udp.c
字号:
}
// 计算剩余的数据
for(ucLoop = 0; ucLoop < ucDataLen; ucLoop++)
{
ulCheckSum += *pusPointer;
pusPointer++;
}
// 数据是单数还要将最后一个数据加上,低8位补零
if(usDataLen & 0x0001)
{
ulCheckSum += (*pusPointer & 0xff00);
}
// 加上进位部分
ulCheckSum = (ulCheckSum >> 16) + (ulCheckSum & 0x0000ffff);
// 可能再次进位,再加上进位部分,之后不可能再进位
ulCheckSum += (ulCheckSum >> 16);
usRealDataLen = (UWORK16)ulCheckSum;
usRealDataLen = (~usRealDataLen);
return usRealDataLen;
}
/*********************************************************************
函数名: void ArpRequest(UWORK8 *pucaIP)
功能: ARP请求
输入: ARP请求需要
输出: 组ARP请求包
返回: None
日期: 2004/12/19
修改: 2006/6/01
*********************************************************************/
void ArpRequest(UWORK8 *pucaIP)
{ // 以太网头
memset(&MAC_Remote_buf[0],0xff,MAC_LEN); // 发广播包
MAC_Remote_buf[12] = 0x08;
MAC_Remote_buf[13] = 0x06;
ArpRequestFormat.usOPER = OPER_REQUEST; // ARP请求
memcpy(&ArpRequestFormat.ucaTPA[0],pucaIP,IP_LEN); // 目的IP
memcpy(&ArpRequestFormat.ucaSPA[0],&IPAddress_buf[0],IP_LEN); // 源IP
memcpy(&NetSend_buf[0],&ArpRequestFormat,sizeof(ArpRequestFormat));
SendEthernetPacket(28);
if(IPConflitTestFlag) // IP冲突测试
{
StartTimer(5,501); // 启动IP冲突超时
}
}
/*********************************************************************
函数名: void ArpProcess(void)
功能: ARP应答,因为是接收一帧处理一帧,不用返回成功失败
输入: 接收的帧是ARP帧
输出: 回应ARP查询
返回: None
日期: 2004/12/11
*********************************************************************/
void ArpProcess(void)
{
xdata ST_ARP_FORMAT *pArpRcv;
UWORK8 ucLoop;
pArpRcv = (ST_ARP_FORMAT *)&gstaRevEthernet.ucaPacket[0]; // 指向ARP数据包内容
if((HTYPE == pArpRcv->usHTYPE) && (PTYPE == pArpRcv->usPTYPE) // 验证是否是以太网ARP
&&(HLEN == pArpRcv->ucHLEN) && (PLEN == pArpRcv->ucPLEN))
{
if((0 == memcmp(&pArpRcv->ucaSHA[0],&NetParameter.MAC_Local_buf[0],MAC_LEN)) //发送端的IP或MAC与本地IP或MAC相同则表示有冲突
|| (0 == memcmp(&pArpRcv->ucaSPA[0],&IPAddress_buf[0],IP_LEN)))
{
IPOrMacConfiltFlag = TRUE;
ARPFinishFlag = FALSE; // 清ARP完成标志
StopArpCounter(); // 检测到冲突,停止ARP相关计数器
StartTimer(12,400); // 4秒种后再次检测
}
switch(pArpRcv->usOPER)
{
case OPER_REQUEST: // 收到ARP请求帧
memcpy(&ArpAnswerFormat.ucaTHA[0],&pArpRcv->ucaSHA[0],MAC_LEN); // ARP应答
memcpy(&ArpAnswerFormat.ucaTPA[0],&pArpRcv->ucaSPA[0],IP_LEN);
memcpy(&ArpAnswerFormat.ucaSPA[0],&IPAddress_buf[0],IP_LEN);
memcpy(&NetSend_buf[0],&ArpAnswerFormat,sizeof(ArpAnswerFormat));
memcpy(&MAC_Remote_buf[0],&pArpRcv->ucaSHA[0],MAC_LEN);
MAC_Remote_buf[12] = 0x08;
MAC_Remote_buf[13] = 0x06;
SendEthernetPacket(28);
break;
case OPER_APLY: // 收到ARP应答帧
for(ucLoop = 0; ucLoop < IpModeNum; ucLoop++)
{
if(0 == memcmp(&ArpCache_Buf[ucLoop].ucaArpIp[0],&pArpRcv->ucaSPA[0],IP_LEN))
{
memcpy(&ArpCache_Buf[ucLoop].ucaMAC[0],&pArpRcv->ucaSHA[0],MAC_LEN);
ARPFinishFlag = TRUE; // 置ARP完成标志
if('r' != ArpCache_Buf[ucLoop].ucStatus)
{
ArpCache_Buf[ucLoop].ucStatus = 'r';
}
else // 此时应该是老化阶段,停止了定时器6,需要打开定时器4来启动定时器7
{
StopTimer(6);
gucARPOddNum = 0; // 有了回应,老化计数器清零
StartTimer(4,10); // 定时器4来启动定时器7
}
break;
}
}
break;
default:
break;
}
}
}
/*********************************************************************
函数名: void IpOrRouter(void)
功能: IP路由选择
输入: 初始化或者改变IP的时候
输出: 判断IP还是路由
返回: None
日期: 2005/01/24
更新: 2006/05/21
*********************************************************************/
void IpOrRouter(void)
{
UWORK32 ulLocalIP,ulRemoteIP,ulMask;
UWORK8 ucaTemp[4],ucLoop;
memcpy((UWORK8 *)&ulLocalIP,&IPAddress_buf[0],IP_LEN);
memcpy((UWORK8 *)&ulMask,&SubNetMask_buf[0],IP_LEN);
for(ucLoop = 0; ucLoop < REMOTE_IP_NUM; ucLoop++) // 目的IP地址 /
{
memset(&ucaTemp[0],0,4);
if(0 == memcmp(&ucaTemp[0],&ArpCache_Buf[ucLoop].ucaIP[0],IP_LEN))
{
ArpCache_Buf[ucLoop].ucIPValible = 0; // 没有合法的IP,规定0.0.0.0为非法IP
}
else
{
ArpCache_Buf[ucLoop].ucIPValible = 1;
memcpy((UWORK8 *)&ulRemoteIP,&ArpCache_Buf[ucLoop].ucaIP[0],IP_LEN);
if((ulLocalIP & ulMask) == (ulRemoteIP & ulMask))
{
ArpCache_Buf[ucLoop].ucIpOrRouter = 0; // 网络号相同,直接交付
memcpy(&ArpCache_Buf[ucLoop].ucaArpIp[0],&ArpCache_Buf[ucLoop].ucaIP[0],IP_LEN);
}
else
{
ArpCache_Buf[ucLoop].ucIpOrRouter = 1; // 网络号不相同,使用路由间接交付
memcpy(&ArpCache_Buf[ucLoop].ucaArpIp[0],&GateWay_buf[0],IP_LEN);
}
}
ArpCache_Buf[ucLoop].ucStatus = 'f';
}
}
/*********************************************************************
函数名: void StopArpCounter(void)
功能: 停止ARP相关的计数器
输入: 检测到了IP或MAC冲突
输出: 停止ARP
返回: None
日期: 2006/06/22
*********************************************************************/
void StopArpCounter(void)
{
StopTimer(5);
StopTimer(6);
StopTimer(7);
}
/*********************************************************************
函数名: void IpReceive(void)
功能: Ip处理,因为是接收一帧处理一帧,不用返回成功失败
输入: 接收的帧是Ip帧
输出: 处理IP分组
返回: None
日期: 2004/12/20
*********************************************************************/
void IpReceive(void)
{
ST_IP_HEAD_FORMAT *pIpHead;
ST_UDP_HEAD_FORMAT *pUdpHead;
UWORK16 usFragmentOffset;
pIpHead = (ST_IP_HEAD_FORMAT *)&gstaRevEthernet.ucaPacket[0]; // 指向IP头
pUdpHead = (ST_UDP_HEAD_FORMAT *)&gstaRevEthernet.ucaPacket[20];
// IP数据需满足3个条件 1.广播包 2.本地IP地址
// 只处理IPV4和基本长度的IP包
if(0x45 == pIpHead->ucVerAndLen)
{
if(0x0000 == CheckSum((UWORK16 *)&gstaRevEthernet.ucaPacket[0],20)) // 计算IP校验头
{
if(0 == (pIpHead->usSegOffset & 0x3fff)) // 没有分片的处理,直接从接收缓冲拷贝数据
{
if(pIpHead->usTotalLen > 1514) // 不能超过以太网的最大包长度,防止恶意攻击
{
return;
}
gbHaveFragment = FALSE; // 清分片标志
switch(pIpHead->ucprotocol)
{
case ICMP: //网间网控制报文协议,PING命令
IcmpReceive(pIpHead->usTotalLen - 20);
break;
case UDP:
UdpReceive();
break;
case TCP: //TCP协议
// TCPReceive();
break;
case IGMP: //IGMP协议
// IGMPReceive();
break;
default:
break;
}
}
else // 建立一个缓冲,用于组装分散包
{
usFragmentOffset = (pIpHead->usSegOffset & 0x1fff) * 8;
if(pIpHead->usSegOffset & MORE_FRAGMENT) // 有更多的分片
{
if( 0 == usFragmentOffset) // 第一个分片
{
memcpy(&NetSend_buf[0],&gstaRevEthernet.ucaPacket[0],20); // ICMP需要
memcpy(&gucaSegTemp[0],&gstaRevEthernet.ucaPacket[0],pIpHead->usTotalLen);
RevIpID = pIpHead->usID;
gbHaveFragment = TRUE;
}
else //中间分片
{
if(RevIpID != pIpHead->usID) // 是否为同一个ID /
{
return;
}
if((usFragmentOffset + pIpHead->usTotalLen) <= SEGMENT_DATA) // 只有5K的缓存
{
memcpy(&gucaSegTemp[usFragmentOffset + 20],&gstaRevEthernet.ucaPacket[20],pIpHead->usTotalLen - 20);
}
}
}
else // 最后一个分片
{
if(RevIpID != pIpHead->usID) // 是否为同一个ID
{
return;
}
if((usFragmentOffset + pIpHead->usTotalLen) <= SEGMENT_DATA) // 只有5K的缓存
{
memcpy(&gucaSegTemp[usFragmentOffset + 20],&gstaRevEthernet.ucaPacket[20],pIpHead->usTotalLen - 20);
// 还需要判断数据是否完全到齐?????
switch(NetSend_buf[9])
{
case ICMP:
IcmpReceive(usFragmentOffset + pIpHead->usTotalLen - 20);
break;
case UDP:
UdpReceive();
break;
default:
break;
}
}
}
}
}
}
}
/*********************************************************************
函数名: void IpSend(void)
功能: Ip发送数据
输入: 发送数据的长度
输出: 将数据打包成IP包
返回: None
日期: 2004/12/28
*********************************************************************/
void IpSend(void)
{
ST_IP_HEAD_FORMAT *pIpHeadBuff;
MAC_Remote_buf[12] = 0x08; // IP协议
MAC_Remote_buf[13] = 0x00;
pIpHeadBuff = (ST_IP_HEAD_FORMAT *)&NetSend_buf[0]; // IP头
memcpy(&NetSend_buf[0],&gstIphead,20);
pIpHeadBuff->usCheckSum = 0;
pIpHeadBuff->usCheckSum = CheckSum((UWORK16 *)&NetSend_buf[0],20); // 计算IP头校验和
SendEthernetPacket(pIpHeadBuff->usTotalLen);
}
/*********************************************************************
函数名: void IcmpReceive(UWORK16 usTotalLen)
功能: Icmp处理,因为是接收一帧处理一帧,不用返回成功失败
输入: IP包数据长度
输出: 处理Icmp分组
返回: None
日期: 2004/12/21
*********************************************************************/
void IcmpReceive(UWORK16 usTotalLen)
{
ST_ICMP_HEAD_FORMAT *pIcmpHead;
ST_IP_HEAD_FORMAT *pIpHeadBuff;
UWORK16 usLoop,usRes,usCheckSum;
UWORK8 ucNum;
if(FALSE == gbHaveFragment)
{
pIcmpHead = (ST_ICMP_HEAD_FORMAT *)&gstaRevEthernet.ucaPacket[20]; // 指向ICMP头
usCheckSum = CheckSum((UWORK16 *)&gstaRevEthernet.ucaPacket[20],usTotalLen);
pIpHeadBuff = (ST_IP_HEAD_FORMAT *)&gstaRevEthernet.ucaPacket[0];
}
else
{
pIcmpHead = (ST_ICMP_HEAD_FORMAT *)&gucaSegTemp[20];
usCheckSum = CheckSum((UWORK16 *)&gucaSegTemp[20],usTotalLen);
pIpHeadBuff = (ST_IP_HEAD_FORMAT *)&gucaSegTemp[0];
}
if(0x0000 != usCheckSum)
{
return; // 校验和错误,返回
}
switch(pIcmpHead->ucType)
{
case ICMP_ECHO: // 目的端的回送请求
// 组帧应答
pIcmpHead->ucType = ICMP_ECHO_REPLY; // 应答
pIcmpHead->usCheckSum = 0x00;
// IP头
gstIphead.usID = ++LocalIpID;
gstIphead.ucprotocol = 0x01; // ICMP协议
memcpy(&gstIphead.ucSourceIP[0],&IPAddress_buf[0],IP_LEN); // 原IP地址
memcpy(&gstIphead.ucDestIP[0],&pIpHeadBuff->ucSourceIP[0],IP_LEN); // 目的IP地址
memcpy(&MAC_Remote_buf[0],&gstaRevEthernet.ucaSourceNodID[0],NOD_ID_LENGTH); // 目的MAC地址
if(FALSE == gbHaveFragment) // 没有分片的数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -