首页 新闻 搜索 专区 学院

使用rawsocket为什么不能发ICMP出去呢,大神的帮看看

0
[待解决问题]

#include <iostream>
#include <WINSOCK2.H>
#include <ws2tcpip.h>


using namespace std;
#pragma comment(lib,"ws2_32.lib")


#define ICMP_PROTOCOL 8
#define ICMP_CODE 0
#define ICMP_MIN 8

#define DEF_PACKET_SIZE 100
#define DEF_PACKET_NUMBER 10
#define MAX_PACKET 64

/************************************************************************/
/* 下面是IP_Head 的结构体 */
/************************************************************************/
struct IP_Head{
BYTE version:4; //版本//
BYTE lenght:4; //首部长度//
unsigned char ip_tos; //服务//
unsigned short totallenght; //IP首部总长//
unsigned short ip_id; //IP标识//

//下面三个是标志//
unsigned char ip_MF :1; //为1的时候是代表后面还有分片//
unsigned char ip_DF :1; //当等于0的时候才允许分片//
unsigned char ip_NF :1; //设置为0,因为现在还不使用//

//下面是片偏移//
unsigned char ip_frag_offset :5;
unsigned char ip_frag_offset1;

BYTE ip_TTL; //这是生存时间,以跳数来计算,每通过一个路由器就减1//
BYTE ip_protocol; //这是所使用的协议//
unsigned short check_num; //首部校验和//
unsigned int ip_sou; //源地址//
unsigned int ip_dest; //目的地址//
};

/************************************************************************/
/* 下面是ICMP_Head信息 */
/************************************************************************/
struct ICMP_Head{
BYTE icmp_type;
BYTE icmp_code;
USHORT check_num;
USHORT icmp_id;
USHORT icmp_seq;
ULONG timeStamp;
};

/************************************************************************/
/* 下面是UDP_Head信息 */
/************************************************************************/
struct UDP_Head{
unsigned short udp_sou_port;
unsigned short udp_dst_port;
unsigned short udp_lenght;
unsigned short udp_check_num;
};

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

//填充IP_Head信息//
void fill_IP(char *buf,const sockaddr_in to){

IP_Head *ip=(IP_Head*)buf;

ip->version=4;
ip->lenght=sizeof(IP_Head)>>2;
ip->ip_tos=0;
ip->totallenght= htons(sizeof(IP_Head) + sizeof(ICMP_Head));
ip->ip_id=0;
ip->ip_DF=0;
ip->ip_NF=0;
ip->ip_MF=0;
ip->ip_frag_offset=0;
ip->ip_frag_offset1=0;
ip->ip_protocol=IPPROTO_ICMP;
ip->ip_TTL=128;
ip->check_num=0;

ip->ip_sou=inet_addr("10.120.80.13");
ip->ip_dest=inet_addr(inet_ntoa(to.sin_addr));

}

//解析ICMP信息,来自ICMP的错误报文//
void fill_ICMP(char *buf){

ICMP_Head *icmphead=NULL;
char *datapart=NULL;
icmphead=(ICMP_Head*)(buf+sizeof(IP_Head));
icmphead->icmp_type =ICMP_PROTOCOL;
icmphead->icmp_code =0;
icmphead->check_num =0;
icmphead->icmp_id = (USHORT)GetCurrentProcessId();
icmphead->timeStamp=0;
icmphead->icmp_seq=0;

datapart = buf+(sizeof(IP_Head) + sizeof(ICMP_Head));

int size=DEF_PACKET_SIZE-(sizeof(ICMP_Head)+sizeof(IP_Head));
for(int i=0; i<size; i++,datapart++)
*datapart=NULL;
}

void decode_ICMP(const char *recvbuf,int byt,sockaddr_in *from){
recv_packet++;
IP_Head *idHead=(IP_Head*)recvbuf;
ICMP_Head *icmp_head=(ICMP_Head*)(recvbuf+sizeof(IP_Head));
cout<<"IP Version:"<<static_cast<int>(idHead->version)<<endl;
cout<<"protocol:"<<static_cast<int>(idHead->ip_protocol)<<endl;
cout<<"Reply from "<<inet_ntoa(from->sin_addr);
cout<<" "<<byt<<" bytes";
cout<<" time : "<<((ULONG)GetTickCount()-icmp_head->timeStamp)<<" ms ";
cout<<" seq="<<icmp_head->icmp_seq;
cout<<" TTL="<<static_cast<int>(idHead->ip_TTL);
if (static_cast<int>(idHead->ip_protocol)==17)
{
UDP_Head *head=(UDP_Head*)(recvbuf+sizeof(IP_Head));
cout<<"UDP port:"<<static_cast<int>(head->udp_sou_port)<<endl;
cout<<"UDP port:"<<static_cast<int>(head->udp_dst_port)<<endl;
}
cout<<endl;

}

