Click here to Skip to main content
15,881,852 members
Articles / Programming Languages / C++
Article

Ping and Traceroute

Rate me:
Please Sign up or sign in to vote.
4.83/5 (25 votes)
21 Feb 2008CPOL2 min read 136.4K   5.1K   65   25
In this article, we will see how Ping and Tracert networking tools work and we will create our own replicas for them.
Ping_and_Tracert_Codes

Ping

Ping is an old Unix utility which is pretty useful even today. The basic idea behind Ping is to find out whether the network is reachable and alive or not. Ping basically sends an ICMP echo request and then waits for an ICMP echo response; the roundtrip time is calculated from the time at which the request was sent and the time at which a response is received. For more information on ICMP, please see RFC 792.

To send out ICMP requests, we create a socket which will use ICMP as the protocol:

C++
SOCKET sock;

//Create a raw socket which will use ICMP
sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);

Now to send an ICMP request, first of all we populate the ICMP header structure:

C++
struct ICMPheader
{
    unsigned char    byType;
    unsigned char    byCode;
    unsigned short    nChecksum;
    unsigned short    nId;
    unsigned short    nSequence;
};

ICMPheader sendHdr;
sendHdr.byCode = 0;       //Zero for ICMP echo and reply messages

//Sequence number is incremented with each request, this should be different
//so we can match a response with a request
sendHdr.nSequence = htons (nSequence++);    
sendHdr.byType = 8;       //Eight for ICMP echo message
sendHdr.nChecksum = 0;    //Checksum is calculated later on

Next we fill the ICMP header and message data into a buffer to be sent out:

C++
//Create the message buffer, which is big enough to store the header and the 
//message data
pSendBuffer = new char [sizeof (ICMPheader) + nMessageSize];

//Copy the message header in the buffer
memcpy_s (pSendBuffer, sizeof (ICMPheader), &sendHdr, sizeof (ICMPheader));

//Fill the message with some arbitrary value
memset (pSendBuffer + sizeof (ICMPheader), 'x', nMessageSize);

Now we calculate the checksum of the ICMP header and the message being sent with it. The checksum for ICMP messages is calculated in the same way as for IP headers.

C++
//Calculate checksum over ICMP header and message data
sendHdr.nChecksum = 
    htons (CalcChecksum (pSendBuffer, sizeof (ICMPheader) + nMessageSize)); 
   
//Copy the message header back into the buffer
memcpy_s (pSendBuffer, sizeof (ICMPheader), &sendHdr, sizeof (ICMPheader));

We are all ready to send the ICMP echo request, so here we do that:

C++
nResult = sendto (sock, pSendBuffer, sizeof (ICMPheader) + 
            nMessageSize, 0, (SOCKADDR *)&dest, sizeof (SOCKADDR_IN));

With an ICMP request sent out, we now wait for the timeout interval (default is 5 seconds) to get a response. We use I/O socket model for this.

C++
timeval timeInterval = {0, 0};
//Set the timeout interval for the select call to expire
timeInterval.tv_usec = nTimeOut * 1000;

FD_ZERO (&fdRead);
FD_SET (sock, &fdRead);

select (0, &fdRead, NULL, NULL, &timeInterval);

If we get a response, then the response is parsed to see if it has the correct checksum, the sequence ID is the same as in the request which was sent out, etc. One point to note here is that the bytes received contain the IP header + ICMP header + message, so we need to take them out accordingly and then proceed. The following code explains it further:

C++
//We got a response so we construct the ICMP header and message out of it
ICMPheader recvHdr;
char *pICMPbuffer = NULL;

//The response includes the IP header as well, so we move 20 bytes ahead to 
//read the ICMP header
pICMPbuffer = pRecvBuffer + sizeof(IPheader);

//ICMP message length is calculated by subtracting the IP header size from 
//the total bytes received
int nICMPMsgLen = nResult - sizeof(IPheader);

//Construct the ICMP header
memcpy_s (&recvHdr, sizeof (recvHdr), pICMPbuffer, sizeof (recvHdr));

//Construct the IP header from the response
IPheader ipHdr;
memcpy_s (&ipHdr, sizeof (ipHdr), pRecvBuffer, sizeof (ipHdr));

recvHdr.nId = recvHdr.nId;
recvHdr.nSequence = recvHdr.nSequence;
recvHdr.nChecksum = ntohs (recvHdr.nChecksum);

//Check if the response is an echo reply, transaction ID and sequence number 
//are same as for the request, and that the checksum is correct
if (recvHdr.byType == 0 &&
    recvHdr.nId == sendHdr.nId &&
    recvHdr.nSequence == sendHdr.nSequence &&
    ValidateChecksum (pICMPbuffer, nICMPMsgLen) && 
memcmp (pSendBuffer + sizeof(ICMPheader), pRecvBuffer + sizeof(ICMPheader) + 
        sizeof(IPheader), nResult - sizeof (ICMPheader) - sizeof(IPheader)) == 0)
{
    //All's OK
    //So just calculate the round trip time and print it
}

