Ping source code

Source: Internet
Author: User
Ping source code-general Linux technology-Linux programming and kernel information. The following is a detailed description. /* PING. C
/*
/* Ping source code distribute by cpu | digger.
/* For unix family only. compil and link success in sco unix.
/* I think linux no problem too. u can try it.
/* Before read this code, you shoud know about the principle
/* TCP/IP, especially icmp protocol, u also shoshould also know some
/* About BSD socket API, and unix system signal programming.
/*
/* Cc-o ping. c-lsocket, then u will get executable file,
/* But must act as root when cc it, and then set euid attribute
/* For this ping, then u can execute it as common user.
/* Because only root can have authority to creat raw socket.
/*
/* I love socket, if so do u,
/* Call me, cpu = digger

# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include

# Define ICMP_ECHO 8/* icmp echo requir */
# Define ICMP_ECHOREPLY 0/* icmp echo reply */
# Define ICMP_HEADSIZE 8/* icmp packet header size */
# Define IP_HEADSIZE 20/* ip packet header size */

Typedef struct tagIpHead/* icmp packet header */
{
U_char ip_verlen;/* ip version and ip header lenth */
U_char ip_tos;/* ip type of service */
U_short ip_len;/* ip packet lenghth */
U_short ip_id;/* ip packet identification */
U_short ip_fragoff;/* ip packet fragment and offset */
U_char ip_ttl;/* ip packet time to live */
U_char ip_proto;/* ip packet protocol type */
U_short ip_chksum;/* ip packet header checksum */
U_long ip_src_addr;/* ip source ip adress */
U_long ip_dst_addr;/* ip destination ip adress */
} IPHEAD;

Typedef struct tagIcmpHead/* icmp header */
{
U_char icmp_type;/* icmp service type */
/* 8 echo require, 0 echo reply */
U_char icmp_code;/* icmp header code */
U_short icmp_chksum;/* icmp header chksum */
U_short icmp_id;/* icmp packet identification */
U_short icmp_seq;/* icmp packet sequent */
U_char icmp_data [1];/* icmp data, use as pointer */
} ICMPHEAD;

U_short ChkSum (u_short * pIcmpData, int iDataLen)
/* For check sum of icmp header */
{
U_short iSum;
U_short iOddByte;

ISum = 0;

While (iDataLen> 1) {/* xor the next unsigned int data */
ISum ^ = * pIcmpData ++;
IDataLen-= 2;
}

If (iDataLen = 1) {/* the rest odd byte */
IOddByte = 0;
* (U_char *) & iOddByte) = * (u_char *) pIcmpData;
ISum ^ = iOddByte;
}

ISum ^ = 0 xffff;/* xor 0 xffff = not it */
Return (iSum );
}

Long time_now ()/* return time passed */
/* Since 1970.1.1 00:00:00 ,*/
/* In 1/1000000 second */
{
Struct timeval now;
Long lPassed;
Gettimeofday (& now, 0 );
LPassed = now. TV _sec * 1000000 + now. TV _usec;
/* Now. TV _sec in second */
/* Now. TV _usec in 1/1000000 second */
Return lPassed;
}

Char * host;/* destination host */
Char * prog;/* program name */
Extern errno;/* system global parameter */
Long lSendTime;/* each time when send, change it */
U_short seq;/* the icmp packet seqence */
Int iTimeOut;/* time out parameter */
Int sock, sent, recvd, max, min, total;
/* Sent: icmp packet already sent */
/* Recvd: proper icmp packet already ed */
/* Max, min: max min round trip time */
/* Total: total round trip time */
/* Store to calculate average */
U_long lHostIp;/* host ip adress */
Struct sockaddr_in it;/* destination host information */

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;

If (argc <2) {/* ping the destination host */
/* Every timeout second */
/* Default timeout is 1 second */

Printf ("usage: % s [-timeout] host | IP \ n", argv [0]);
Exit (0 );
}
Prog = argv [0];
Host = argc = 2? Argv [1]: argv [2];
ITimeOut = argc = 2? 1: atoi (argv [1]);

/* Creat the raw socket for icmp */

If (sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) <0 ){
Perror ("socket ");
Exit (2 );
}

/* Set destination host information */

Bzero (& it, sizeof (it ));
It. sin_family = AF_INET;

/* Check host format */

