I need to fix in my code, I can not later add, bust network route using a socket.
The program must identify all computers connected to the network no matter the topology.
*/
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
typedef struct _PseudoHeader
{
unsigned int SourceAddress;
unsigned int DestinationAddress;
unsigned char Zeros;
unsigned char Proto;
unsigned short Length;
} PseudoHeader;
typedef PseudoHeader FAR * LPPseudoHeader;
typedef struct _IPHeader
{
unsigned char ip_header_len:4;
unsigned char ip_version :4;
unsigned char ip_tos;
unsigned short ip_total_length;
unsigned short ip_id;
unsigned short ip_frag_offset;
unsigned char ip_ttl;
unsigned char ip_protocol;
unsigned short ip_checksum;
unsigned int ip_srcaddr;
unsigned int ip_destaddr;
} IPHeader;
typedef struct icmp_hdr
{
unsigned char type;
unsigned char code;
unsigned short checksum;
unsigned short id;
unsigned short seq;
} ICMP_HDR;
typedef struct udp_hdr
{
unsigned short source_port;
unsigned short dest_port;
unsigned short udp_length;
unsigned short udp_checksum;
} UDP_HDR;
typedef struct udppacket
{
UDP_HDR udp;
char messg[35];
} UDP_PACKET;
typedef struct icmppacket
{
ICMP_HDR icmp;
DWORD dwTime;
char cData[35];
} ICMP_PACKET;
typedef struct traceinfo
{
int packetid;
int ttl;
int proto;
int size;
unsigned long saddr;
unsigned long daddr;
} TRACE_INFO;
static int ICMP_SEQNO;
const int UDP_DEST_PORTNO = 33434;
const int FALLBACK_TO_ICMP = 1;
int DESTINATION_UNREACHABLE = 0;
int MAX_CONQ_ICMP_TIMEOUT = 2;
int latency;
unsigned short CalculateChecksum(unsigned short *usBuf, int iSize)
{
unsigned long usChksum=0;
while (iSize>1)
{
usChksum+=*usBuf++;
iSize-=sizeof(unsigned short);
}
if (iSize)
usChksum+=*(unsigned char*)usBuf;
usChksum=(usChksum >> 16) + (usChksum & 0xffff);
usChksum+=(usChksum >> 16);
return (unsigned short)(~usChksum);
}
unsigned short CalculatePseudoChecksum(char *buf, int BufLength,unsigned long dest,unsigned long src)
{
LPPseudoHeader lpPseudo;
int PseudoHeaderLength = sizeof(PseudoHeader);
lpPseudo = new PseudoHeader;
lpPseudo->DestinationAddress = dest;
lpPseudo->SourceAddress = src;
lpPseudo->Zeros = 0;
lpPseudo->Proto = 0x11;
lpPseudo->Length = htons(BufLength);
int iTotalLength;
iTotalLength = PseudoHeaderLength+BufLength;
char* tmpBuf;
tmpBuf=new char[iTotalLength];
memcpy(tmpBuf,lpPseudo,PseudoHeaderLength);
memcpy(tmpBuf+PseudoHeaderLength,buf,BufLength);
unsigned short usChecksum;
usChecksum = CalculateChecksum((unsigned short*)tmpBuf,iTotalLength);
delete tmpBuf;
delete lpPseudo;
return usChecksum;
}
int gethostaddr( char* pszHost,sockaddr_in& dest)
{
memset( &dest, 0, sizeof( dest ) );
unsigned int addr = inet_addr( pszHost );
if( addr != INADDR_NONE )
{
dest.sin_addr.s_addr = addr;
dest.sin_family = AF_INET;
}
else
{
hostent* hp = gethostbyname( pszHost );
if ( hp != 0 )
{
memcpy( &(dest.sin_addr), hp->h_addr, hp->h_length );
dest.sin_family = hp->h_addrtype;
}
else
{
printf("Failed to resolve %s\n", pszHost);
return -1;
}
}
return 0;
}
int IsSocketReadible(SOCKET &s)
{
struct timeval Timeout;
fd_set readfds;
readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;
return(select(1, &readfds, NULL, NULL, &Timeout));
}
int ProcessIpPacket (IPHeader *iphdr, unsigned long dest)
{
unsigned short iphdrlen;
sockaddr_in source;
iphdrlen = iphdr->ip_header_len*4;
static no_hops;
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = iphdr->ip_srcaddr;
if(!DESTINATION_UNREACHABLE || (source.sin_addr.s_addr == dest))
printf("\n %2d %4d ms %15s \n", ++no_hops, latency, inet_ntoa(source.sin_addr));
if(source.sin_addr.s_addr == dest)
return(1);
return(0);
}
int ProcessIcmpPacket(char* Buffer , int Size, unsigned long dest)
{
unsigned short iphdrlen;
int dest_reached = -1;
IPHeader *iphdr = (IPHeader *)Buffer;
iphdrlen = iphdr->ip_header_len*4;
ICMP_HDR *icmpheader=(ICMP_HDR*)(Buffer+iphdrlen);
if((unsigned int)(icmpheader->type)==11)
;
else if((unsigned int)(icmpheader->type)==0)
;
else if((unsigned int)(icmpheader->type)==3)
DESTINATION_UNREACHABLE = 1;
dest_reached = ProcessIpPacket(iphdr,dest);
return dest_reached;
}
int ProcessPacket(char* Buffer, int size, unsigned long dest)
{
IPHeader *ip = (IPHeader *)Buffer;
int dest_reached = -1;
switch (ip->ip_protocol)
{
case 1:
dest_reached = ProcessIcmpPacket(Buffer,size,dest);
break;
case 2:
break;
case 6:
break;
case 17:
break;
default:
break;
}
return dest_reached;
}
int processResponse(SOCKET &s, unsigned long dest)
{
char Buffer[1500];
int mangobyte;
int dest_reached = -1;
if (Buffer == NULL)
{
printf("malloc() failed.\n");
return dest_reached;
}
mangobyte = recvfrom(s,Buffer,sizeof(Buffer),0,0,0);
if(mangobyte > 0)
dest_reached = ProcessPacket(Buffer, mangobyte, dest);
else
{
printf( "recvfrom() failed.\n");
}
return dest_reached;
}
void construct_ip_hdr(char *pack_data,TRACE_INFO trace)
{
memset(pack_data,0,trace.size);
int size = sizeof(pack_data);
IPHeader *ip = (IPHeader *)(pack_data);
ip->ip_version = 4;
ip->ip_header_len = 5;
ip->ip_tos = 0x0;
ip->ip_total_length = htons(trace.size);
ip->ip_frag_offset = 0x0;
ip->ip_protocol = trace.proto;
ip->ip_destaddr = trace.daddr;
ip->ip_srcaddr = trace.saddr;
ip->ip_checksum = 0;
ip->ip_id = htons(trace.packetid);
ip->ip_ttl = trace.ttl;
}
int construct_proto_pack(char *packdata,TRACE_INFO trace)
{
IPHeader *ip = (IPHeader *)(packdata);
int packet_length = -1;
static portincr = 0;
construct_ip_hdr(packdata,trace);
if(trace.proto == IPPROTO_UDP)
{
if(portincr > 100)
portincr = 0;
UDP_PACKET *udp_pack = (UDP_PACKET *) (ip + 1);
strcpy(udp_pack->messg, "Hello there!");
udp_pack->udp.dest_port = htons(UDP_DEST_PORTNO + portincr++);
udp_pack->udp.source_port = htons(0);
udp_pack->udp.udp_checksum = 0;
udp_pack->udp.udp_length = htons(sizeof(*udp_pack));
int udp_hdr_n_data_len = sizeof(*udp_pack);
packet_length = ((int)(ip + 1) - (int)ip) + udp_hdr_n_data_len;
ip->ip_total_length = packet_length;
udp_pack->udp.udp_checksum = CalculatePseudoChecksum((char *)udp_pack,udp_hdr_n_data_len,trace.daddr,trace.saddr);
}
else if(trace.proto == IPPROTO_ICMP)
{
ICMP_PACKET *icmp_pack = (ICMP_PACKET *) (ip + 1);
icmp_pack->icmp.code = 0;
icmp_pack->icmp.type = 8;
icmp_pack->icmp.checksum = 0;
icmp_pack->icmp.id = ICMP_SEQNO;
icmp_pack->icmp.seq = ICMP_SEQNO++;
icmp_pack->dwTime = GetTickCount();
strcpy(icmp_pack->cData, "Hello there!");
int icmp_hdr_n_data_len = sizeof(*icmp_pack);
packet_length = ((int)(ip + 1) - (int)ip) + icmp_hdr_n_data_len;
ip->ip_total_length = packet_length;
icmp_pack->icmp.checksum = CalculateChecksum((USHORT *)icmp_pack,icmp_hdr_n_data_len);
}
else
return (-1);
return(packet_length);
}
void settraceinfo(TRACE_INFO &traceinfo,int packetid,int ttl,int proto,unsigned long dest, unsigned long src, int size)
{
traceinfo.packetid = packetid;
traceinfo.ttl = ttl;
traceinfo.proto = proto;
traceinfo.saddr = src;
traceinfo.daddr = dest;
traceinfo.size = size;
}
int main(int argc, char* argv[])
{
sockaddr_in dest, src;
TRACE_INFO traceinfo;
char data[100];
char hostname[70];
ICMP_SEQNO = 1;
WSAData wsaData;
int char_size = sizeof(unsigned char);
if(!(argc == 2))
{
printf("Usage: %s %s \n",argv[0],"target_name");
return 1;
}
if (WSAStartup(MAKEWORD(2, 1), &wsaData) != 0)
{
printf("Failed to find Winsock 2.1 or better");
return 1;
}
SOCKET sock = socket(AF_INET, SOCK_RAW,IPPROTO_IP);
if(sock == INVALID_SOCKET) {
printf("\nCouldn't create socket");
return 1;
}
int on = 1;
if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (const char *)&on, sizeof(on)) == SOCKET_ERROR) {
printf("\nCouldn't set IP_HDRINCL");
return 1;
}
if(gethostaddr(argv[1],dest) < 0)
{
printf("\n Couldn't resolve host %s \n", argv[1]);
return 1;
}
if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR)
{
printf("\nCannot retrieve hostname");
return 1;
}
if(gethostaddr(hostname,src) < 0)
{
return 1;
}
int packetid = GetCurrentProcessId();
int written = 0;
int proto = IPPROTO_UDP;
int pack_size = sizeof(data);
int sockreadible = 0;
int dest_reached = 0;
int count = 0;
int timed_out_cnt = 0;
ULONG RequestTime = 0;
ULONG ResponseTime = 0;
printf("\n Tracing route to %s [%s] \n", argv[1], inet_ntoa(dest.sin_addr));
while(dest_reached == 0)
{
settraceinfo(traceinfo, packetid + count, count+1, proto, dest.sin_addr.s_addr, src.sin_addr.s_addr, pack_size);
if((pack_size = construct_proto_pack(data, traceinfo)) > 0)
{
RequestTime = GetTickCount();
written = sendto(sock,data,pack_size,0,(struct sockaddr *)&dest,sizeof(dest));
if (written == SOCKET_ERROR)
{
printf("\n Sending packet failed. Check permissions on this system");
printf("\n Admin rights are required on XP");
return 1;
}
sockreadible = IsSocketReadible(sock);
if(sockreadible)
{
timed_out_cnt = 0;
ResponseTime = GetTickCount();
latency = ResponseTime - RequestTime;
dest_reached = processResponse(sock,dest.sin_addr.s_addr);
if((DESTINATION_UNREACHABLE && (proto != IPPROTO_ICMP) && FALLBACK_TO_ICMP)) {
proto = IPPROTO_ICMP;
DESTINATION_UNREACHABLE = 0;
}
else if (DESTINATION_UNREACHABLE){
printf("\n Destination unreachable, so cannot proceed further");
return 1;
}
count ++;
}
else if(written > 0 && proto == IPPROTO_ICMP)
{
timed_out_cnt ++;
if(timed_out_cnt >= MAX_CONQ_ICMP_TIMEOUT) {
printf("\n Request has timed out even after %d hops, so not proceeding further\n",MAX_CONQ_ICMP_TIMEOUT);
return 1;
}
else {
printf("\n Request timed out");
count ++;
}
}
else if(written > 0 && FALLBACK_TO_ICMP)
{
if(proto != IPPROTO_UDP)
count ++;
proto = IPPROTO_ICMP;
}
else if(FALLBACK_TO_ICMP == 0)
count ++;
}
}
closesocket(sock);
WSACleanup();
return 0;
}