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

📄 iroute.cpp

📁 使用VC模拟实现linux下irout命令功能。访问某一网址并写出中间路由IP。
💻 CPP
字号:
#include<iostream.h>
#include<winsock2.h>
#include<ws2tcpip.h>
#include<iomanip.h>

//定义ip头部结构体
typedef struct iphdr{
	unsigned int headlen:4;                      //4位IP头长度
	unsigned int version:4;                      //4位IP版本号
	unsigned char tos;                           //服务类型
	unsigned short totallen;                     //IP包总长度
	unsigned short id;                           //ID号
	unsigned short flag;                         //标记
	unsigned char ttl;                           //生存时间
	unsigned char prot;                          //协议
	unsigned short checksum;                     //校验和

	unsigned int sourceIP;                       //源IP
	unsigned int destIP;                         //目的IP
}IpHeader;

typedef struct icmphdr{
	BYTE type;                                   //ICMP类型码,回送请求的类型码为8
	BYTE code;                                   //子类型码,保存与特定ICMP报文类型相关的细节信息
	USHORT checksum;                             //校验和
	USHORT id;                                   //ICMP报文ID号
	USHORT seq;                                  //ICMP数据报的序列号
}IcmpHeader;

#define ICMP_ECHO 8                              //请求回送
#define ICMP_ECHO_REPLY 0                        //请求回应
#define ICMP_MIN 8                               //ICMP包头长度(最小ICMP包长度)
#define STATUS_FAILED 0xFFFF                     //错误码
#define DEF_PACKET_SIZE 32                       //缺省数据报长度
#define MAX_PACKET 1024                          //最大数据块长度
#define MAX_PACKET_SIZE (MAX_PACKET+sizeof(IpHeader)) //最大接收数据包长度

void fill_icmp_data(char*,int);                  //填充ICMP包
USHORT checksum(USHORT*,int);                    //校验和函数 


