#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <setjmp.h>
#include <errno.h>
#define PACKET_SIZE 4096
#define MAX_WAIT_TIME 5
#define Max_no_packets 3
Char Sendpacket[packet_size];
Char Recvpacket[packet_size];
int sockfd,datalen=56;
int nsend=0,nreceived=0;
struct sockaddr_in dest_addr;
pid_t pid;
struct sockaddr_in from;
struct Timeval tvrecv;
void statistics (int signo);
unsigned short cal_chksum (unsigned short *addr,int len);
int pack (int pack_no);
void Send_packet (void);
void Recv_packet (void);
int unpack (char *buf,int len);
void Tv_sub (struct timeval *out,struct timeval *in);
void statistics (int signo)
{
printf ("\ n--------------------PING statistics-------------------\ n");
printf ("%d packets transmitted,%d received,%%%d lost\n", nsend,nreceived, (nsend-nreceived)/nsend*100);
Close (SOCKFD);
Exit (1);
}
/* CHECKSUM algorithm */
unsigned short cal_chksum (unsigned short *addr,int len)
{
int Nleft=len;
int sum=0;
unsigned short *w=addr;
unsigned short answer=0;
/* Add the ICMP header binary data in 2-byte increments. */
while (nleft>1)
{
sum+=*w++;
nleft-=2;
}
/* If the ICMP header is an odd number of bytes, the last byte is left. Treats the last byte as a high byte of 2 bytes of data,
The low byte of this 2-byte data is 0 and continues to accumulate */
if (nleft==1)
{
* (unsigned char *) (&answer) =* (unsigned char *) W;
Sum+=answer;
}
Sum= (sum>>16) + (SUM&0XFFFF);
sum+= (SUM>>16);
Answer=~sum;
return answer;
}
/* Set ICMP header */
int pack (int pack_no)
{
int i,packsize;
struct ICMP *icmp;
struct Timeval *tval;
icmp= (struct icmp*) sendpacket;
icmp->icmp_type=icmp_echo;
icmp->icmp_code=0;
icmp->icmp_cksum=0;
icmp->icmp_seq=pack_no;
icmp->icmp_id=pid;
Packsize=8+datalen;
tval= (struct timeval *) icmp->icmp_data;
Gettimeofday (Tval,null); /* Record Send time */
Icmp->icmp_cksum=cal_chksum ((unsigned short *) icmp,packsize); /* Validation Algorithm */
return packsize;
}
/* Send three ICMP messages */
void Send_packet ()
{
int packetsize;
while (Nsend)
{
nsend++;
Packetsize=pack (Nsend); /* Set ICMP header */
if (SendTo (sockfd,sendpacket,packetsize,0, (struct sockaddr *) &dest_addr,sizeof (DEST_ADDR)) <0)
{
Perror ("SendTo error");
Continue
}
Sleep (1); /* Send an ICMP message every second */
}
}
/* Receive all ICMP messages */
void Recv_packet ()
{
int N,fromlen;
extern int errno;
Signal (sigalrm,statistics);
Fromlen=sizeof (from);
while (nreceived)
{
Alarm (max_wait_time);
if ((N=recvfrom (sockfd,recvpacket,sizeof (Recvpacket), 0, (struct sockaddr *) &from,&fromlen))
{
if (ERRNO==EINTR) continue;
Perror ("Recvfrom error");
Continue
}
Gettimeofday (&tvrecv,null); /* Record receive time */
if (Unpack (recvpacket,n) ==-1);
Continue
nreceived++;
}
}
/* peel off the ICMP header */
int unpack (char *buf,int len)
{
int I,iphdrlen;
struct IP *ip;
struct ICMP *icmp;
struct Timeval *tvsend;
Double RTT;
ip= (struct IP *) buf;
iphdrlen=ip->ip_hl<<2; /* For IP header length, that is, the length of the IP header is marked by 4*/
icmp= (struct ICMP *) (Buf+iphdrlen); /* Cross the IP header, point to the ICMP header */
Len-=iphdrlen; /*ICMP header and the total length of the ICMP datagram */
if (len<8)/* Less than ICMP header length is unreasonable */
{
printf ("ICMP packets\ ' s length is less than 8\n");
return-1;
}
/* Make sure to receive the ICMP response I sent.
if ((icmp->icmp_type==icmp_echoreply) && (icmp->icmp_id==pid))
{
tvsend= (struct timeval *) icmp->icmp_data;
Tv_sub (&tvrecv,tvsend); /* Time difference to receive and send */
rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000; /* Calculates rtt*/in milliseconds
/* Show relevant information */
printf ("%d bytes from%s:icmp_seq=%u ttl=%d rtt=%.3f ms\n",
Len,inet_ntoa (FROM.SIN_ADDR), Icmp->icmp_seq,ip->ip_ttl,rtt);
}
else return-1;
}
int main (int argc,char *argv[])
{
struct Hostent *host;
struct Protoent *protocol;
unsigned long inaddr=0l;
int waittime=max_wait_time;
int size=50*1024;
if (argc<2)
{
printf ("usage:%s hostname/ip address\n", argv[0]);
Exit (1);
}
if ((Protocol=getprotobyname ("ICMP") ==null)
{
& nbsp; perror ("Getprotobyname");
exit (1);
}
/* Generates an original socket using ICMP, which is only rooted to generate */
if ((Sockfd=socket (af_inet,sock_ Raw,protocol->p_proto) <0)
{
perror (" Socket error ");
exit (1);
}
/* Recover root permissions, set current user rights */
setuid (Getuid ());
/* Widening socket receive buffer to 50K this is done primarily to reduce the likelihood of a receive buffer overflow
, if you inadvertently ping a broadcast address or multicast address, you will receive a large number of responses */
setsockopt (sockfd,sol_socket,so_rcvbuf,&size,sizeof (size));
bzero (&dest_addr,sizeof (DEST_ADDR));
dest_addr.sin_family=af_inet;
/* Determines whether the host name or IP address */
if ((Inaddr=inet_addr (argv[1))) ==inaddr_none)
{
if ((Host=gethostbyname (argv[1)) ==null)/* is host name */
{
Perror ("gethostbyname error");
exit (1);
}
memcpy ((char *) &dest_addr.sin_addr,host->h_addr,host->h _length);
}
else/* is the IP address */
memcpy ((char *) &dest_addr, (char *) &inaddr,host->h_length);
Else
DEST_ADDR.SIN_ADDR.S_ADDR=INADDR;
/* Gets the process ID of main, which sets the identifier for the ICMP */
Pid=getpid ();
printf ("PING%s (%s):%d bytes data in ICMP packets.\n", Argv[1],
Inet_ntoa (DEST_ADDR.SIN_ADDR), datalen);
#if 0
while (1)
{
Send_packet (); /* Send all ICMP messages */
Recv_packet (); /* Receive all ICMP messages */
}
Statistics (SIGALRM); /* for Statistics */
#endif
return 0;
}
/* Subtract two timeval structures */
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;
}
/*-------------the End-----------*/