And lastly, we repeat the above process (sending ICMP echo request and receiving responses) three or four times, as asked by the user, to calculate Ping statistics.

Tracert

Tracert is another networking utility which determines the route taken by packets across an IP network. The basic idea behind tracert is that it sends ICMP requests and increments their TTL value in the IP header by one on each request. The first request has a TTL of one, the next one two, and so on. When the first request reaches the next host, the host ignores the request and sends an ICMP time exceeded response. By seeing this response we are able to determine the host and thus able to produce a lists of hosts by sending incremented TTL values.

The code for Tracert is very similar to Ping. The only point of interest here is that we need to modify the IP header to change the TTL values. This is done using setsockopt with IPPROTO_IP and IP_TTL values as shown below:

C++
setsockopt (sock, IPPROTO_IP, IP_TTL, (char *)&nTTL, sizeof (nTTL));

Conclusion

I mainly wrote this article for learning purposes and I hope that the code in this article is useful to others as well. Please be kind enough to notify me about any mistakes or a better way to do things.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionif run os'ping will be get error Pin
qingye200826-Jun-13 20:13
qingye200826-Jun-13 20:13 
Generalclosesocket(sock); missing! Pin
StoneHead7-Dec-10 13:59
StoneHead7-Dec-10 13:59 
GeneralNice article - one problem Pin
SamNorris15-Apr-10 9:18
SamNorris15-Apr-10 9:18 
GeneralNEED HELP! An Error has occur in gethostbyname operaion: WSAGetLastError <> = 11004 Pin
bkimp1-Mar-10 22:09
bkimp1-Mar-10 22:09 
GeneralAnother ICMP packet Pin
welcomyou4-Nov-09 22:14
welcomyou4-Nov-09 22:14 
Questionregarding raw sockets Pin
N.siva subrahmanyam22-Oct-09 20:09
N.siva subrahmanyam22-Oct-09 20:09 
AnswerRe: regarding raw sockets Pin
welcomyou4-Nov-09 22:02
welcomyou4-Nov-09 22:02 
Generalcompile error Pin
alaa naeem2-Aug-09 5:58
alaa naeem2-Aug-09 5:58 
QuestionI couldn't execute the project !!! Please Help! Pin
mecrop2-Dec-08 14:46
mecrop2-Dec-08 14:46 
GeneralVista business version will fail Pin
owenskao25-Apr-08 2:35
owenskao25-Apr-08 2:35 
GeneralRe: Vista business version will fail Pin
youval vaknin28-Sep-08 5:20
youval vaknin28-Sep-08 5:20 
QuestionNetwork ping ???? Pin
wege26-Feb-08 23:42
wege26-Feb-08 23:42 
AnswerRe: Network ping ???? Pin
Hitesh Sharma28-Feb-08 3:43
Hitesh Sharma28-Feb-08 3:43 
AnswerRe: Network ping ???? Pin
Emilio Garavaglia10-Mar-08 7:47
Emilio Garavaglia10-Mar-08 7:47 
GeneralRe: Network ping ???? Pin
wege10-Mar-08 22:51
wege10-Mar-08 22:51 
GeneralRe: Network ping ???? Pin
Emilio Garavaglia12-Mar-08 0:48
Emilio Garavaglia12-Mar-08 0:48 
GeneralEmprovement suggestions Pin
Emilio Garavaglia22-Feb-08 2:02
Emilio Garavaglia22-Feb-08 2:02 
GeneralRe: Emprovement suggestions Pin
Hitesh Sharma22-Feb-08 2:25
Hitesh Sharma22-Feb-08 2:25 
Thanks, emilio_grv Smile | :) .

I was too lazy or wanted to keep things as simple to understand as possible Unsure | :~ . Anyways, you have explained the stuff so many thanks Smile | :) .
GeneralMessage Body Pin
Jeffrey Walton22-Feb-08 1:10
Jeffrey Walton22-Feb-08 1:10 
GeneralRe: Message Body Pin
Hitesh Sharma22-Feb-08 2:36
Hitesh Sharma22-Feb-08 2:36 
GeneralRe: Message Body Pin
ThatsAlok10-Mar-08 5:28
ThatsAlok10-Mar-08 5:28 
GeneralRe: Message Body Pin
Hitesh Sharma10-Mar-08 7:29
Hitesh Sharma10-Mar-08 7:29 
GeneralRe: Message Body Pin
ThatsAlok10-Mar-08 7:40
ThatsAlok10-Mar-08 7:40 
GeneralRe: Message Body Pin
Hitesh Sharma10-Mar-08 12:03
Hitesh Sharma10-Mar-08 12:03 
GeneralRe: Message Body Pin
ThatsAlok10-Mar-08 16:55
ThatsAlok10-Mar-08 16:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.