Connectionless socket server programming using ICMP protocol

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Hi,
I have written connection less socket server and client, using ICMP protocol, though client and server are able to communicate with other, when I look at ICMPHeader values at the server side, they are zero: (TYPE,CODE,ID,SEQ,CHECKSUM,DATA)..
Environment that I am working : Window7 operating system and Visual studio 2005..langauge:C++/VC++
Socket functions used : Rawsockets, ICMP protocol, bind, sendto, recvfrom
also attached some code for both server and client at the bottom..
Objective : The connectionless socket server should able to respond to client, At the server side I should able see all the values that are sent by the client...
As of now, though client and server are able to communicate with other, but values for ICMP header are received as zero..
so I am sending all structures, that are I am passing through sendto function., I have also used #pragma pack(1) too, also struct member alignment as 1 Byte (/Zp1).. even then values are not reaching to the server..same thing when I send
values
back from the server to client, so when I look at ehereal window, it shows echoreply for both echo-request/echo-reply
I like to know, whether I have to do any other structure alignment, so that values packed with structure reaches server
vice versa... Could you please help me on this, as I am seriously working on a project ...


At the server side the following structures are used:
<pre>//Header file declarations..
#pragma pack(1)

#define REQ_DATASIZE 27 // Echo Request Data size

typedef struct tagIPHDR
{
u_char version; // version number
u_char TOS; // Type Of Service
u_short TotLen; // Total Length
u_short ID; // Identification
u_short FlagOff; // Flags and Fragment Offset
u_char TTL; // Time To Live
u_char Protocol; // Protocol
u_short Checksum; // Checksum
struct in_addr iaSrc; // Internet Address - Source
struct in_addr iaDst; // Internet Address - Destination
}IPHDR, *PIPHDR;

// ICMP Header - RFC 792
typedef struct tagICMPHDR
{
u_char Type; // Type
u_char Code; // Code
u_short Checksum; // Checksum
u_short ID; // Identification
u_short Seq; // Sequence
char Data; // Data
}ICMPHDR, *PICMPHDR;

// ICMP Echo Reply..
typedef struct tagECHOREPLY
{
IPHDR ipHdr;
ICMPHDR icmpHdr;
DWORD dwTime;
char cData[REQ_DATASIZE];
char cFiller[256];
}ECHOREPLY,*PECHOREPLY;

//ICMP Echo Request...
typedef struct tagECHOREQUEST
{
ICMPHDR icmpHdr;
DWORD dwTime;
char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;
#pragma pack()

//cpp file
bool OnInitializeSocketENV()
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2,0);
//init Winsock session will be called only once..
static int startup = WSAStartup(wVersionRequested,&wsaData);
if(startup)
{
printf("Errot initializing winsockn");
return false;
}
//Here it is checking for version requested...
if(wsaData.wVersion != wVersionRequested)
{
printf("Error winsock version not supportedn");
return false;
}
return true;
}
//Here it creates the socket object...
bool OnCreateSocket(SOCKET& rawSocket)
{
rawSocket = socket(AF_INET, SOCK_RAW,IPPROTO_ICMP);
if(rawSocket == NULL)
{
printf("Socket creation failre..n");
return false;
}
return true;
}

//Here it binds the socket..
bool BindSocket(SOCKET& rawSocket)
{
//Here preparation is done to bind the socket.
objServAddress.sin_addr.s_addr = INADDR_ANY;
objServAddress.sin_family = AF_INET;
objServAddress.sin_port = 0;
//Here it binds the socket...
int nRetValue = bind(rawSocket,(struct sockaddr*)&objServAddress,sizeof(objServAddress));
if(nRetValue == SOCKET_ERROR)
{
printf("Socket binding is failedn");
closesocket(rawSocket);
rawSocket = NULL;
return false;
}
return true;
}

