代码拉取完成,页面将自动刷新
#include "basetype.h"
#include "common.h"
#include "packet_lib.h"
#include "ethernet_lib.h"
#include "arp_lib.h"
#include "ipv4_lib.h"
#include "icmp_lib.h"
#include "addr_lib.h"
#include "timer_data.h"
#include "device_data.h"
#include "route_data.h"
#include "arp_data.h"
#include "routing_process.h"
/*
* description: 创建一个task任务,并初始化
*
* input:
* usDeviceId 源设备ID
* pstIcmp_task cmp_task 结构体,具体内容见icmp_lib.h 里的的结构体定义
* UINT8* DstMac 目的mac地址
*
* output: NULL
* return: NULL
* tip: IN是空宏,表示改参数是输入
*/
VOID IcmpTask_Init(IN UINT16 usDeviceId, IN ICMP_TASK_S* pstIcmp_task, IN UINT32 DstIp, IN UINT8* DstMac)
{
UINT32 i = 0;
pstIcmp_task->usDeviceId = usDeviceId;
pstIcmp_task->usSeq = 0;
pstIcmp_task->uiDstIP = DstIp;
for (i = 0; i < 5; i++)
{
pstIcmp_task->ausSuccess[i] = 0;
}
DeviceData_MountIcmpTask(usDeviceId, pstIcmp_task);
return;
}
/*
* description:icmp报文是否超时
*
* input:
* auiPara[] // auiPara[0]存放设备id,[1]存放ping对端ip地址,[2]存放当前次数
*
* output: NULL
* return: NULL
* tip: IN是空宏,表示改参数是输入
*/
VOID IcmpTask_Timeout(IN UINT32 auiPara[])
{
ICMP_TASK_S* pstIcmp_task = DeviceData_GetIcmpTask(auiPara[0]); // 获取task
/* 定时器超时一定是ping不通 */
pstIcmp_task->ausSuccess[pstIcmp_task->usSeq] = 0;
if (++(pstIcmp_task->usSeq) == 5) // 如果seq == 5,打印结果
{
IcmpTask_print(auiPara[0]);
}
else
{
Ping(pstIcmp_task->usDeviceId, pstIcmp_task->uiDstIP, pstIcmp_task->usSeq); // 否则发送ping 并且增加一个定时器
pstIcmp_task->uiTimerId = TimerData_Add(10, TIMER_ID_INVALID, auiPara, IcmpTask_Timeout);
}
}
/*
* description: 执行icmp打印任务
*
* input:
* usDeviceId 源设备ID
*
* output: 打印收到的报文的字节数,ttl等
* return: NULL
* tip: IN是空宏,表示改参数是输入
*/
VOID IcmpTask_print(IN UINT16 usDeviceId)
{
UINT32 i = 0;
UINT8 aucIPv4String[IPV4_STRING_MAXLEN];
ICMP_TASK_S* pstIcmp_task = DeviceData_GetIcmpTask(usDeviceId);
for (i = 0; i < 5; i++)
{
if (1 == pstIcmp_task->ausSuccess[i])
{
AddrLib_InttoDotString(pstIcmp_task->uiDstIP, aucIPv4String);
printf("Received reply from %s: Bytes=%d,Delay-Time=%d,TTL=%d.\n", aucIPv4String, 32, 5, 255);
}
else
{
printf("Request Timeout\n");
}
}
printf("\n\n");
}
/*
* description: 对ping命令的处理,或者说ping命令具体流程的开始处
*
* input:
* usDeviceId 源设备ID
* uiDstIPv4Addr 目的IP地址
* usSe sequence 每送出一个报文就+1
*
* output: NULL
* return: 错误码
* tip: IN是空宏,表示改参数是输入
*/
UINT32 Ping(IN UINT16 usDeviceId, IN UINT32 uiDstIPv4Addr, IN UINT16 usSeq)
{
UINT8 aucBuffer[PACKET_MAX_SIZE] = { 0 };
UINT16 usPacketLen = 0, usOutIfNum;
INT32 iRet = ERROR_SUCCESS;
ROUTE_DATA_S* pstRoute;
ROUTE_DEVICE_S* pstRouteDevice;
DEVICE_IF_S* pstIf;
ARP_DEVICE_S* pstArpDevice;
pstRouteDevice = RouteData_FindDevice(usDeviceId); // 根据设备id获取路由设备
pstRoute = RouteData_BestMatch(pstRouteDevice, uiDstIPv4Addr); // 查主机路由
if (NULL == pstRoute)
{
// 找不到到路由就丢包,目的不可达
printf("Destination unreachable.\n");
return iRet;
}
usOutIfNum = pstRoute->usIfNum;
pstIf = DeviceData_GetIf(usDeviceId, usOutIfNum);
pstArpDevice = ArpData_FindDevice(usDeviceId);
// icmp封装
usPacketLen += IcmpLib_EncodeIcmp(aucBuffer, ICMPoptype_Ask_Echorequest, ICMPcode_Echoreply_Reply, usSeq);
iRet = send3(usDeviceId, uiDstIPv4Addr, pstIf->uiIPv4, aucBuffer, usPacketLen, 0xFF, Protocol_ICMP);
return iRet;
}
/*
* description: 封装报文的icmp部分
*
* input:
* pucBuffer 报文
* ucOptype icmp里面的optype,详细见icmp结构体定义
* ucCode icmp里面的Code,详细见icmp结构体定义
* usSeq icmp里面的sequence,详细见icmp结构体定义
*
* output: NULL
* return: icmp部分长度
* tip: IN是空宏,表示改参数是输入
*/
UINT32 IcmpLib_EncodeIcmp(IN UINT8* pucBuffer, IN UINT8 ucOptype, IN UINT8 ucCode, IN UINT16 usSeq)
{
UINT8* pucPointer = pucBuffer;
pucPointer = pucPointer + 34;
// 传进来要偏移
*pucPointer++ = ucOptype;
*pucPointer++ = ucCode;
UINT16 Checksum = PacketLib_CRCCheak(pucBuffer, 4);
*pucPointer++ = (UINT8)((Checksum & 0xFF00) >> 8);
*pucPointer++ = (UINT8)(Checksum & 0x00FF);
*((UINT16*)pucPointer) = 0; // ucIdentifier
pucPointer += 2;
*pucPointer++ = (usSeq >> 8 & 0xFF);
*pucPointer++ = (UINT8)(usSeq & 0xFF);
return 8;
}
/*
* description: 对报文的icmp报文部分解封装,并获得对应的内容
*
* input:
* pucBuffer 报文
* usPacketLen 报文长度
* output:
* pstIcmp icmp内容
* return: NULL
* tip: IN是空宏,表示改参数是输入
*/
VOID IcmpLib_DecodeIcmp(IN UINT8* pucBuffer, OUT ICMP_S* pstIcmp, IN UINT32 usPacketLen)
{
UINT8* pucPointer = pucBuffer;
if (usPacketLen < 20)
{
printf("Icmp header message length error\n");
exit(-1);
}
ETHERNET_VLAN_S ustEthernetVlanHeader;
UINT16 usVlanFlag;
usVlanFlag = 0x8100;
// 得到以太头中是否有vlan
EthernetLib_DecodeEthernetVlanHeader(pucBuffer, usPacketLen, &ustEthernetVlanHeader);
if (usVlanFlag == ustEthernetVlanHeader.usEtype)
{
pucPointer = pucPointer + 34 + 4;
}
else
{
pucPointer = pucPointer + 34;
}
pstIcmp->ucOptype = *pucPointer++;
pstIcmp->ucCode = *pucPointer++;
pstIcmp->usChecksum = PacketLib_CRCCheak(pucBuffer, 4);
*pucPointer++ = (UINT8)((pstIcmp->usChecksum & 0xFF00) >> 8);
*pucPointer++ = (UINT8)(pstIcmp->usChecksum & 0x00FF);
pstIcmp->usIdentifier = *(UINT16*)(pucPointer);
pucPointer += 2;
pstIcmp->usSeqnum = ((UINT16)*pucPointer++) << 8;
pstIcmp->usSeqnum += (UINT16)*pucPointer++;
pucPointer++;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。