//照书写的,但是有问题.#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>#pragma comment(lib, "ws2_32")
#define IP_RECORD_ROUTE 0x7typedef struct _iphdr
{
unsigned int  h_len:4;
unsigned int version:4;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
}IpHeader;#define ICMP_ECHO       8
#define ICMP_ECHOREPLY  0
#define ICMP_MIN        8
typedef struct _Icmphdr
{
BYTE  i_type;
BYTE  i_code;
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;
ULONG  timestamp;
}IcmpHeader;
typedef  struct _ipoptionhdr
{
unsigned char   code;
unsigned char    len;
unsigned  char   ptr;
unsigned  long  addr[9];
} IpOptionHeader;#define DEF_PACKET_SIZE    32
#define MAX_PACKET         1024
#define MAX_IP_HDR_SIZE    60bool   bRecordRoute = true;
int datasize = DEF_PACKET_SIZE ;
char * lpdest = "172.25.136.97";//change to your own address.
void FillICMPData(char * icmp_data,int datasize)
{
IcmpHeader * icmp_hdr = NULL;
char  * datapart = NULL;
icmp_hdr = (IcmpHeader*)icmp_data;
icmp_hdr->i_type = ICMP_ECHO;
icmp_hdr->i_code = 0;
icmp_hdr ->i_id = (USHORT)GetCurrentProcessId();
icmp_hdr ->i_cksum = 0;
icmp_hdr -> i_seq = 0; datapart = icmp_data + sizeof(IcmpHeader); memset(datapart,'E',datasize-sizeof(IcmpHeader));
return;
}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);}void DecodeIPOptions(char * buf,int bytes)
{
IpOptionHeader * ipopt = NULL;
IN_ADDR    inaddr;
int i;
HOSTENT  * host = NULL; ipopt = (IpOptionHeader *) (buf + 20);
for ( i = 0;i < (ipopt->ptr/4)-1;i++)
{
inaddr.S_un.S_addr = ipopt-> addr[i];
printf("%d\n",ipopt->addr[i]);
if (i != 0 )
printf("      ");
host = gethostbyaddr((char *)&inaddr.S_un.S_addr,sizeof(inaddr.S_un.S_addr),AF_INET); if (host)
printf("(%-15s) %s\n",inet_ntoa(inaddr),host->h_name);
else
printf("(%-15s) \n",inet_ntoa(inaddr)); }
return;}void DecodeIcmpHeader(char * buf,int bytes,struct sockaddr_in * from)
{
IpHeader  * iphdr = NULL;
IcmpHeader   *icmphdr = NULL;
unsigned short  iphdrlen;
DWORD   tick;
static int icmpcount = 0;
iphdr = (IpHeader *)buf;
iphdrlen = iphdr->h_len * 4;
tick = GetTickCount();
if ((iphdrlen == MAX_IP_HDR_SIZE) && (!icmpcount))
DecodeIPOptions(buf,bytes); if (bytes < iphdrlen + ICMP_MIN)
printf("TOO few bytes form %s\n",inet_ntoa(from->sin_addr)); icmphdr = (IcmpHeader*)(buf + iphdrlen);

printf("%d,%d,%d,%d,%d",icmphdr->i_seq,icmphdr->i_type,icmphdr->i_code,icmphdr->i_id,icmphdr->i_cksum);
if (icmphdr->i_type != ICMP_ECHOREPLY)
{
printf("Erro2\n");
return ;
} if (icmphdr->i_id != (USHORT)GetCurrentProcessId())
{
printf("Erro1\n");
return ;
}
printf ("%d bytes from %s:",bytes,inet_ntoa(from->sin_addr));
printf ("icmp_seq =  %d.",icmphdr->i_seq);
printf("time: %d ms",tick - icmphdr->timestamp);
printf("\n");
icmpcount++;
return;
}int main(int argc,char**argv)
{
WSADATA  wsaData;
SOCKET   sockRaw = INVALID_SOCKET;
struct sockaddr_in  dest,from;
int bread,fromlen = sizeof(from),timeout = 1000,ret;
char * icmp_data = NULL,*recvbuf = NULL;
unsigned int addr = 0;
USHORT     seq_no = 0;
struct hostent *hp = NULL;
IpOptionHeader ipopt; if (WSAStartup(MAKEWORD(2,2),&wsaData) !=0)
{
return -1;
}
sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);
if (sockRaw == INVALID_SOCKET)
{
return -1;
} //如果注释掉下面的一段就是正确的、
         //start      
ZeroMemory(&ipopt,sizeof(ipopt));
ipopt.code = IP_RECORD_ROUTE;
ipopt.ptr = 4;
ipopt.len = 39;
ret = setsockopt(sockRaw,IPPROTO_IP,IP_OPTIONS,(char *)&ipopt,sizeof(ipopt));
if (ret == SOCKET_ERROR)
printf("error");         //end.
bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout)); if (bread == SOCKET_ERROR)
return -1; timeout = 1000; bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout));
if (bread == SOCKET_ERROR)
return -1; memset(&dest,0,sizeof(dest));
dest.sin_family = AF_INET; if((dest.sin_addr.s_addr = inet_addr(lpdest)) == INADDR_NONE)
{
if ((hp = gethostbyname("FPC9b-015") )!= NULL)
{
memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("%s\n",inet_ntoa(dest.sin_addr));

}
else
return -1;
}
datasize += sizeof(IcmpHeader);
icmp_data =(char *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET);
recvbuf = (char * )HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET);
if (!icmp_data)
return -1;
memset(icmp_data,0,MAX_PACKET);
FillICMPData(icmp_data,datasize); while(1)
{
static int nCount = 0;
int bwrote;
if (nCount ++ == 4)
break;
((IcmpHeader *)icmp_data)->i_cksum = 0;
((IcmpHeader *)icmp_data)->timestamp = GetTickCount();
((IcmpHeader *)icmp_data)->i_seq = seq_no++;
((IcmpHeader *)icmp_data)->i_cksum = checksum((USHORT*)icmp_data,datasize); bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));
if (bwrote == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
continue;

printf("Erro13\n");
return -1; }
if (bwrote < datasize)
printf("Wrote %d bytes \n",bwrote); bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr * )&from, &fromlen); if (bread == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
continue;

printf("Erro4\n");
return -1;
} DecodeIcmpHeader(recvbuf,bread,&from);
Sleep(1000);
} if(sockRaw != INVALID_SOCKET)
closesocket(sockRaw);
HeapFree(GetProcessHeap(),0,recvbuf);
HeapFree(GetProcessHeap(),0,icmp_data);
WSACleanup();
return 0;
}

解决方案 »

  1.   

    1. 路由ip地址显示错误。
    2. 显示结果如下:
    (99.186.67.0    )
     104 bytes from 182.99.186.67:icmp_seq _ 0.time: 0 ms
     Erro2
     Erro2
     Erro2
     但是去掉start 和 end 之间的部分,就是正确的。
      

  2.   

    马的,花了一个下午。终于知道他妈的问题在哪里了。
    只要把 ipopt = (IpOptionHeader *) (buf + 20); 一句改成
     ipopt = (IpOptionHeader *) (buf + 19); 
    就对了。
    可是IP格式前面是20字节。具体原因还是不太清楚。
    还有个问题,printf("(%-15s) %s\n",inet_ntoa(inaddr),host->h_name);
    这句显示结果:(0.0.0.0) 主机名   //注主机名居然是正确的。
    这是怎么回事。
      

  3.   

    看TCP/IP去呀.记得前20个字节是封包用的.以方便打散了在装起来.和应该在网络中怎么走