Click here to Skip to main content
13,735,397 members
Click here to Skip to main content
Add your own
alternative version


41 bookmarked
Posted 29 May 2002

Trace Utility to Trace IP Packet Path

, 29 May 2002
Rate this:
Please Sign up or sign in to vote.
Using the ICMP protocol to trace the routing of packets.


The Trace utility traces the path of an IP packet. To understand the process, its important to understand ICMP protocol we are going to use for this purpose.

ICMP Protocol

The Internet Protocol (IP) is used for host-to-host datagram service in a system of interconnected networks. Occasionally a destination host will communicate with a source host, for example, to report an error in datagram processing. For such purposes the Internet Control Message Protocol (ICMP), is used. ICMP, uses the basic support of IP as if it were a higher level protocol, however, ICMP is actually an integral part of IP, and must be implemented by every IP module.

ICMP messages are sent in several situations: for example, when a datagram cannot reach its destination, when the gateway does not have the buffering capacity to forward a datagram, and when the gateway can direct the host to send traffic on a shorter route.

The Internet Protocol is not designed to be absolutely reliable. The purpose of these control messages is to provide feedback about problems in the communication environment, not to make IP reliable. There are still no guarantees that a datagram will be delivered or a control message will be returned. Some datagrams may still be undelivered without any report of their loss. The higher level protocols that use IP must implement their own reliability procedures if reliable communication is required.

The ICMP messages typically report errors in the processing of datagrams. To avoid the infinite regress of messages about messages etc., no ICMP messages are sent about ICMP messages. Also ICMP messages are only sent about errors in handling fragment zero of fragemented datagrams. (Fragment zero has the fragment offeset equal zero).

Basics of the Trace utility

Apart from other fields each ICMP header consists of a field called Time to Live (TTL). TTL field is decremented at each machine in which the datagram is processed. Thus if my packet routes through Machine A-> Machine B-> Machine C, and if I set initial TTL to 3 then TTL at B would be 2 and at C would be 1. If the gateway processing a datagram finds TTL field is zero it discards the datagram. The gateway also notifies the source host via the time exceeded message.

Thus to get our utility working we send a packet containing echo request to the destination machine with increasing number of TTL starting from 1. Each time TTL goes to zero the machine that was currently processing datagram returns the packet with time exceeded message. We remeber the ip of this machine and send the packet back with incremented TTL. We repeat this till we successfully receive an echo reply.

You can compile the .cs file on command line by command

csc Trace.cs

and run it


The Code