If (lHostIp = inet_addr (host ))! = INADDR_NONE ){
/* Is available ip adress */
It. sin_addr.s_addr = lHostIp;
Strcpy (dst_host, host );
} Else if (h = gethostbyname (host )){
/* Is available host name */
/* From hosts file of local host */
/* Or from DNS */
Bcopy (h-> h_addr, & it. sin_addr, h-> h_length );
Sprintf (dst_host, "% s (% s)", host,
Inet_ntoa (it. sin_addr ));
} Else {
/* Bad ip adress or host name */
/* Exit */
Fprintf (stderr, "bad IP or host \ n ");
Exit (3 );
}
Namelen = sizeof (it );

Printf ("\ nDigger pinging % s, send % d bytes \ n ",
Dst_host,
IP_HEADSIZE + ICMP_HEADSIZE + sizeof (long)
);

Seq = 0;/* first icmp_seq = 0 */
Sigset (SIGINT, stat);/* when press del or ctrl + c, call stat */
/* To statistic the result, and then exit */
Sigset (SIGALRM, ping);/* hook ping function to timer */
Alarm (iTimeOut);/* start timer, call ping every timeout */
/* Seconds */
Ping ();
For (;) {/* waiting for every echo back */
/* Icmp packet and check it */
Register size;
Register u_char ttl;
Register delta;
Register iIpHeadLen;

/* Block to received echo back datax */

Size = recvfrom (sock, buf, sizeof (buf), 0,
(Struct sockaddr *) & it, & namelen );
If (size =-1 & errno = EINTR ){
/* Receive error or system call */
/* Interrupted */
Continue;
}

/* Calculate the round trip time ,*/
/* Time when receive minus time when send */

Delta = (int) (time_now ()-lSendTime)/1000 );

/* Get echo back packet and check its ip header */

PIpHead = (IPHEAD *) buf;

/* Get the ip packet lenth */
/* If too small, not the icmp echoreply packet */
/* Give it up */

IIpHeadLen = (int) (pIpHead-> ip_verlen & 0x0f) <2 );
If (size <iIpHeadLen + ICMP_HEADSIZE ){
Continue;
}
Ttl = pIpHead-> ip_ttl;/* time to live param */

/* Get the icmp header information */
PIcmpHead = (ICMPHEAD *) (buf + iIpHeadLen );

/* Not icmp echo reply packet, give it up */
If (pIcmpHead-> icmp_type! = ICMP_ECHOREPLY ){
Continue;
}

/* Not proper icmp sequent number, give it up */
If (pIcmpHead-> icmp_id! = Seq | pIcmpHead-> icmp_seq! = Seq ){
Continue;
}

/* Print out result for each icmp */
/* Echo reply information */
Sprintf (buf, "icmp_seq = % u bytes = % d ttl = % d ",
PIcmpHead-> icmp_seq, size, ttl );
Fprintf (stderr, "reply from % s: % s time = % d ms \ n ",
Host, buf, delta );

/* Calculate some statistic information */
/* Max, min, average round trip time */
/* Received icmp echo reply packet numbers */
Max = MAX (delta, max );
Min = min? MIN (delta, min): delta;
Total + = delta;
++ Recvd;

/* For next icmp sequence */

++ Seq;
}
}

Ping ()
{
Char buf [200];
Int iPacketSize;

/* Make the icmp header information */

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;

/* Store time information as icmp packet content, 4 bytes */
/* U may store other information instead */

* (Long *) pIcmpHead-> icmp_data) = time_now ();

IPacketSize = ICMP_HEADSIZE + 4;/* icmp packet length */

/* Icmp header check sum */

PIcmpHead-> icmp_chksum = ChkSum (u_short *) pIcmpHead,
IPacketSize );

/* Remember the time when send for calculate round trip time */
LSendTime = time_now ();

/* Send the icmp packet to des host */
If (sendto (sock, buf, iPacketSize, 0, (struct sockaddr *) & it,
Sizeof (it) <0 ){
Perror ("send failed ");
Exit (6 );
}

/* Packet number been sent */
++ Sent;

/* Reset the timer hooker to me again */
Alarm (iTimeOut );
}

Void stat ()/* print the statistic information for this time's ping */
{
If (sent ){
Printf ("\ n ----- % s ping statistics summerized by Digger ----- \ n"
, Host );
Printf ("% d packets sent, % d packets received, %. 2f % lost \ n ",
Sent, recvd, (float) (sent-recvd)/(float) sent * 100 );
}
If (recvd ){
Printf ("round_trip min/avg/max: % d/% d ms \ n ",
Min, total/recvd, max );
}
Exit (0 );
}
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.