//照书写的,但是有问题.#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;
}
#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;
}
2. 显示结果如下:
(99.186.67.0 )
104 bytes from 182.99.186.67:icmp_seq _ 0.time: 0 ms
Erro2
Erro2
Erro2
但是去掉start 和 end 之间的部分,就是正确的。
只要把 ipopt = (IpOptionHeader *) (buf + 20); 一句改成
ipopt = (IpOptionHeader *) (buf + 19);
就对了。
可是IP格式前面是20字节。具体原因还是不太清楚。
还有个问题,printf("(%-15s) %s\n",inet_ntoa(inaddr),host->h_name);
这句显示结果:(0.0.0.0) 主机名 //注主机名居然是正确的。
这是怎么回事。