*    Class:        Trace
*    Description:  Traces path of an ip packet with its respond time
*    Author:       Sanjay Ahuja
*    Date:         5/15/2002
*    Copyright©:   © 2002, Sanjay Ahuja ( Use it 
*                  as you want till you leave my name intact

using System;
using System.Net;
using System.Net.Sockets;

//ICMP constants
struct ICMPConstants
    public const int ICMP_ECHOREPLY= 0;     // Echo reply query
    public const int ICMP_TIMEEXCEEDED= 11; // TTL exceeded error
    public const int ICMP_ECHOREQ=    8;    // Echo request query
    public const int MAX_TTL= 256;          // Max TTL

//ICMP header, size is 8 bytes
struct ICMP
    public byte    type;           // Type
    public byte    code;           // Code
    public ushort  checksum;       // Checksum
    public ushort  id;             // Identification
    public ushort  seq;            // Sequence

// ICMP Echo Request, size is 12+ 32 (PACKET_SIZE as 
// defined in class Trace)= 44 bytes
struct REQUEST
    public ICMP    m_icmp;
    public byte    []m_data;

class Trace
    const int PACKET_SIZE= 32;

    public static void Main(string[] args)
            //verify command line
            if(args.Length== 0)
                Console.WriteLine("usage: trace <hostname>");

            //Create Raw ICMP Socket 
            Socket s= new Socket(AddressFamily.InterNetwork, 
                                 SocketType.Raw, ProtocolType.Icmp);
            IPEndPoint ipdest= new IPEndPoint(
            IPEndPoint ipsrc= new IPEndPoint(Dns.GetHostByName(
            EndPoint epsrc= (EndPoint)ipsrc;
            ICMP ip= new ICMP();
            ip.type = ICMPConstants.ICMP_ECHOREQ; 
            ip.code = 0;
            ip.checksum = 0;

            //any number you feel is kinda unique :)
   = (ushort)DateTime.Now.Millisecond;    
            ip.seq  = 0;
            REQUEST req= new REQUEST();
            req.m_icmp= ip;
            req.m_data = new Byte[PACKET_SIZE];
            //Initialize data
            for (int i = 0; i < req.m_data.Length; i++)
                req.m_data[i] = (byte)'S';

            //this function would gets byte array from the REQUEST structure
            Byte[] ByteSend= CreatePacket(req);

            //send requests with increasing number of TTL
            for(int ittl=1; ittl<= ICMPConstants.MAX_TTL; ittl++)
                Byte[] ByteRecv = new Byte[256];
                //Socket options to set TTL and Timeouts 
                                  SocketOptionName.IpTimeToLive, ittl);

                //Get current time
                DateTime dt= DateTime.Now;
                //Send Request
                int iRet= s.SendTo(ByteSend, ByteSend.Length, SocketFlags.None, 
                //check for Win32 SOCKET_ERROR
                if(iRet== -1)
                    Console.WriteLine("error sending data");

                iRet= s.ReceiveFrom(ByteRecv, ByteRecv.Length, 
                                    SocketFlags.None, ref epsrc);

                //Calculate time required
                TimeSpan ts= DateTime.Now- dt;;

                //check if response is OK
                if(iRet== -1)
                    Console.WriteLine("error getting data");

                Console.WriteLine("TTL= {0,-5} IP= {1,-20} Time= {2,3}ms",
                                  ittl, ((IPEndPoint)epsrc).Address,
                //reply size should be sizeof REQUEST + 20 (i.e sizeof IP header),
                //it should be an echo reply and id should be same
                if((iRet == PACKET_SIZE+ 8 +20)&& 
                    (BitConverter.ToInt16(ByteRecv,24) == 
                    (ByteRecv[20] == ICMPConstants.ICMP_ECHOREPLY))
                //time out
                if(ByteRecv[20] != ICMPConstants.ICMP_TIMEEXCEEDED)
                    Console.WriteLine("unexpected reply, quitting...");
        catch(SocketException e)
        catch(Exception e)


    public static byte[] CreatePacket( REQUEST req )
        Byte[] ByteSend= new Byte[PACKET_SIZE+ 8];
        //Create Byte array from REQUEST structure
        ByteSend[0]= req.m_icmp.type;
        ByteSend[1]= req.m_icmp.code;
                   0, ByteSend, 2, 2);
                   0, ByteSend, 4, 2);
                   0, ByteSend, 6, 2);
        for(int i=0; i< req.m_data.Length; i++)
            ByteSend[i+8]= req.m_data[i];

        //calculate checksum
        int iCheckSum = 0;
        for (int i= 0; i < ByteSend.Length; i+= 2) 
            iCheckSum += Convert.ToInt32( BitConverter.ToUInt16(ByteSend,i));

        iCheckSum = (iCheckSum >> 16) + (iCheckSum & 0xffff);
        iCheckSum += (iCheckSum >> 16);

        //update byte array to reflect checksum 
        Array.Copy(BitConverter.GetBytes((ushort)~iCheckSum), 0, 
                   ByteSend, 2, 2);
        return ByteSend;


Questions? Send them to me at


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Sanjay Ahuja
United States United States
Sanjay Ahuja is a Bachelor of Engineer and has completed his CDAC in Pune,India. He is currently working as a consultant for Verizon.

You may also be interested in...

Comments and Discussions

Generalplease help me .. Pin
microgroup20-Oct-07 23:40
membermicrogroup20-Oct-07 23:40 
Generalit doesnt work properly Pin
30-Jun-05 5:11
member30-Jun-05 5:11 
GeneralRe: it doesnt work properly Pin
culeadragos15-Feb-06 4:20
memberculeadragos15-Feb-06 4:20 
GeneralQuestion about your algoritm Pin
Mazdak3-Apr-03 19:53
memberMazdak3-Apr-03 19:53 
GeneralRe: Question about your algoritm Pin
Anonymous12-Apr-03 13:06
memberAnonymous12-Apr-03 13:06 
GeneralRe: Question about your algoritm Pin
dfhgesart3-Feb-05 4:13
memberdfhgesart3-Feb-05 4:13 
GeneralRe: Question about your algoritm Pin
shahzad ahmad butt12-Apr-06 4:33
membershahzad ahmad butt12-Apr-06 4:33 
GeneralNice article and a question Pin
Mazdak6-Mar-03 19:17
memberMazdak6-Mar-03 19:17 
GeneralRe: Nice article and a question Pin
Anonymous12-Apr-03 13:03
memberAnonymous12-Apr-03 13:03 

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.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web04-2016 | 2.8.180920.1 | Last Updated 30 May 2002
Article Copyright 2002 by Sanjay Ahuja
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid