Main Page | Class List | File List | Class Members | File Members

icmp.cpp

Go to the documentation of this file.
00001 // icmp.cpp
00002 
00003 #include "icmp.h"
00004 
00005 const char* ICMPDATATEMPLATE  = "abcdefghijklmnopqrstuvw";
00006 
00007 void FillICMPData(char* pData, int size)
00008 {
00009   while (size)
00010   {
00011     const char* pszTemplate = ICMPDATATEMPLATE;
00012     while (*pszTemplate && size)
00013     {
00014       *pData = *pszTemplate;
00015       size--;
00016       pszTemplate++;
00017       pData++;
00018     }
00019   }
00020 }
00021 
00022 USHORT IPChecksum(USHORT* pBuffer, int nSize)
00023 {
00024   unsigned long cksum = 0;
00025 
00026   while (nSize > 1) 
00027   {
00028     cksum += *pBuffer++;
00029     nSize -= sizeof(USHORT);
00030   }
00031   
00032   if (nSize) 
00033     cksum += *(UCHAR*)pBuffer;
00034 
00035   cksum = (cksum >> 16) + (cksum & 0xffff);
00036   cksum += (cksum >> 16);
00037   return (USHORT)(~cksum);
00038 }
00039 
00040 void EncodePacket(char* pPacket, int iDataSize, USHORT uSequence)
00041 {
00042   ICMP_HEADER* pIcmp = (ICMP_HEADER*)pPacket;
00043   pIcmp->type = ICMP_ECHO_REQUEST;
00044   pIcmp->code = 0;
00045   pIcmp->id = (USHORT)GetCurrentProcessId();
00046   pIcmp->seq = uSequence;
00047   char* pData = ((char*)pIcmp) + sizeof(ICMP_HEADER);
00048   FillICMPData(pData+sizeof(LONGLONG), iDataSize-sizeof(LONGLONG));
00049   pIcmp->cksum = 0;
00050   // Embed timer tick in first bytes
00051   LARGE_INTEGER starttick;
00052   QueryPerformanceCounter(&starttick);
00053   *(LONGLONG*)pData = starttick.QuadPart;
00054   pIcmp->cksum = IPChecksum((USHORT*)pIcmp, sizeof(ICMP_HEADER) + iDataSize);
00055 }
00056 
00057 bool DecodePacket(char* pPacket, int iSize, USHORT& uSequence, LONGLONG& llTick)
00058 {
00059   IP_HEADER* pIPHeader = (IP_HEADER*)pPacket;
00060   int iIpHdrlen = pIPHeader->h_len * 4; //Number of 32-bit words*4 = bytes
00061   if (iSize < iIpHdrlen + (int)sizeof(ICMP_HEADER))
00062     return false;
00063 
00064   ICMP_HEADER* pIcmpHdr = (ICMP_HEADER*) (((char*) pIPHeader) + iIpHdrlen);
00065   char* pData = pPacket + iIpHdrlen + sizeof(ICMP_HEADER);
00066   //int iDataSize = iSize - iIpHdrlen - sizeof(ICMP_HEADER);
00067   USHORT uCksumPacket = pIcmpHdr->cksum;
00068   pIcmpHdr->cksum = 0;
00069   USHORT cksum = IPChecksum((USHORT*)pPacket, iSize);
00070   pIcmpHdr->cksum = uCksumPacket;
00071   if (cksum != uCksumPacket)
00072     return false;
00073 
00074   switch(pIcmpHdr->code)
00075   {
00076     case ICMP_ECHO_REPLY:
00077       if (pIcmpHdr->id == (USHORT)GetCurrentProcessId())
00078       {
00079         uSequence = pIcmpHdr->seq;
00080         // First data bytes are send tick
00081         llTick = *(LONGLONG*)pData;
00082         return true;
00083       }
00084       break;
00085     case ICMP_DESTINATION_UNREACHABLE:
00086       // Destination is unreachable and no response is gathered
00087       break;
00088     case ICMP_TIME_EXCEEDED:
00089       // No response is gathered
00090       break;
00091   }
00092   return false;
00093 }

Generated on Sun Jun 26 13:43:46 2005 for pingem by  doxygen 1.4.3