//Here it receives the echo message
bool RecvEchoMessage(SOCKET& rawSocket)
{
ECHOREPLY echoReply;

int nAddrLen = sizeof(struct sockaddr_in);
int nRet;

//char on=1;
//setsockopt(rawSocket,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));
if((nRet = recvfrom(rawSocket,(LPSTR)&echoReply,sizeof(ECHOREPLY),0,(struct sockaddr *)&objClientAddress,
&nAddrLen)) > 0)
{
printf("nEcho is received from..: %sn",inet_ntoa(objClientAddress.sin_addr));
printf("n..............IPHEADER INFO.........................n");
printf("size of IPHeder=%dn",sizeof(echoReply.ipHdr));
printf("IP Header Version :%dn",echoReply.ipHdr.version);
printf("Type of service :%dn",echoReply.ipHdr.TOS);
printf("TTL :%dn",echoReply.ipHdr.TTL);

//Here it sends the echo request..
if(echoReply.ipHdr.Protocol == IPPROTO_ICMP)
printf("It is a ICMP protocol %dn",echoReply.ipHdr.Protocol);
else
printf("It is not a ICMP protocol:%dn",echoReply.ipHdr.Protocol);

printf("Here is source address :%sn",inet_ntoa(echoReply.ipHdr.iaSrc));
printf("Here is destination address:%sn",inet_ntoa(echoReply.ipHdr.iaDst));

printf("nn..............ICMP HEADER INFO.........................n");
printf("Message Type...: %dn",echoReply.icmpHdr.Type);
printf("Message Code...: %dn",echoReply.icmpHdr.Code);
printf("ID.............: %dn",echoReply.icmpHdr.ID);
printf("SEQ............: %dn",echoReply.icmpHdr.Seq);
printf("CHECKSUM.......: %dn",echoReply.icmpHdr.Checksum);
printf("DATA sent......: %sn",echoReply.cData);

//Here it constructs the echo reply and sends the same back to the client
ECHOREQUEST echoReq;
int nId = 1;
int nSeq = 1;
int nRet,nIndex;

//Fill in echo request..
echoReq.icmpHdr.Type = ICMP_ECHOREPLY;
echoReq.icmpHdr.Code = 0;
echoReq.icmpHdr.Checksum = 0;
echoReq.icmpHdr.ID = nId++;
echoReq.icmpHdr.Seq = nSeq++;
//Fill in some data to send..
for(nIndex = 0; nIndex < REQ_DATASIZE-1; nIndex++)
{
echoReq.cData[nIndex] = a+nIndex;
}
//save tick count when sent..
echoReq.dwTime = GetTickCount();
//Put data in packet and compute checksum
echoReq.icmpHdr.Checksum = in_cksum((u_short*)&echoReq,sizeof(ECHOREQUEST));

if((nRet = sendto(rawSocket,(LPSTR)&echoReq,sizeof(ECHOREQUEST),0,(struct sockaddr *)&objClientAddress,
nAddrLen)) > 0)
{
printf("nReply is sent to...:%sn",inet_ntoa(objClientAddress.sin_addr));
}
}
if(nRet == SOCKET_ERROR)
{
int nError = WSAGetLastError();
printf("Failure while sending and receiving data, Error:%dn",nError);
return false;
}
printf("Received value is...:%d",nRet);
return true;
}[/code]
<br/>
At the client side , the following code is used:
<div style="color:Black;background-color:White; <pre>
Client Header File....

#pragma pack(1)

<span style="color:Green; //IP Header
<span style="color:Blue; typedef <span style="color:Blue; struct tagIPHDR
{
<span style="color:Blue; unsigned <span style="color:Blue; char Version;
<span style="color:Blue; unsigned <span style="color:Blue; char TOS;
<span style="color:Blue; unsigned <span style="color:Blue; short TotLen;
<span style="color:Blue; unsigned <span style="color:Blue; short ID;
<span style="color:Blue; unsigned <span style="color:Blue; short FlagOff;
<span style="color:Blue; unsigned <span style="color:Blue; char TTL;
<span style="color:Blue; unsigned <span style="color:Blue; char Protocol;
<span style="color:Blue; unsigned <span style="color:Blue; short Checksum;
<span style="color:Blue; struct in_addr iaSrc; <span style="color:Green; // Internet Address - Source
<span style="color:Blue; struct in_addr iaDst; <span style="color:Green; // Internet Address - Destination

} IPHDR, *PIPHDR;

<span style="color:Green; //ICMP Header
<span style="color:Blue; typedef <span style="color:Blue; struct tagICMPHDR
{
<span style="color:Blue; unsigned <span style="color:Blue; char Type;
<span style="color:Blue; unsigned <span style="color:Blue; char Code;
<span style="color:Blue; unsigned <span style="color:Blue; short Checksum;
<span style="color:Blue; unsigned <span style="color:Blue; short ID;
<span style="color:Blue; unsigned <span style="color:Blue; short Seq;
<span style="color:Blue; char cData;
}ICMPHDR, *PICMPHDR;