//下面是处理的过程//
void process_IP(SOCKET raw_sock,const sockaddr_in to){
char ip_buf[DEF_PACKET_SIZE];
memset(ip_buf,NULL,DEF_PACKET_SIZE);
char recvbuf[500];
fill_IP(ip_buf,to);
fill_ICMP(ip_buf);

sockaddr_in fromaddr;
int len=sizeof(sockaddr);
for (int i=0; i<DEF_PACKET_NUMBER; ++i)
{

((IP_Head*)ip_buf)->ip_id++;
((IP_Head*)ip_buf)->check_num=0;
((ICMP_Head*)(ip_buf+sizeof(IP_Head)))->check_num=0;
((ICMP_Head*)(ip_buf+sizeof(IP_Head)))->icmp_seq=i+1;
((ICMP_Head*)(ip_buf+sizeof(IP_Head)))->timeStamp= GetTickCount();
((ICMP_Head*)(ip_buf+sizeof(IP_Head)))->check_num=checksum((unsigned short*)(ip_buf+sizeof(IP_Head)),sizeof(ICMP_Head));
((IP_Head*)ip_buf)->check_num= checksum((unsigned short*)ip_buf, sizeof(IP_Head) + sizeof (ICMP_Head));

int bsend;


bsend=sendto(raw_sock,ip_buf,DEF_PACKET_SIZE,0,(sockaddr*)&to,sizeof(sockaddr));
if (bsend==SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
{
cout<<"Send Request timed out."<<endl;
continue;
}
else
{
cout<<"sendto( ) failed:"<<WSAGetLastError();
cout<<endl;
return;
}
}

cout<<"send success!data is:"<<((ICMP_Head*)(ip_buf+sizeof(IP_Head)))->icmp_seq;
cout<<" send "<<bsend<<" byte"<<endl;
int len=sizeof(sockaddr);

int brecv=recvfrom(raw_sock,recvbuf,500,0,(sockaddr*)&fromaddr,&len);
if (brecv==SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
{
cout<<"Recv Request timed out."<<endl;
continue;
}
cout<<"recvfrom() failed: "<<WSAGetLastError()<<__LINE__<<endl;
cout<<endl;
return;
}
decode_ICMP(recvbuf,brecv,&fromaddr);
Sleep(1000);
}
cout<<"all send "<<DEF_PACKET_NUMBER<<" packet ,obtain "<<recv_packet<<endl;
cout<<"loss packet is %"<<(1-recv_packet/DEF_PACKET_NUMBER)*100<<endl;

}

int main(int argc,const char* argv[]){
SOCKET raw_sock;
sockaddr_in destAddr;
hostent *h;
WSADATA wsadata;

if (WSAStartup(MAKEWORD(2,2),&wsadata)!=0)
{
cout<<"WSAStartup fail!"<<endl;
cout<<"errno="<<WSAGetLastError()<<endl;
return 1;
}
if (argc<=1)
{
cout<<"please the host address!"<<endl;
WSACleanup();
return 1;
}
h=gethostbyname(argv[1]);
if (h==NULL)
{
cout<<"gethostbyname fail!"<<endl;
WSACleanup();
return 1;
}
memcpy(&(destAddr.sin_addr),h->h_addr,h->h_length);
destAddr.sin_family=h->h_addrtype;
cout<<"address:"<<inet_ntoa(destAddr.sin_addr)<<endl;

raw_sock=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if (raw_sock==SOCKET_ERROR)
{
cout<<"socket fail!"<<endl;
WSACleanup();
return 1;
}
//使用下面的方法来设置IP_head//
int optval=1;
if(setsockopt(raw_sock,IPPROTO_IP,IP_HDRINCL,(char*)&optval,sizeof(optval))==SOCKET_ERROR)
{
cout<<"setsockopt IP fail!"<<endl;
cout<<WSAGetLastError()<<endl;
WSACleanup();
return 1;
}
DWORD dwValue = 1; //dwValue=1 启动
int nRet = ioctlsocket(raw_sock,0x98000001,&dwValue); //dwValue=1 启动
int recvTimeout=2000;
if (setsockopt(raw_sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&recvTimeout,sizeof(recvTimeout))==SOCKET_ERROR)
{
cout<<"recvtimeo fail!"<<endl;
return 1;
}

cout<<"ip:"<<sizeof(IP_Head)+sizeof(ICMP_Head)<<endl;
cout<<"set success!"<<endl;
process_IP(raw_sock,destAddr);
WSACleanup();
closesocket(raw_sock);
return 0;
}

zh_u_的主页 zh_u_ | 菜鸟二级 | 园豆:202
提问于:2013-08-25 14:16
< >
分享
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册