📄 icmp.c
字号:
/*********************************************************************
* Copright(c) 2004,张会福 湖南科技大学计算机学院
* All rights reserved.
*
*文件名称: icmp.c
*文件标识:
*摘 要: 测试主机的可达性,其中主要的操作是ping
*
*当前版本: V1.0
*完成日期: 2004.4.10
*
*
*********************************************************************/
#define ICMP_GLOBALS
#include "net_cfg.h"
/**********************************************************************
**函数原型: void Ping_Request( )
**入口参数: 无
**出口参数: 无
**返 回 值: 无
**说 明: 发送PING请求报文,测试对方主机的可达性
************************************************************************/
void Ping_Request()
{
TxdNetBuff.EtherFrame.DestMacId[0]=Ping_MAC.words[0]; //填充以太网协议目的物理地址字段
TxdNetBuff.EtherFrame.DestMacId[1]=Ping_MAC.words[1];
TxdNetBuff.EtherFrame.DestMacId[2]=Ping_MAC.words[2];
TxdNetBuff.EtherFrame.NextProtocal=0x0800; //以太网协议的下层协议为IP协议
TxdNetBuff.IpFrame.VerandIphLen=0x45; //IP版本和首部长度各占VerandIphLen字段的4位,版本4,占用高4位
//首部长度5*4=20,单位字节
TxdNetBuff.IpFrame.ServerType=0x00; //服务类型,默认为0
TxdNetBuff.IpFrame.TotalLen=60; //IP数据报总长度40字节,其中由总长度
//减去首部长度即可得数据报长度
TxdNetBuff.IpFrame.ttl=0x80; //IP生存时间
TxdNetBuff.IpFrame.FrameIndex=FrameIndex; //帧序号
FrameIndex++; //
TxdNetBuff.IpFrame.Segment=0x0000; //标志及段偏移都为0
TxdNetBuff.IpFrame.NextProtocal=0x0001; //IP的下层协议为ICMP协议:TCP
TxdNetBuff.IpFrame.Crc=0;
TxdNetBuff.IpFrame.DestId[0]=Ping_Ip_Address.words[0]; //填充目的IP地址
TxdNetBuff.IpFrame.DestId[1]=Ping_Ip_Address.words[1];
TxdNetBuff.IpFrame.SourceIp[0]=My_Ip_Address.words[0]; //填充源IP地址
TxdNetBuff.IpFrame.SourceIp[1]=My_Ip_Address.words[1];
TxdNetBuff.IpFrame.Crc=CreateIpHeadCrc(); //产生IP数据报首部检验和,CreateIpHeadCrc()在global.c中定义
TxdNetBuff.IcmpFrame.type=0x08; //表示该ICMP数据帧为PING请求
TxdNetBuff.IcmpFrame.Crc=0;
TxdNetBuff.IcmpFrame.id=0x0300; //标识符
TxdNetBuff.IcmpFrame.seq=FrameIndex; //ICMP报文序号
TxdNetBuff.IcmpFrame.Crc=CreateIcmpCrc(); //产生ICMP报文的校验和,CreatIcmpCrc()在global.c中定义
Send_Packet(&TxdNetBuff,74); //发送数据包
}
//==========================================================
/**********************************************************************
**函数原型: void Ping_Answer( )
**入口参数: 无
**入口参数: 无
**返 回 值: 无
**说 明: PING应答,与PING请求一起用来测试一个主机地可达性.PING的回答
**********: 是将PING请求报文的源物理地址和目的物理地址互换,源IP地址和
**********: 目的IP地址互换,将ICMP操作类型字段换为回答,并且将PING请求
**********: 报文中的选项数据(32字节)原封不动的发回.
************************************************************************/
void Ping_Answer()
{
uchar i;
if(RxdNetBuff.IcmpFrame.type==0x08)//表示是ping请求
{
for (i=16;i<RxdNetBuff.EtherFrame.length;i++)
//从以太网协议开始复制数据到发送缓冲区
/* 发送以太网数据帧格式如下
* | 目的物理地址 | 源物理地址 | 以太网协议 | 数 据 报 |
* 6字节 6字节 2字节 46~1500字节
*
* | RTL8019 首部| 目的物理地址 | 源物理地址 | 以太网协议 | 数 据 报 |
* 4字节 6字节 6字节 2字节 46~1500字节
* |------->
* |从此处开始复制接收到的数据报
*因此在利用接收的数据拼装数据报时,一定要注意RTL8019自动地在接收数据报中添加
*了4字节的首部数据,在global.c文件的以太网驱动底层数据接收程序中也有详细说明.
*/
{
TxdNetBuff.bytes.bytebuf[i]=RxdNetBuff.bytes.bytebuf[i];//将数据复制到发送缓冲区
}
//复制接收数据报的源物理地址到发送数据报的目的物理地址字段中
TxdNetBuff.EtherFrame.DestMacId[0]=RxdNetBuff.EtherFrame.SourceMacId[0];
TxdNetBuff.EtherFrame.DestMacId[1]=RxdNetBuff.EtherFrame.SourceMacId[1];
TxdNetBuff.EtherFrame.DestMacId[2]=RxdNetBuff.EtherFrame.SourceMacId[2];
TxdNetBuff.IpFrame.ttl=TxdNetBuff.IpFrame.ttl-1; //IP数据包寿命减1
TxdNetBuff.IpFrame.Crc=0;
TxdNetBuff.IpFrame.DestId[0]=RxdNetBuff.IpFrame.SourceIp[0];//复制源IP地址到目的IP地址字段中
TxdNetBuff.IpFrame.DestId[1]=RxdNetBuff.IpFrame.SourceIp[1];
TxdNetBuff.IpFrame.SourceIp[0]=My_Ip_Address.words[0]; //填充源IP地址
TxdNetBuff.IpFrame.SourceIp[1]=My_Ip_Address.words[1];
TxdNetBuff.IpFrame.Crc=CreateIpHeadCrc(); //创建IP头校验和
TxdNetBuff.IcmpFrame.type=0x00; //操作类型:ICMP应答
TxdNetBuff.IcmpFrame.Crc=0;
for(i=21;i<41;i++) //将接收缓冲区40字节的ICMP数据复制到发送缓冲区中
{
TxdNetBuff.words.wordbuf[i]=RxdNetBuff.words.wordbuf[i];
}
TxdNetBuff.IcmpFrame.Crc=CreateIcmpCrc();
Send_Packet(&TxdNetBuff,RxdNetBuff.EtherFrame.length);
}
}
//==========================================================
/**********************************************************************
**函数原型: void Ping_Echo( )
**入口参数: 无
**出口参数: 无
**返 回 值: 无
**说 明: 接收到PING应答数据后,在本地机通过串口回显信息
************************************************************************/
void Ping_Echo()
{
union Ip_Address_Type ip;
ip.words[0] = RxdNetBuff.IpFrame.SourceIp[0];
ip.words[1] = RxdNetBuff.IpFrame.SourceIp[1];
Printf_String(" \r\nReply From IP=");
Printf_IPStr(ip);
Printf_String(" Bytes=32 ");
Printf_String("TTL=");
Printf_Hex(RxdNetBuff.IpFrame.ttl);
}
//===========================================================
/**********************************************************************
**函数原型: void Process_Ping( )
**入口参数: 无
**出口参数: 无
**返 回 值: 无
**说 明: 对PING数据包进行处理
************************************************************************/
void Process_Ping()
{
if(Ping_Count>0)
{
Ping_Count--;
if(Ping_Count>0)
{
if((Ping_IP_TTL>0)||(Gateway_IP_TTL>0))
//ARP请求发送后,ARP回答会对请求分组中的IP地址进行解析,并设置全局变量的值
//如果是对网关的解析则将Gateway_IP_TTL的值置为10;若是对某一主机IP的解析则
//将Ping_IP_TTL的值置为10.
{ //表示ip地址已经解析
//Printf_String("\r\nSend Ping Request...");
Ping_Request(); //发送PING请求
}
else
{ //IP地址还没有解析
//Printf_String("\r\nSend ARP Request...\r\n ");
Arp_Request(Ping_Ip_Address.dwords); //发送ARP请求,对IP地址进行解析
}
if(Ping_Ip_Address.dwords==My_Ip_Address.dwords) //ping的是自己的ip地址
{
Printf_String("\r\nReply From IP="); //显示信息
Printf_IPStr(My_Ip_Address);
Printf_String(" Bytes=32 ");
Printf_String("TTL=10");
}
}//if(Ping_Count>0)
if(Ping_Count==0)
{
if(((Ping_Ip_Address.dwords!=My_Ip_Address.dwords)&(Ping_IP_TTL == 0))
||((Ping_Ip_Address.dwords=Gateway_Ip_Address.dwords)&(Gateway_IP_TTL==0)))
Printf_String("\r\nRequest Timed out.\r\n");
Printf_String("\r\nPing Command Finished.\r\n");
Ping_IP_TTL=0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -