00001
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
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;
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
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
00081 llTick = *(LONGLONG*)pData;
00082 return true;
00083 }
00084 break;
00085 case ICMP_DESTINATION_UNREACHABLE:
00086
00087 break;
00088 case ICMP_TIME_EXCEEDED:
00089
00090 break;
00091 }
00092 return false;
00093 }