void main(int argc,char*argv[])
{
	if(argc!=2)
	{
		cout<<"Input Error!"
			<<endl
			<<"Please input:iroute dest_ip"
			<<endl;
		exit(0);
	}

	cout<<endl<<"Tracing route to  "<<argv[1]<<"  over a maximum of 30 hops"<<endl<<endl;

	WSADATA wsaData;
	if(WSAStartup(0x102,&wsaData)!=0)            //开始使用Ws2_32.dll
	{
		cout<<"WSAStartup failed:"<<GetLastError()<<endl;
		ExitProcess(STATUS_FAILED);
	}

	//创建原始套接字
	SOCKET sock;
	sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);
	if(sock==INVALID_SOCKET)
	{
		cout<<"WSASocket() failed:"<<WSAGetLastError()<<endl;
		ExitProcess(STATUS_FAILED);
	}

	//设置接收延时
	int timeout=1000;
	int bread=setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
	if(bread==SOCKET_ERROR)
	{
		cout<<"failed to set recv timeout:"<<WSAGetLastError()<<endl;
		ExitProcess(STATUS_FAILED);
	}

	//设置发送延时
	timeout=1000;
	bread=setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));
	if(bread==SOCKET_ERROR)
	{
		cout<<"failed to set send timeout:"<<WSAGetLastError()<<endl;
		ExitProcess(STATUS_FAILED);
	}

	struct sockaddr_in dest,from;                //dest:目的IP,from:接收ICMP包的源IP
	int fromlen=sizeof(from);                    //接收ICMP包长度
	char* recvbuf=new char[MAX_PACKET_SIZE];//接收ICMP包缓冲区


	memset(&dest,0,sizeof(dest));               //初始化dest结构

	dest.sin_family=AF_INET;
	dest.sin_addr.s_addr=inet_addr(argv[1]);    //填入目的IP地址

	char icmp_data[MAX_PACKET];                 //MAX_PACKET是数据报最大可能的长度
	memset(icmp_data,0,MAX_PACKET);             //将数据报清空初始化
	int datasize=DEF_PACKET_SIZE;               //数据报报文体的缺省长度
	datasize+=sizeof(IcmpHeader);               //加上报头的长度
	fill_icmp_data(icmp_data,datasize);         //填充ICMP数据报
	((IcmpHeader*)icmp_data)->checksum=0;       //先将校验和置零
	((IcmpHeader*)icmp_data)->seq=0;            //序列号设为0

	//计算校验和后填入
	((IcmpHeader*)icmp_data)->checksum=checksum((USHORT*)icmp_data,datasize);

	int ttl=1;                                  //ttl初始值为1

	//开始路由,当找到目的主机或达到30跳时退出
	while(from.sin_addr.s_addr!=dest.sin_addr.s_addr&&ttl<=30)
	{
		//设置IP报头的TTL
		bread=setsockopt(sock,IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl));
		if(bread==SOCKET_ERROR)
		{
			cout<<"failed to set IP_TTL:"<<WSAGetLastError()<<endl;
			ExitProcess(STATUS_FAILED);
		}

		unsigned long tc = GetTickCount();      //发送时间

		//发送数据报
		bread=sendto(sock,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));
		int n=0;
		if(bread==SOCKET_ERROR)
		{
			if(WSAGetLastError()==WSAETIMEDOUT)
			{
				cout<<"Request timed out"<<endl;
			}
			cout<<endl<<"Sendto failed:"<<WSAGetLastError()<<endl;
			ExitProcess(STATUS_FAILED);
			n=1;
		}
		if(WSAGetLastError()==WSAETIMEDOUT)
		{
			cout<<"Request timed out"<<endl;
			ExitProcess(STATUS_FAILED);
			n=1;
		}
		if(bread<datasize)
		{
			cout<<"Wrote "<<bread<<" bytes"<<endl;
			ExitProcess(STATUS_FAILED);
			n=1;
		}

		//接收数据报
		bread=recvfrom(sock,recvbuf,MAX_PACKET_SIZE,0,(struct sockaddr*)&from,&fromlen);
		if(bread==SOCKET_ERROR)
		{
			if(WSAGetLastError()==WSAETIMEDOUT)
			{
				cout<<setw(3)<<ttl<<"  Request timed out"<<endl;
			}
			cout<<endl<<"Receive failed:"<<WSAGetLastError()<<endl;
			ExitProcess(STATUS_FAILED);
			n=1;
		}

		unsigned int ms=GetTickCount()-tc;              //计算总时间
	
		//去掉IP报头,输出IP地址
		if(n==0)
		{
			IpHeader* iphdr;
			IcmpHeader* icmphdr;
			unsigned short iphdrlen;
			iphdr=(IpHeader*)recvbuf;
			iphdrlen=iphdr->headlen*4;                  //IP报头的长度
			icmphdr=(IcmpHeader*)(recvbuf+iphdrlen);    //跳过IP报头
			if(bread<iphdrlen+ICMP_MIN) continue;       //数据报太短,丢弃

			//输出相关信息
			cout<<setw(3)<<ttl;
			if(ms<1)
				cout<<setw(4)<<"<1"<<" ms  ";
			else
				cout<<setw(4)<<ms<<" ms  ";
			cout<<inet_ntoa(from.sin_addr)<<endl;
			ttl++;
		}
	}
	cout<<endl<<"Trace complete"<<endl;
}

//填充ICMP包
void fill_icmp_data(char*icmp_data,int datasize)
{
	IcmpHeader* icmp_hdr;
	char *datapart;
	icmp_hdr=(IcmpHeader*)icmp_data;
	icmp_hdr->type=ICMP_ECHO;
	icmp_hdr->id=(USHORT)GetCurrentThreadId();
	datapart=icmp_data+sizeof(IcmpHeader);
	memset(datapart,'A',datasize-sizeof(IcmpHeader));
}

//计算校验和
USHORT checksum(USHORT *buffer,int size)
{
	unsigned long cksum=0;
	while(size>1)
	{
		cksum+=*buffer++;
		size-=sizeof(USHORT);
	}
	if(size)
	{
		cksum+=*(UCHAR*)buffer;
	}
	cksum=(cksum>>16)+(cksum& 0xffff);
	cksum+=cksum>>16;
	return(USHORT)(~cksum);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -