• 大小: 8.80KB
    文件类型: .rar
    金币: 1
    下载: 0 次
    发布日期: 2024-04-19
  • 语言: C/C++
  • 标签: route  out  ACE  CE  

资源简介

traceroute(路由跟踪)用于查找传输数据所经过的路由地址

资源截图

代码片段和文件信息

#include 
#include 
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include 
#include 
using namespace std;

#pragma comment(lib “Ws2_32.lib“)

//IP报头
typedef struct IP_HEADER
{
unsigned char hdr_len : 4;       //4位头部长度
unsigned char version : 4;       //4位版本号
unsigned char tos;             //8位服务类型
unsigned short total_len;      //16位总长度
unsigned short identifier;     //16位标识符
unsigned short frag_and_flags; //3位标志加13位片偏移
unsigned char ttl;             //8位生存时间
unsigned char protocol;        //8位上层协议号
unsigned short checksum;       //16位校验和
unsigned long sourceIP;        //32位源IP地址
unsigned long destIP;          //32位目的IP地址
} IP_HEADER;

//ICMP报头
typedef struct ICMP_HEADER
{
BYTE type;    //8位类型字段
BYTE code;    //8位代码字段
USHORT cksum; //16位校验和
USHORT id;    //16位标识符
USHORT seq;   //16位序列号
} ICMP_HEADER;

//报文解码结构
typedef struct DECODE_RESULT
{
USHORT usSeqNo;        //序列号
DWORD dwRoundTripTime; //往返时间
in_addr dwIPaddr;      //返回报文的IP地址
}DECODE_RESULT;

//计算网际校验和函数
/**
1、把校验和字段置为0;
2、对IP头部中的每16bit进行二进制求和;
3、如果和的高16bit不为0,则将和的高16bit和低16bit反复相加,直到和的高16bit为0,从而获得一个16bit的值;
4、将该16bit的值取反,存入校验和字段。
*/
USHORT checksum(USHORT *pBuf int iSize)
{
unsigned long cksum = 0;
//每16位相加
while (iSize > 1)
{
cksum += *pBuf++;
iSize -= sizeof(USHORT);
}
if (iSize)//如果 iSize 为正,即为奇数个字节
{
cksum += *(UCHAR *)pBuf; //则在末尾补上一个字节,使之有偶数个字节
}
cksum = (cksum >> 16) + (cksum & 0xffff); //将高16位与低16位相加
cksum += (cksum >> 16); //将进位到高位的16位与低16位相加,确保高16位为0
return (USHORT)(~cksum); //最后将结果取反,得到checksum
}

//对数据包进行解码
BOOL DecodeIcmpResponse(char *pBuf int iPacketSize DECODE_RESULT &DecodeResult
BYTE ICMP_ECHO_REPLY BYTE ICMP_TIMEOUT)
{
//检查数据报大小的合法性
IP_HEADER *pIpHdr = (IP_HEADER *)pBuf;
int iIpHdrLen = pIpHdr->hdr_len * 4;    //ip报头的长度是以4字节为单位的

//若数据包大小 小于 IP报头 + ICMP报头,则数据报大小不合法
if (iPacketSize < (int)(iIpHdrLen + sizeof(ICMP_HEADER)))
return FALSE;

//根据ICMP报文类型提取ID字段和序列号字段
ICMP_HEADER *pIcmpHdr = (ICMP_HEADER *)(pBuf + iIpHdrLen);//ICMP报头 = 接收到的缓冲数据 + IP报头
USHORT usID usSquNo;

if (pIcmpHdr->type == ICMP_ECHO_REPLY)    //ICMP回显应答报文
{
usID = pIcmpHdr->id;        //报文ID
usSquNo = pIcmpHdr->seq;    //报文序列号
}
else if (pIcmpHdr->type == ICMP_TIMEOUT)  //ICMP超时差错报文
{
char *pInnerIpHdr = pBuf + iIpHdrLen + sizeof(ICMP_HEADER); //载荷中的IP头
int iInnerIPHdrLen = ((IP_HEADER *)pInnerIpHdr)->hdr_len * 4; //载荷中的IP头长
ICMP_HEADER *pInnerIcmpHdr = (ICMP_HEADER *)(pInnerIpHdr + iInnerIPHdrLen);//载荷中的ICMP头

usID = pInnerIcmpHdr->id;        //报文ID
usSquNo = pInnerIcmpHdr->seq;    //序列号
}
else
{
return false;
}

//检查ID和序列号以确定收到期待数据报
if (usID != (USHORT)GetCurrentProcessId() || usSquNo != DecodeResult.usSeqNo)
{
return false;
}
//记录IP地址并计算往返时间
DecodeResult.dwIPaddr.s_addr = pIpHdr->sourceIP;
DecodeResult.dwRoundTripTime = GetTickCount() - DecodeResult.dwRoundTripTime;


评论

共有 条评论