?? 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 + -