//*******************************************************************
// A ping program.
// Copright by Hugo. 2006/03/20
//*******************************************************************
#include "stdio.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netdb.h"
#include "netinet/in.h"
#include "netinet/in_systm.h"
#include "sys/select.h"
#include "sys/time.h"
// IP Header -- RFC 791
#define ICMP_ECHOREPLY 0
#define ICMP_ECHO 8
#define REQ_DATASIZE 32
typedef struct tagIPHDR
{
u_char VIHL; // Version and IHL
u_char TOS; // Type Of Service
short TotLen; // Total Length
short ID; // Identification
short FlagOff; // Flags and Fragment Offset
u_char TTL; // Time To Live
u_char Protocol; // Protocol
u_short Checksum; // Checksum
struct in_addr iaSrc; // Internet Address - Source
struct in_addr iaDst; // Internet Address - Destination
}IPHDR, *PIPHDR;
// ICMP Header - RFC 792
typedef struct tagICMPHDR
{
u_char Type; // Type
u_char Code; // Code
u_short Checksum; // Checksum
u_short ID; // Identification
u_short Seq; // Sequence
char Data; // Data
}ICMPHDR, *PICMPHDR;
// ICMP Echo Request
typedef struct tagECHOREQUEST
{
ICMPHDR icmpHdr;
struct timeval echoTime;
char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;
// ICMP Echo Reply
typedef struct tagECHOREPLY
{
IPHDR ipHdr;
ECHOREQUEST echoRequest;
char cFiller[256];
}ECHOREPLY, *PECHOREPLY;
pid_t pid;
void tv_sub(struct timeval *out,struct timeval *in);
unsigned short checksum(unsigned short *buffer, int size);
int WaitForEchoReply(int socket);
int main(int argc, char **argv)
{
int sockfd;
int nRet;
struct sockaddr_in addrDest;
struct hostent *Dest;
float spenttime;
if(argc != 2)
{
fprintf(stderr, "usage: %s hostname\n", argv[0]);
exit(1);
}
if ((Dest=gethostbyname(argv[1])) == NULL)
{
/* get the host info */
herror("gethostbyname");
exit(1);
}
printf("Host name : %s\n", Dest->h_name);
// printf("IP Address : %s\n",inet_ntoa(*((struct in_addr *)Dest->h_addr)));
if((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{
perror("socket");
exit(1);
}
addrDest.sin_addr = *((struct in_addr *)Dest->h_addr);
addrDest.sin_family = AF_INET;
bzero(&(addrDest.sin_zero), 8);
ECHOREQUEST echoReq;
echoReq.icmpHdr.Type = ICMP_ECHO;
echoReq.icmpHdr.Code = 0;
echoReq.icmpHdr.ID = getpid();
int Seq = 0;
for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
echoReq.cData[nRet] = ' '+nRet;
while(1){
echoReq.icmpHdr.Seq = Seq++;
echoReq.icmpHdr.Checksum = 0;
gettimeofday(&echoReq.echoTime,NULL);
echoReq.icmpHdr.Checksum = checksum((unsigned short*)&echoReq, sizeof(struct tagECHOREQUEST));
if (sendto(sockfd, (struct ECHOREQUEST*)&echoReq, sizeof(struct
tagECHOREQUEST), 0, (struct sockaddr *)&addrDest, sizeof(addrDest))
< 0)
{
perror("sendto");
exit(1);
}
if(WaitForEchoReply(sockfd) == -1)
{
perror("select");
exit(1);
}
ECHOREPLY icmpRecv;
int addr_len;
addr_len = sizeof(struct sockaddr);
if (recvfrom(sockfd, (struct ECHOREPLY*)&icmpRecv, sizeof(struct
tagECHOREPLY), 0, (struct sockaddr *)&addrDest, &addr_len) <
0)
{
perror("sendto");
}
else if(icmpRecv.echoRequest.icmpHdr.Type == ICMP_ECHOREPLY)
{
gettimeofday(&icmpRecv.echoRequest.echoTime, NULL);
tv_sub(&icmpRecv.echoRequest.echoTime, &echoReq.echoTime);
spenttime=icmpRecv.echoRequest.echoTime.tv_sec*1000+icmpRecv.echoRequest.echoTime.tv_usec*0.001;
printf("Reply from %s: Bytes=%d Id_seq = %d time=%4.3fms
TTL=%d\n",Dest->h_name, sizeof(icmpRecv.echoRequest),
icmpRecv.echoRequest.icmpHdr.Seq, spenttime,icmpRecv.ipHdr.TTL);
sleep(1);
}
}
}
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);
}
//Wait for echoRecv
int WaitForEchoReply(int socket)
{
struct timeval Timeout;
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(socket, &readfds);
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;
return(select(socket+1, &readfds, NULL, NULL, &Timeout));
}
/*timeval*/
void tv_sub(struct timeval *out,struct timeval *in)
{
if( (out->tv_usec-=in->tv_usec)<0)
{
--out->tv_sec;
out->tv_usec+=1000000;
}
out->tv_sec-=in->tv_sec;
}
阅读(1466) | 评论(0) | 转发(0) |