📄 icmp.c
字号:
/**---------------------版权 (c)----------------------------------------------------------***
*** 作者:颜章健 ***
*** 邮件:jenkinyan@163.com ***
*** ***
***---------------------File Info---------------------------------------------------------***
*** 创 建 人: 颜章健 ***
*** 创建日期: 2008-03-16 ***
*** 创建版本: ***
*** 文件描述: ***
***---------------------------------------------------------------------------------------***
*** 修 订 人: ***
*** 修订日期: ***
*** 修订版本: ***
*** 修订描述 ***
***---------------------------------------------------------------------------------------**/
#include "config.h"
#define ICMPS_TIMEOUT 1
#define ICMPS_ACK 2
#define ICMPS_REQ 3
static int TimerHandler;
static uint8 IcmpStatus;
static uint32 RequestTime;
static uint8 IcmpRequestPacket[12];
NET_PKT IcmpReqPacket;
static union {uint16 w; uint8 b[2];}IcmpReqId;
static union {uint16 w; uint8 b[2];}IcmpCrc;
/********************************************************************************************
*** 函数名称: IcmpEchoReqTimeOut
*** 函数描述: ping 命令请求超时服务,用于注入定时器定时后触发
*** 入 口: 无
*** 出 口: 无
********************************************************************************************/
static void IcmpEchoReqTimeOut(void)
{
if(IcmpStatus != ICMPS_ACK)
{
IcmpStatus = ICMPS_TIMEOUT;
_printf("Request timed out\r\n");
}
}
/********************************************************************************************
*** 函数名称: IcmpEchoRequest
*** 函数描述: ping 命令请求
*** 入 口: ip 目的IP地址
*** 出 口: 无
********************************************************************************************/
void IcmpEchoRequest(uint8 *ip)
{
char IcmpStr[100];
sprintf(IcmpStr,"Pinging %d.%d.%d.%d whith 4 bytes of data:\r\n",ip[0],ip[1],ip[2],ip[3]);
_printf(IcmpStr);
IcmpReqId.w++;
IcmpReqPacket.Data = IcmpRequestPacket;
IcmpReqPacket.Length = 12;
IcmpReqPacket.Next = NULL;
IcmpRequestPacket[0] = ICMPF_ECHOREQ;
IcmpRequestPacket[1] = 0x00;
IcmpRequestPacket[2] = 0x00;
IcmpRequestPacket[3] = 0x00;
IcmpRequestPacket[4] = IcmpReqId.b[1];
IcmpRequestPacket[5] = IcmpReqId.b[0];
IcmpCrc.w = 0xffff - InetCheckSum(IcmpRequestPacket,12);
IcmpRequestPacket[2] = IcmpCrc.b[0];
IcmpRequestPacket[3] = IcmpCrc.b[1];
NetLayer.SendPacket(IPF_ICMP,ip,&IcmpReqPacket);
RequestTime = NetTimerGetTc();
TimerHandler = NetTimerHookRegist(3000,IcmpEchoReqTimeOut);
IcmpStatus = ICMPS_REQ;
}
/********************************************************************************************
*** 函数名称: IcmpMaskRequest
*** 函数描述: 请求子网掩码
*** 入 口: 无
*** 出 口: 无
********************************************************************************************/
void IcmpMaskRequest(void)
{
uint8 ip[4] = {0xff,0xff,0xff,0xff};
IcmpReqId.w++;
IcmpReqPacket.Data = IcmpRequestPacket;
IcmpReqPacket.Length = 12;
IcmpReqPacket.Next = NULL;
IcmpRequestPacket[0] = ICMPF_MASKREQ;
IcmpRequestPacket[1] = 0x00;
IcmpRequestPacket[2] = 0x00;
IcmpRequestPacket[3] = 0x00;
IcmpRequestPacket[4] = IcmpReqId.b[1];
IcmpRequestPacket[5] = IcmpReqId.b[0];
IcmpCrc.w = 0xffff - InetCheckSum(IcmpRequestPacket,12);
IcmpRequestPacket[2] = IcmpCrc.b[0];
IcmpRequestPacket[3] = IcmpCrc.b[1];
NetLayer.SendPacket(IPF_ICMP,ip,&IcmpReqPacket);
}
/********************************************************************************************
*** 函数名称: IcmpEchoReqProcess
*** 函数描述: ping 请求处理:返回应答包
*** 入 口: 无
*** 出 口: 无
********************************************************************************************/
void IcmpEchoAck(void)
{
char IcmpStr[100];
union {uint16 w; uint8 b[2];}crc;
NET_PKT AckIpPacket;
uint8 *p;
uint8 i;
uint8 IpHeadLen;
AckIpPacket.Data = NetLayer.Rxd;
AckIpPacket.Length = NetLayer.Rxl;
AckIpPacket.Next = NULL;
IpHeadLen = (NetLayer.Rxd[0] & 0x0f) << 2;
sprintf(IcmpStr,"Ping请求,IP头部长=%d\r\n", IpHeadLen);
_printf(IcmpStr);
// 设置源和目的IP
for(i=0; i<4; i++)
{
NetLayer.Rxd[i+16] = NetLayer.Rxd[i+12];
NetLayer.Rxd[i+12] = LinkLayer.Config.Ip[i];
}
// TTL减1
NetLayer.Rxd[8] = NetLayer.Rxd[8] - 1;
// 清零IP包头部校验值
NetLayer.Rxd[10] = 0;
NetLayer.Rxd[11] = 0;
// 计算并填充IP头部校验值
crc.w = 0xffff - InetCheckSum(AckIpPacket.Data,IpHeadLen);
NetLayer.Rxd[10] = crc.b[0];
NetLayer.Rxd[11] = crc.b[1];
// 设置ICPM类型、代码,清空校验字段
p = NetLayer.Rxd + IpHeadLen;
p[0] = ICMPF_ECHOACK; // 类型
p[1] = 0x00; // 代码
p[2] = 0x00; // CRC清零
p[3] = 0x00; // CRC清零
// 计算并填充ICMP头部校验值
crc.w = 0xffff - InetCheckSum(p,(NetLayer.Rxl - IpHeadLen));
p[2] = crc.b[0];
p[3] = crc.b[1];
LinkLayer.PutFrame(PPPF_IP,&AckIpPacket);
}
/********************************************************************************************
*** 函数名称: IcmpEchoAckDisplay
*** 函数描述: ping 应答显示
*** 入 口: 无
*** 出 口: 无
********************************************************************************************/
void IcmpEchoAckDisplay(void)
{
char IcmpStr[100];
uint8 *ip;
uint16 bytes;
uint8 TTL;
uint32 TC;
NetTimerHookDelete(TimerHandler);
IcmpStatus = ICMPS_ACK;
TC = NetTimerGetTc();
if(TC < RequestTime)
{
RequestTime = 300000 - RequestTime + TC;
}
else
{
RequestTime = TC - RequestTime;
}
bytes = *(NetLayer.Rxd + 2);
bytes <<= 8;
bytes |= ((*(NetLayer.Rxd + 3)) & 0xff);
TTL = ((*NetLayer.Rxd) & 0x0f) << 2;
bytes = bytes - TTL - 8;
TTL = *(NetLayer.Rxd + 8);
ip = NetLayer.Rxd + 12;
sprintf(IcmpStr,"Reply form %d.%d.%d.%d: bytes=%d time=%dms TTL=%d \r\n",
ip[0],ip[1],ip[2],ip[3],bytes,RequestTime,TTL);
_printf(IcmpStr);
}
/********************************************************************************************
*** 函数名称: IcmpMaskAckProcess
*** 函数描述: 子网掩码应答处理:保存子网掩码
*** 入 口: 无
*** 出 口: 无
********************************************************************************************/
void IcmpMaskAckProcess(void)
{
char IcmpStr[100];
uint8 *p;
uint8 i;
i = ((*NetLayer.Rxd) & 0x0f) << 2;
p = NetLayer.Rxd + i + 8;
sprintf(IcmpStr,"获取到子网掩码 %d.%d.%d.%d \r\n",p[0],p[1],p[2],p[3]);
_printf(IcmpStr);
for(i=0; i<4; i++)
{
LinkLayer.Config.Mask[i] = *p++;
}
LinkLayer.Config.Mask[4] = 1;
}
/********************************************************************************************
*** 函数名称: IcmpProcess
*** 函数描述: ICMP 协议主程序
*** 入 口: 无
*** 出 口: 无
********************************************************************************************/
void IcmpProcess(void)
{
uint8 dat;
_printf("ICMP packet:\r\n");
dat = *(NetLayer.Rxd + 20);
switch(dat)
{
case ICMPF_ECHOREQ:
if(InetMemCmp(NetLayer.Rxd+16,LinkLayer.Config.Ip,4))
{
IcmpEchoAck();
}
break;
case ICMPF_ECHOACK:
if(InetMemCmp(NetLayer.Rxd+16,LinkLayer.Config.Ip,4))
{
IcmpEchoAckDisplay();
}
break;
case ICMPF_MASKACK:
if(InetMemCmp(NetLayer.Rxd+16,LinkLayer.Config.Ip,4))
{
IcmpMaskAckProcess();
}
break;
default:
break;
}
}
/********************************************************************************************
*** 文件结束 ***
********************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -