#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "fcntl.h"
#include "errno.h"
#include "signal.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "sys/time.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "netdb.h"
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#define ICMP_HEADSIZE 8
#define IP_HEADSIZE 20
#define MAX(a,b) ((a) > (b))?(a):(b)
#define MIN(a,b) ((a) > (b))?(b):(a)
typedef struct tagIpHead
{
u_char ip_verlen;
u_char ip_tos;
u_char ip_len;
u_short ip_id;
u_short ip_fragoff;
u_char ip_ttl;
u_char ip_proto;
u_short ip_chksum;
u_long ip_src_addr;
u_long ip_dst_addr;
}IPHEAD;
typedef struct tagIcmpHead
{
u_char icmp_type;
u_char icmp_code;
u_short icmp_chksum;
u_short icmp_id;
u_short icmp_seq;
u_char icmp_data[1];
}ICMPHEAD;
u_short ChkSum(u_short * pIcmpData, int iDataLen)
{
u_short iSum;
u_short iOddByte;
iSum = 0;
while(iDataLen>1){
iSum ^= *(pIcmpData++);
iDataLen -=2;
}
if(iDataLen == 1){
iOddByte = 0;
*((u_char*)&iOddByte) = *(u_char*)pIcmpData;
iSum ^= iOddByte;
}
iSum ^=0xffff;
return(iSum);
}
long time_now()
{
struct timeval now;
long lPassed;
gettimeofday(&now,0);
lPassed = now.tv_sec * 1000000 + now.tv_usec;
return lPassed;
}
char * host;
char * prog;
extern errno;
long lSendTime;
u_short seq;
int iTimeOut;
int sock,sent,recvd,max,min,total;
u_long lHostIp;
struct sockaddr_in it;
struct timeval now;
int ping();
void stat();
main(int argc, char ** argv)
{
struct hostent * h;
char buf[200];
char dst_host[32];
int i,namelen;
IPHEAD * pIpHead;
ICMPHEAD * pIcmpHead;
int normalSize = 0;
int times = 0;
if(argc<2){
printf("usage: %s [-timeout] host|IPn",argv[0]);
exit(0);
}
//printf("argc: %d argv: %s",argc,*(argv+1));
prog = argv[0];
host = argc == 2?argv[1]:argv[2];
iTimeOut = argc == 2?1:atoi(argv[1]);
if((sock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))<0){
perror("socket");
exit(2);
}
bzero(&it, sizeof(it));
it.sin_family = AF_INET;
if((lHostIp = inet_addr(host))!= INADDR_NONE){
it.sin_addr.s_addr = lHostIp;
strcpy(dst_host,host);
}
else if(h = gethostbyname(host)){
bcopy(h->h_addr,&it.sin_addr,h->h_length);
sprintf(dst_host,"%s(%s)",host,inet_ntoa(it.sin_addr));
}
else{
fprintf(stderr,"bad IP or hostn");
exit(3);
}
namelen = sizeof(it);
i = IP_HEADSIZE+ICMP_HEADSIZE+sizeof(long);
printf("npinging %s, send %d bytesnn",dst_host,i);
seq = 0;
sigset(SIGINT,stat);
sigset(SIGALRM,ping);
alarm(iTimeOut);
ping();
for(;;){
register size;
register u_char ttl;
register delta;
register iIpHeadLen;
size = recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr *)&it,&namelen);
if(size == -1 ){// errno == EINTR){
// printf("recvrrom failed, size is %dn",size);
continue;
}
delta = (int)((time_now() - lSendTime));
pIpHead = (IPHEAD *)buf;
iIpHeadLen = (int)((pIpHead->ip_verlen&0xf)<<2);
normalSize = iIpHeadLen + ICMP_HEADSIZE;
if(size<normalSize){
// printf("size of iIPHeadLen + ICMP_HEADSIZE error: size is %dn",size);
continue;
}
ttl = pIpHead->ip_ttl;
pIcmpHead = (ICMPHEAD *)(buf+iIpHeadLen);
if(pIcmpHead->icmp_type != ICMP_ECHOREPLY){
// printf("ICMP_ECHOREPLY errorn");
continue;
}
if(pIcmpHead->icmp_id!=seq||pIcmpHead->icmp_seq!=seq){
// printf("icmp_id != seqn");
continue;
}
sprintf(buf,"icmp_seq=%u bytes=%d ttl=%d",pIcmpHead->icmp_seq,size,ttl);
printf("---myping--- reply from %s: %s time=%.3f msn",host,buf,(float)delta/1000);
max = MAX(delta,max);
min = min<delta?MAX(delta,min):delta;
total += delta;
++recvd;
++seq;
if(times == 3){
stat();
break;
}
times++;
}
}
ping()
{
char buf[200];
int iPacketSize;
int tag = -1;
ICMPHEAD * pIcmpHead = (ICMPHEAD *)buf;
pIcmpHead->icmp_type = ICMP_ECHO;
pIcmpHead->icmp_code = 0;
pIcmpHead->icmp_id = seq;
pIcmpHead->icmp_seq = seq;
pIcmpHead->icmp_chksum = 0;
*((long*)pIcmpHead->icmp_data)=time_now();
iPacketSize = ICMP_HEADSIZE +4;
pIcmpHead->icmp_chksum = ChkSum((u_short *)pIcmpHead,iPacketSize);
lSendTime = time_now();
tag = sendto(sock,buf,iPacketSize,0,(struct sockaddr *)&it,sizeof(it));
if(tag<0){
printf("nmy_ping send failedn");
exit(6);
}
++sent;
alarm(iTimeOut);
}
void stat()
{
if(sent){
printf("n----%s ping statistics summerized by Digger----n",host);
printf("%d packets sent, %d packets received, %.2f%% lostn",
sent,recvd,(float)(sent-recvd)/(float)sent*100);
}
if(recvd){
printf("round_trip min/avg/max: %d/%d/%d msnn",min,total/recvd,max);
}
exit(0);
}