<span style="color:Green; //ICMP Echo Request..
<span style="color:Blue; typedef <span style="color:Blue; struct tagECHOREQUEST
{
IPHDR ipHdr;
ICMPHDR icmpHdr;
DWORD dwTime;
<span style="color:Blue; char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;

<span style="color:Green; //ICMP Echo Reply..
<span style="color:Blue; typedef <span style="color:Blue; struct tagECHOREPLY
{
IPHDR ipHdr;
ICMPHDR icmpHdr;
DWORD dwTime;
<span style="color:Blue; char cData[REQ_DATASIZE];
<span style="color:Blue; char cFiller[256];
}ECHOREPLY,*PECHOREPLY;

#pragma pack()

Client VisualCPP FILe..
<span style="color:Green; //Here it initializes the socket environment..
<span style="color:Blue; bool CICMPClientDlg::Initialize(<span style="color:Blue; void)
{
<span style="color:Blue; static WSADATA wsaData;
<span style="color:Blue; static WORD wVersionRequested = MAKEWORD(2,0);

<span style="color:Green; //init Winsock session will be called only once..
<span style="color:Blue; static <span style="color:Blue; int startup = WSAStartup(wVersionRequested,&wsaData);
<span style="color:Blue; if(startup)
{
afxDump << <span style="color:#A31515; "Errot initializing winsockn";
AfxMessageBox(_T(<span style="color:#A31515; "Error initializing winsock"));
<span style="color:Blue; return <span style="color:Blue; false;

}
<span style="color:Green; //if requested version does not match the
<span style="color:Blue; if(wsaData.wVersion != wVersionRequested)
{
afxDump << <span style="color:#A31515; "Error winsock version not supportedn";
AfxMessageBox(_T(<span style="color:#A31515; "winsock version not supported"));
<span style="color:Blue; return <span style="color:Blue; false;
}
<span style="color:Blue; return <span style="color:Blue; true;
}
<span style="color:Green; //Here it creates the socket...
<span style="color:Blue; bool CICMPClientDlg::CreateSOCKET(SOCKET& rawSocket)
{
rawSocket = socket(AF_INET, SOCK_RAW,IPPROTO_ICMP);
<span style="color:Blue; if(SOCKET_ERROR == rawSocket)
{
TRACE(<span style="color:#A31515; "Error while creating a socketn");
AfxMessageBox(_T(<span style="color:#A31515; "Failed while creating a socket"));
rawSocket = NULL;
<span style="color:Blue; return <span style="color:Blue; false;
}
<span style="color:Blue; return <span style="color:Blue; true;
}

<span style="color:Green; //Here it sends the echorequest..
<span style="color:Blue; bool CICMPClientDlg::SendEchoRequest(CString& strIPAddress,SOCKET& objRawSocket)
{
<span style="color:Blue; bool bIsEchoSent = <span style="color:Blue; true;

<span style="color:Blue; try{
<span style="color:Blue; static ECHOREQUEST echoReq;
<span style="color:Blue; int nId = 1;
<span style="color:Blue; int nSeq = 1;
<span style="color:Blue; int nRet,nIndex;
CStringA strIpAddr(strIPAddress);

<span style="color:Blue; char on=1;
setsockopt(objRawSocket,IPPROTO_IP,IP_HDRINCL,(<span style="color:Blue; char *)(LPINT)on,<span style="color:Blue; sizeof(<span style="color:Blue; int));

<span style="color:Green; //Send the echo request..
sockaddr_in objSockDest;
objSockDest.sin_addr.s_addr = ::inet_addr(strIpAddr);
objSockDest.sin_family = AF_INET;
objSockDest.sin_port = htons(0);
<span style="color:Green; //Fill in echo request..
echoReq.icmpHdr.Type = 8; <span style="color:Green; //ICMP_ECHOREQ;
echoReq.icmpHdr.Code = 0;
echoReq.icmpHdr.Checksum = 0;
echoReq.icmpHdr.ID = htons (nId++);
echoReq.icmpHdr.Seq = htons ( nSeq++);
<span style="color:Green; //Fill in some data to send..
<span style="color:Blue; for(nIndex = 0; nIndex < REQ_DATASIZE-1; nIndex++)
{
echoReq.cData[nIndex] = +nIndex;
}
<span style="color:Green; //save tick count when sent..
echoReq.dwTime = GetTickCount();
<span style="color:Green; //Put data in packet and compute checksum
echoReq.icmpHdr.Checksum = in_cksum((u_short*)&echoReq,<span style="color:Blue; sizeof(ECHOREQUEST));

<span style="color:Green; //Here it sends data on rawsocket..
nRet = sendto(objRawSocket, <span style="color:Green; //socket
(<span style="color:Blue; const <span style="color:Blue; char*)&echoReq, <span style="color:Green; //buffer
<span style="color:Blue; sizeof(ECHOREQUEST), <span style="color:Green; //size of request
0, <span style="color:Green; //flags
(SOCKADDR*)&objSockDest, <span style="color:Green; //destination
<span style="color:Blue; sizeof(objSockDest)); <span style="color:Green; //address length

afxDump << <span style="color:#A31515; "Size of the data is:" << nRet <<<span style="color:#A31515; "n";
<span style="color:Blue; if(nRet == SOCKET_ERROR)
{
afxDump << <span style="color:#A31515; "Failure while receiving datan";
bIsEchoSent = <span style="color:Blue; false;
}
}
<span style="color:Blue; catch(...)
{
bIsEchoSent = <span style="color:Blue; false;
}
<span style="color:Blue; return bIsEchoSent;
}

<span style="color:Green; //Here it receives the echo reply
<span style="color:Blue; bool CICMPClientDlg::RecvEchoMessage(SOCKET& rawSocket)
{
ECHOREPLY echoReply;
<span style="color:Blue; int nAddrLen = <span style="color:Blue; sizeof(<span style="color:Blue; struct sockaddr_in);
<span style="color:Blue; int nRet;
sockaddr_in objServerAddress;

<span style="color:Blue; if((nRet = recvfrom(rawSocket,(LPSTR)&echoReply,<span style="color:Blue; sizeof(ECHOREPLY),0,(<span style="color:Blue; struct sockaddr *)&objServerAddress,
&nAddrLen)) > 0)
{

<span style="color:Blue; char* strInetAddr = inet_ntoa(objServerAddress.sin_addr);
afxDump << <span style="color:#A31515; "Echoreply is received from..:"<<strInetAddr <<<span style="color:#A31515; "n";

afxDump << <span style="color:#A31515; "Message Type...:" <<echoReply.icmpHdr.Type << <span style="color:#A31515; "n";
afxDump << <span style="color:#A31515; "Message Code...:" << echoReply.icmpHdr.Code << <span style="color:#A31515; "n";

afxDump << <span style="color:#A31515; "IP Header Version :" << echoReply.ipHdr.Version << <span style="color:#A31515; "n";
afxDump << <span style="color:#A31515; "Type of service :" << echoReply.ipHdr.TOS << <span style="color:#A31515; "n";
afxDump << <span style="color:#A31515; "TTL : " << echoReply.ipHdr.TTL << <span style="color:#A31515; "n";

<span style="color:Green; //Here it sends the echo request..
<span style="color:Blue; if(echoReply.ipHdr.Protocol == IPPROTO_ICMP)
afxDump << <span style="color:#A31515; "It is a ICMP protocol:" << echoReply.ipHdr.Protocol<< <span style="color:#A31515; "n";
<span style="color:Blue; else
afxDump << <span style="color:#A31515; "It is not a ICMP protocol:" << echoReply.ipHdr.Protocol<< <span style="color:#A31515; "n";

afxDump << <span style="color:#A31515; "Here is source address :" << inet_ntoa(echoReply.ipHdr.iaSrc)<< <span style="color:#A31515; "n";
afxDump << <span style="color:#A31515; "Here is destination address:" << inet_ntoa(echoReply.ipHdr.iaDst)<< <span style="color:#A31515; "n";
}
<span style="color:Blue; else <span style="color:Blue; if(nRet == SOCKET_ERROR)
{
afxDump << <span style="color:#A31515; "Failure while receiving data:n" << WSAGetLastError();
<span style="color:Blue; return <span style="color:Blue; false;
}
<span style="color:Blue; return <span style="color:Blue; true;
}
[/code]
<br/>
Regards
Lakkan





<hr class="sig Narayana Reddy.L

View the full article
 
Back
Top