我最近要写一个程序,用到要写一个自己的ping程序,而且要改变发出去的数据报的原地址,参看的csdn里不少文章,但由于我水品有限,现在实现起来还是有困难,第一次写文章求救,希望大家帮忙!谢谢!在我不自己填写ip头时,程序还能正常ping通,但是我尝试着自己填充ip头后,就ping不了了!ip头的数据结构typedef struct ip_hdr
{
unsigned char ip_verlen; 
unsigned char ip_tos; 
unsigned short ip_totallength; 
unsigned short ip_id; 
unsigned short ip_offset; 
unsigned char ip_ttl; 
unsigned char ip_protocol; 
unsigned short ip_checksum; 
unsigned int ip_srcaddr; 
unsigned int ip_destaddr; 
}IPHDR, *PIPHDR;icmp数据结构typedef struct tagICMPHDR
{
 unsigned char Type;   // Type
 unsigned char Code;   // Code
 u_short Checksum;  // Checksum
 u_short ID;    // Identification
 u_short Seq;   // Sequence
 unsigned char Data;   // Data
}ICMPHDR, *PICMPHDR;
#define REQ_DATASIZE 32  // Echo Request Data size// ICMP Echo Request
typedef struct tagECHOREQUEST
{
 ICMPHDR icmpHdr;
 DWORD dwTime;
 unsigned char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;
// ICMP Echo Reply
typedef struct tagECHOREPLY
{
 IPHDR ipHdr;
 ECHOREQUEST echoRequest;
 unsigned char    cFiller[256];
}ECHOREPLY, *PECHOREPLY;我就不全放上程序了,选重要的。bool bOpt=true;
 setsockopt(rawSocket, IPPROTO_IP, IP_HDRINCL, (char*)bOpt, sizeof(bOpt));//选择自己填充ip头我这样填充 IPHDR  myIPHead;
 myIPHead.ip_totallength=htons(sizeof(IPHDR)+sizeof(ECHOREQUEST)); 
 int ipsize=sizeof(IPHDR)/sizeof(unsigned long);
 int iIPVersion=4;
 myIPHead.ip_verlen=(iIPVersion<<4)|ipsize;
 myIPHead.ip_tos=0;
 myIPHead.ip_id=0;
 myIPHead.ip_offset=0;
 myIPHead.ip_ttl=128;
 myIPHead.ip_protocol=IPPROTO_ICMP;
 myIPHead.ip_checksum=0;
 myIPHead.ip_srcaddr=inet_addr("127.0.0.1");//这里发现只有写自己的ip才行,不然sendto报错
 myIPHead.ip_destaddr=inet_addr("211.65.86.255"); 
然后计算ip的校验和myIPHead.ip_checksum=in_cksum((u_short *)&myIPHead, sizeof(myIPHead));icmp部分是用了一个现成的,不会有问题的echoReq.icmpHdr.Type  = ICMP_ECHOREQ;
 echoReq.icmpHdr.Code  = 0;
 echoReq.icmpHdr.Checksum = 0;
 echoReq.icmpHdr.ID   = nId++;
 echoReq.icmpHdr.Seq   = nSeq++;
 
 // Fill in some data to send
 for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
  echoReq.cData[nRet] = ' '+nRet; // Save tick count when sent
 echoReq.dwTime    = GetTickCount();
 
 // Put data in packet and compute checksum
 echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST));填充一个buffer,准备发送。
memcpy(szSendBuf,&myIPHead,sizeof(myIPHead));
 memcpy(szSendBuf+sizeof(myIPHead),&echoReq,sizeof(ECHOREQUEST));
 sendSize=sizeof(myIPHead)+sizeof(echoReq);nRet = sendto(s,      /* socket */
      (LPSTR)szSendBuf,   /* buffer */
      sendSize,
      0,       /* flags */
      (LPSOCKADDR)lpstToAddr, /* destination */
     sizeof(SOCKADDR_IN));   /* address length */现在可以发送icmp报文了,但是我发现我自己填充的ip头得原地址好像必须是我自己机器的地址,否则在发送的时候会报一个套接字的错,查看后是WSAEINTR 10004这个错误,如果用自己得ip填ip头,就不会有这个错误,到底还能不能实现用别的机子的ip填写ip数据报发送数据啊?
