⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icmp.c

📁 在S3C2440上运行的"电子日历“(支持平年,闰年,星期自动调整). 开发环境是RVDS2.2
💻 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 + -