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.