Traceroute using UDP and ICMP

This is a discussion on Traceroute using UDP and ICMP within the C++ Programming forums, part of the General Programming Boards category; I'm trying to write code for a traceroute program for a project. That is , a program that will trace ...

  1. #1
    Unregistered
    Guest

    Traceroute using UDP and ICMP

    I'm trying to write code for a traceroute program for a project. That is , a program that will trace the path of a packet from a source to a destination.

    THEORY -> I'm using UDP, IP and ICMP protocols to implement the traceroute program. I'm sending a UDP packet to a high port (Eg. 33434) on a remote computer and it should reply with an ICMP Destination Unreachable Message (Type=3), Port Unreachable (Type 3) message. Contained within this ICMP message is the address of the remote host. In this way I can get the IP of each computer along the path by varying the TTL value from 1 to 255 until the destination is reached.

    MY PROBLEM -> I am trying to send a UDP packet to a high port (33434) to my local machine which should give me an ICMP reply. However I'm getting a RawIP reply, the original IP header and the contents of the original UDP packet as the reply when I'm supposed to get an IP Header, the ICMP Header(Type 3), and the first 64-bits of the original UDP datagram, as the reply.
    I can't figure out what I'm doing wrong!

    CODE -> This is the code I have so far that gives the wrong reply
    as described above in "MY PROBLEM".
    The code is distributed among 5 files -> "IcmpHeader.h", "IpHeader.h", "PseudoHeader.h", "UdpHeader.h" and "Driver.cpp"

    Does anyone know how to fix this? Any help will be greatly appreciated.
    Thanks.

    (! Please use MSVC++6 and link with ws2_32.lib !)


    /******************** IcmpHeader.h ******************/

    #ifndef ICMP_HEADER
    #define ICMP_HEADER


    struct IcmpHeader
    {
    unsigned char Type;
    unsigned char Code;
    unsigned short Checksum;
    };



    #endif





    /******************* UdpHeader.h*******************/


    #ifndef UDP_HEADER
    #define UDP_HEADER


    struct UdpHeader
    {
    unsigned short SourcePort;
    unsigned short DestinationPort;
    unsigned short Length;
    unsigned short Checksum;
    unsigned long ID; // Data part of UDP header...
    };

    #endif



    /*************** PseudoHeader.h******************/

    #ifndef PSEUDO_HEADER
    #define PSEUDO_HEADER


    struct PseudoHeader
    {
    unsigned long SourceAddress;
    unsigned long DestinationAddress;
    unsigned char Useless;
    unsigned char Protocol;
    unsigned short Length;
    };

    #endif



    /****************** IpHeader.h*******************/


    #ifndef IP_HEADER
    #define IP_HEADER


    struct IpHeader
    {
    unsigned char Version_IHL;
    unsigned char TypeOfService; // Type of service
    unsigned short TotalLength; // total length of the packet
    unsigned short ID; // unique identifier
    unsigned short Flags_Offset; // Flags and Fragment Offset
    unsigned char TimeToLive; // TTL
    unsigned char Protocol; // protocol (TCP, UDP etc)
    unsigned short HeaderChecksum; // IP checksum
    in_addr SourceIP; // Senders address
    in_addr DestinationIP; // Recipient's address
    };


    #endif



    /******************* Driver.cpp *******************/

    #include <iostream>
    using namespace std;


    #include <winsock2.h>

    #include "IcmpHeader.h"
    #include "IpHeader.h"
    #include "UdpHeader.h"
    #include "PseudoHeader.h"

    // Prototypes...
    void sendPacketX();
    char* getProtocolName(unsigned char);
    unsigned short getChecksum(unsigned short*, int);
    void printIpHeaderInfo(IpHeader*);
    void printIcmpHeaderInfo(IcmpHeader*);
    void printPacketInfo(char*);
    void printUdpInfo(UdpHeader*);


    int main()
    {
    sendPacketX();
    return 0;
    }


    unsigned short getChecksum(unsigned short* buffer, int size)
    {
    unsigned long cksum=0;

    while(size >1)
    {
    cksum += *buffer++;
    size -=sizeof(unsigned short);
    }

    if(size )
    {
    cksum += *(unsigned char*)buffer;
    }

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

    return (unsigned short)(~cksum);

    }


    void printUdpInfo(UdpHeader* h)
    {
    cout << "********************* UDP INFO *******************" << endl << endl;
    cout << "Source Port = " << (int)htons(h->SourcePort) << endl;
    cout << "Dest Port = " << (int)htons(h->DestinationPort) << endl;
    cout << "Length = " << (int)h->Length << endl;
    cout << "Checksum = " << (int)h->Checksum << endl;
    cout << "ID = " << h->ID << endl;
    }

    void printPacketInfo(char* buffer)
    {
    IpHeader* h1 = (IpHeader*)buffer;
    int ihl1 = (h1->Version_IHL & 15) * 4;
    printIpHeaderInfo(h1);

    IpHeader* h2 = (IpHeader*)(buffer + ihl1);
    int ihl2 = (h2->Version_IHL & 15) * 4;
    printIpHeaderInfo(h2);


    UdpHeader* udp = (UdpHeader*)(buffer + ihl1 + ihl2);
    printUdpInfo(udp);

    }


    void printIpHeaderInfo(IpHeader* i)
    {

    cout << "**************** IP Header Info *************" << endl;
    cout << "Version = " << (int)(i->Version_IHL >> 4) << endl;
    cout << "IHL = " << (int)(i->Version_IHL & 15) << endl;
    cout << "Type Of Service = " << (int)(i->TypeOfService) << endl;
    cout << "Total Length = " << (i->TotalLength) << endl;
    cout << "ID = " << (i->ID) << endl;
    cout << "Flags = " << (i->Flags_Offset >> 5) << endl;
    cout << "Fragment Offset = " << (i->Flags_Offset & 31) << endl;
    cout << "Time to Live = " << (int)(i->TimeToLive) << endl;
    cout << "Protocol = " << (int)(i->Protocol) << endl;
    cout << "Protocol Name = " << getProtocolName(i->Protocol) << endl;
    cout << "Header Checksum = " << (int)(i->HeaderChecksum) << endl;
    cout << "Source IP = " << inet_ntoa(i->SourceIP) << endl;
    cout << "Destination IP = " << inet_ntoa(i->DestinationIP) << endl;
    cout << endl << endl << endl;

    }



    void printIcmpHeaderInfo(IcmpHeader* e)
    {
    cout << "**************** ICMP Packet Info *************" << endl;
    cout << "Type = " << (int)e->Type << endl;
    cout << "Code = " << (int)e->Code << endl;
    cout << "Checksum = " << (int)e->Checksum << endl;
    }



    char* getProtocolName(unsigned char value)
    {
    switch(value)
    {
    case 0: return "IP";
    case 1: return "ICMP";
    case 2: return "IGMP";
    case 3: return "Gateway";
    case 6: return "TCP";
    case 12: return "PUP";
    case 17: return "UDP";
    case 22: return "XND IDP";
    case 77: return "Net Disk";
    case 255: return "Raw IP";
    }

    return "???";
    }



    void sendPacketX()
    {

    const int PACKET_SIZE = sizeof(IpHeader) + sizeof(UdpHeader);

    // Allocate memory for the UDP packet...
    char* packet = new char[PACKET_SIZE];

    // Clear the contents of the packet...
    memset( (void*)packet, 0, PACKET_SIZE);

    // Get pointers to the Ip and Udp headers...
    IpHeader* ip = (IpHeader*)packet;
    UdpHeader* udp = (UdpHeader*)(packet + sizeof(IpHeader));

    in_addr dest, source;
    dest.s_addr = inet_addr("127.0.0.1");
    source.s_addr = inet_addr("127.0.0.1");


    // Fill the IpHedaer info...
    ip->Version_IHL = 69; // Version=4, IHL=5
    ip->TimeToLive = 245;
    ip->ID = htons(123);
    ip->Protocol = 17;
    ip->DestinationIP.s_addr = dest.s_addr;
    ip->SourceIP.s_addr = source.s_addr;
    ip->TotalLength = htons(PACKET_SIZE);
    ip->HeaderChecksum = getChecksum( (unsigned short*)packet, sizeof(IpHeader));


    // Create the UDP header...
    udp->ID = 99716120; // Fill data part of UdpHeader...
    udp->Checksum = 0; // Checksum must be 0 initially..
    udp->Length = 40;
    udp->SourcePort = htons(5000);
    udp->DestinationPort = htons(33434);

    char* packet_checksum = new char[sizeof(UdpHeader) + sizeof(PseudoHeader)];

    PseudoHeader* ph = (PseudoHeader*)packet_checksum;
    ph->Useless = 0;
    ph->DestinationAddress = dest.s_addr;
    ph->SourceAddress = source.s_addr;
    ph->Protocol = 17;
    ph->Length = htons(40);

    memcpy(packet_checksum + sizeof(PseudoHeader), udp, sizeof(UdpHeader));

    udp->Checksum = getChecksum( (unsigned short*)packet_checksum, sizeof(UdpHeader) + sizeof(PseudoHeader) );


    sockaddr_in peer;
    peer.sin_family = AF_INET;
    peer.sin_addr.s_addr = dest.s_addr;


    WSADATA wsa;
    if( WSAStartup( MAKEWORD(2, 2), &wsa) != 0 )
    {
    cout << "Could not find ws2_32.dll" << endl;
    exit(1);
    }


    int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);

    if(sock == INVALID_SOCKET)
    {
    cout << "Invalid socket!" << endl;
    exit(2);
    }

    int sent = sendto(sock, packet, PACKET_SIZE, 0, (sockaddr*)&peer, sizeof(peer) );

    if(sent == SOCKET_ERROR)
    {
    cout << "Error sending data!" << endl;
    exit(3);
    }

    else if(sent < 0)
    {
    cout << "sent < 0" << endl;
    exit(5);
    }

    else
    {
    cout << sent << " bytes of data sent!" << endl;
    }



    sockaddr from;
    int from_length = sizeof(from);
    char* buffer = new char[1024];
    int received;

    do
    {
    received = recvfrom(sock, buffer, 1024, 0, &from, &from_length);

    if(received == SOCKET_ERROR)
    {
    cout << "Error in receiving data" << endl;
    exit(4);
    }

    else
    {
    cout << received << " bytes of data received!" << endl;
    printPacketInfo(buffer);
    break;
    }

    }
    while(received > 20);


    }



    /**************** RESULTS OF PROGRAM ****************/


    32 bytes of data sent!
    52 bytes of data received!
    **************** IP Header Info *************
    Version = 4
    IHL = 5
    Type Of Service = 0
    Total Length = 13312
    ID = 60419
    Flags = 0
    Fragment Offset = 0
    Time to Live = 128
    Protocol = 255
    Protocol Name = Raw IP
    Header Checksum = 56631
    Source IP = 127.0.0.1
    Destination IP = 127.0.0.1



    **************** IP Header Info *************
    Version = 4
    IHL = 5
    Type Of Service = 0
    Total Length = 8192
    ID = 31488
    Flags = 0
    Fragment Offset = 0
    Time to Live = 245
    Protocol = 17
    Protocol Name = UDP
    Header Checksum = 20423
    Source IP = 127.0.0.1
    Destination IP = 127.0.0.1



    ********************* UDP INFO *******************

    Source Port = 5000
    Dest Port = 33434
    Length = 40
    Checksum = 3898
    ID = 99716120


    Any help will be greatly appreciated.
    Thanks.

  2. #2
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    I can't help you directly, but I can suggest a couple of things.

    - What OS are you using, and what version of Winsock? It appears that a limit level of raw packet processing is supported by ony some versions of Windows.
    - There's an FAQ for Winsock here that contains some good information.
    - If you're going to post code here, please use code tags.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Obtaining source & destination IP,details of ICMP Header & each of field of it ???
    By cromologic in forum Networking/Device Communication
    Replies: 1
    Last Post: 04-29-2006, 02:49 PM
  2. Can TCP sockets also receive ICMP...?
    By failure_to in forum Networking/Device Communication
    Replies: 3
    Last Post: 06-09-2004, 10:36 AM
  3. Traceroute using UDP + ICMP
    By Unregistered in forum Windows Programming
    Replies: 0
    Last Post: 08-05-2002, 10:50 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21