急等着用这个程序!不然老板要骂了!

解决方案 »

  1.   

    使用RAW套接字来试试,所有的头都自己写,要做检验和校验
      

  2.   

    首先谢谢你的回答,但是我就是在用RAW套接字开发。不然也没有上面的代码了!现在可以发送icmp报文了,但是我发现我自己填充的ip头得原地址好像必须是我自己机器的地址,否则在发送的时候会报一个套接字的错。如果我填自己的就没问题,正常发送icmp!查看后是WSAEINTR 10004这个错误,如果用自己得ip填ip头,就不会有这个错误,到底还能不能实现用别的机子的ip填写ip数据报发送数据啊?
    急等着用这个程序!不然老板要骂了!
      

  3.   

    我是参考了csdn上面的一片文章的,大家知道怎么和那篇文章得作者联系吗?我刚来csdn,所以好多地方不熟悉,好多功能不会用!大家指教!
      

  4.   

    改了源地址是可以ping出去的,如果对方有防火墙的话,是看的到的! 但是是不能收到回应包的,道理很简单
      

  5.   

    CodeKey,谢谢!
    不过你是不是改了原地址,实现过ping?我现在不该原地址都正常了,但是改了就发不出去了,在sendto函数报错,查看后是WSAEINTR 10004这个错误。现在不是收不到对方回复,而是发送不成功!
      

  6.   

    用eth层的socket发送数据,这样你修改原地址以后就没有问题了。
    路由器或者交换机实际上是根据mac地址进行通讯的,而数据包离开跨路由的话他的mac地址是改变的,
    然后设置网卡成混杂模式,接受反馈回来的数据,因为数据不会发给你这个虚拟出来的地址的。
      

  7.   

    CodeKey,真不知道怎么谢你,
    多谢指教,不胜感激!我未来两天不能上网,可能不能及时给反馈! :)
      

  8.   

    也谢谢playmud给出自己的想法,但是好像是因为那样的原因!
      

  9.   

    CodeKey,我试了试,你的程序是对的呢,谢谢!
    哎,我该看看我错在哪了,对了,怎么给你分?
      

  10.   

    来晚了阿
    不过我有基于winpcap实现ICMP发送的部分代码
    你要是想要,可以给你
    我也写过类似程序
      

  11.   

    不好意思,再打扰一下!
    我按照你的改了改,可以正常发送icmp报文了,但是对方机子没有响应,我说的响应的意思不一定非要我的程序能收到icmp响应报文,而是对方机子最起码在arp表里面要有我的或者是我ip和mac信息吧,可是现在没有,codekey,这是为什么啊?
    其实我写这个程序的用意就是要在对方机子的arp表里面有我指定的机子的ip mac信息。
    再次打扰真不好意思
      

  12.   

    不好意思,再打扰一下!
    我按照你的改了改,可以正常发送icmp报文了,但是对方机子没有响应,我说的响应的意思不一定非要我的程序能收到icmp响应报文,而是对方机子最起码在arp表里面要有我的或者是我伪造发送icmp的机器(真实存在的)ip和mac信息吧,可是现在没有,codekey,这是为什么啊?
    其实我写这个程序的用意就是要在对方机子的arp表里面有我指定的机子的ip mac信息。
    再次打扰真不好意思
      

  13.   

    寄希望于codekey或者df8327(DF)赶快看到!
    他们还真实厉害!
      

  14.   

    TO xiaojiangtou(黄为) 请将你的代码发给我一份好么 。谢谢 [email protected]
      

  15.   

    谁给我一份代码,我也需要,谢谢!!!
    [email protected]