From 955d4e00adc9f39ab93bf21f07506eb75b013c70 Mon Sep 17 00:00:00 2001 From: Michael Krelin Date: Mon, 05 Jul 2004 01:53:09 +0000 Subject: initial commit into svn repository git-svn-id: http://svn.klever.net/kin/T42/trunk@1 fe716a7a-6dde-0310-88d9-d003556173a8 --- (limited to 'shared-code/kICMP.cpp') diff --git a/shared-code/kICMP.cpp b/shared-code/kICMP.cpp new file mode 100644 index 0000000..09a8f94 --- a/dev/null +++ b/shared-code/kICMP.cpp @@ -0,0 +1,300 @@ +#include "../stdafx.h" +#include "kICMP.h" + +CICMP::_mechanismus CICMP::m_mechanismus = CICMP::_icmpUndetermined; + +BOOL CICMPDll::Initialize() +{ + if(m_hICMP!=INVALID_HANDLE_VALUE || m_hICMPDLL) + Deinitialize(); + m_hICMPDLL = ::LoadLibraryEx("ICMP",NULL,0); + if(!m_hICMPDLL) + return FALSE; + *(FARPROC*)&m_icmpCF = ::GetProcAddress(m_hICMPDLL,"IcmpCreateFile"); + *(FARPROC*)&m_icmpSE = ::GetProcAddress(m_hICMPDLL,"IcmpSendEcho"); + *(FARPROC*)&m_icmpCH = ::GetProcAddress(m_hICMPDLL,"IcmpCloseHandle"); + if(!(m_icmpCF && m_icmpSE && m_icmpCH)){ + Deinitialize(); return FALSE; + } + m_hICMP = (*m_icmpCF)(); + if(m_hICMP==INVALID_HANDLE_VALUE){ + Deinitialize(); return FALSE; + } + TRACE0("ICMP-DLL Initialized\n"); + return TRUE; +} +void CICMPDll::Deinitialize() +{ + if(m_hICMPDLL){ + if(m_hICMP!=INVALID_HANDLE_VALUE && m_icmpCH) + (*m_icmpCH)(m_hICMP); + ::FreeLibrary(m_hICMPDLL); m_hICMPDLL = NULL; + m_icmpCF = NULL; + m_icmpSE = NULL; + m_icmpCH = NULL; + } + m_hICMP=INVALID_HANDLE_VALUE; + if(m_sizeOut && m_bsOut){ + delete m_bsOut; + m_bsOut = NULL; m_sizeOut = 0; + } + if(m_sizeIn && m_bsIn){ + delete m_bsIn; + m_bsIn = NULL; m_sizeIn = 0; + } +} + +LONG CICMPDll::Ping(const in_addr host,const UINT packetSize, + const UINT timeOut,LPINT pStatus) +{ + if(!(m_hICMP && m_hICMPDLL && m_icmpSE)){ + if(pStatus) + (*pStatus) = icmpNotInitialized; + return -1; + } + VERIFY(AdjustBuffers(packetSize)); +IPINFO ipi; + memset(&ipi,0,sizeof(ipi)); + ipi.Ttl = 30; + for(UINT tmp=0;tmpStatus = 0xFFFFFFFFl; + if((*m_icmpSE)(m_hICMP,host.s_addr,m_bsOut,packetSize, + &ipi,pRep,m_sizeIn,timeOut)) + TRACE0("ICMP-SendEcho succeeded\n"); + else + TRACE0("ICMP-SendEcho failed\n"); +LONG lrv = -1; +INT rv = ipUnknown; + switch(pRep->Status){ + case IP_SUCCESS: + lrv = pRep->RTTime; rv = ipSuccess; + break; + case IP_BUF_TOO_SMALL: rv = ipBuffTooSmall; break; + case IP_DEST_NET_UNREACHABLE: rv = ipDestNetUnreachable; break; + case IP_DEST_HOST_UNREACHABLE: rv = ipDestHostUnreachable; break; + case IP_DEST_PROT_UNREACHABLE: rv = ipDestProtUnreachable; break; + case IP_DEST_PORT_UNREACHABLE: rv = ipDestPortUnreachable; break; + case IP_NO_RESOURCES: rv = ipNoResources; break; + case IP_BAD_OPTION: rv = ipBadOption; break; + case IP_HW_ERROR: rv = ipHWError; break; + case IP_PACKET_TOO_BIG: rv = ipPacketTooBig; break; + case IP_REQ_TIMED_OUT: rv = ipTimeOut; break; + case IP_BAD_REQ: rv = ipBadRequest; break; + case IP_BAD_ROUTE: rv = ipBadRoute; break; + case IP_TTL_EXPIRED_TRANSIT: rv = ipTTLExpiredInTransit; break; + case IP_TTL_EXPIRED_REASSEM: rv = ipTTLExpiredInReasm; break; + case IP_PARAM_PROBLEM: rv = ipParamProblem; break; + case IP_SOURCE_QUENCH: rv = ipSourceQuench; break; + case IP_OPTION_TOO_BIG: rv = ipOptionTooBig; break; + case IP_BAD_DESTINATION: rv = ipBadDest; break; + } + if(pStatus) + (*pStatus)=rv; + return lrv; +} + +BOOL CICMPDll::AdjustBuffers(UINT packetSize) +{ + if(!packetSize) + packetSize=1; + if(packetSize>m_sizeOut){ + if(m_sizeOut && m_bsOut) + delete m_bsOut; + m_bsOut = new BYTE[m_sizeOut=packetSize]; + if(!m_bsOut) + return FALSE; + } +UINT sin = sizeof(ICMPECHO)+SIZE_ICMP_HDR+packetSize; + if(sin>m_sizeIn){ + if(m_sizeIn && m_bsIn) + delete m_bsIn; + m_bsIn = new BYTE[m_sizeIn=sin]; + if(!m_bsIn) + return FALSE; + } + return TRUE; +} + + +WORD CICMPWS::m_icmpSeq = 0; + +BOOL CICMPWS::Initialize() +{ + if(m_socket!=INVALID_SOCKET) + Deinitialize(); + m_socket = socket(AF_INET,SOCK_RAW,1/*ICMP*/); + if(m_socket==INVALID_SOCKET) + return FALSE; + TRACE0("ICMP-WS Initialized\n"); + return TRUE; +} +void CICMPWS::Deinitialize() +{ + if(m_socket!=INVALID_SOCKET){ + closesocket(m_socket); + m_socket=INVALID_SOCKET; + } + if(m_sizeOut && m_bsOut){ + delete m_bsOut; + m_bsOut = NULL; m_sizeOut = 0; + } + if(m_sizeIn && m_bsIn){ + delete m_bsIn; + m_bsIn = NULL; m_sizeIn = 0; + } +} +LONG CICMPWS::Ping(const in_addr host,const UINT packetSize, + const UINT timeOut,LPINT pStatus) +{ + if(m_socket==INVALID_SOCKET){ + if(pStatus) + (*pStatus)=icmpNotInitialized; + } + VERIFY(AdjustBuffers(packetSize)); +icmp* pPacket = (icmp*)m_bsOut; + memset(pPacket,0,m_sizeOut); + pPacket->icmp_type = ICMP_ECHO; + pPacket->icmp_seq = m_icmpSeq++; + pPacket->icmp_id = (WORD)(::GetCurrentThreadId()&0xFFFF); + for(UINT tmp=0;tmpicmp_data[tmp]=tmp&0xFF; + pPacket->icmp_cksum = cksum(pPacket,SIZE_ICMP_HDR+packetSize); +sockaddr_in to; + memset(&to,0,sizeof(to)); + to.sin_addr.s_addr = host.s_addr; + to.sin_family = AF_INET; + if(sendto(m_socket,(char*)pPacket,SIZE_ICMP_HDR+packetSize,0, + (SOCKADDR*)&to,sizeof(to)) != (int)(SIZE_ICMP_HDR+packetSize)){ + TRACE1("sendto: %lu\n",WSAGetLastError()); + if(pStatus) + (*pStatus)=icmpSocketError; + return -1; + } +DWORD sentTime = ::GetTickCount(); +sockaddr_in from; + memset(&from,0,sizeof(from)); + from.sin_family=AF_INET; + from.sin_addr.s_addr=INADDR_ANY; +fd_set fds; + FD_ZERO(&fds); + FD_SET(m_socket,&fds); +long lrv = -1; +INT rv = ipTimeOut; + for(;;){ + DWORD ct = ::GetTickCount(); + if((ct-sentTime)>=timeOut){ + TRACE0("Timeout\n"); + break; + } + timeval tv = { + (timeOut-ct+sentTime)/1000, + (timeOut-ct+sentTime)%1000 + }; // tv_sec, tv_usec (secs,microsecs) + if(!select(m_socket,&fds,NULL,NULL,&tv)){ + TRACE1("select: %d\n",WSAGetLastError()); + break; + } + DWORD rtime = ::GetTickCount(); + ASSERT(FD_ISSET(m_socket,&fds)); + int fl = sizeof(from); + int rb = recvfrom(m_socket,(char*)m_bsIn,m_sizeIn,0,(SOCKADDR*)&from,&fl); + ip* pIP = (ip*)m_bsIn; + icmp* pICMP = (icmp*)&m_bsIn[sizeof(ip)]; + if(pICMP->icmp_id!=pPacket->icmp_id) + continue; + if(pICMP->icmp_seq!=pPacket->icmp_seq) + continue; + if(from.sin_addr.s_addr!=host.s_addr) + continue; + if(pICMP->icmp_type==ICMP_ECHOREPLY){ + lrv=rtime-sentTime; + rv=ipSuccess; + break; + } + rv = ipUnknown; // *** + break; + } + if(pStatus) + (*pStatus)=rv; + return lrv; +} + +BOOL CICMPWS::AdjustBuffers(UINT packetSize) +{ + if(!packetSize) + packetSize=0; +UINT osize = packetSize+SIZE_ICMP_HDR; + if(m_sizeOut0){ + if(count>1){ + lSum+=*(pData++); + count-=2; + }else{ + lSum+=((WORD)*(BYTE*)pData)&0xFF; + count--; + } + } + lSum = (lSum&0xFFFF)+(lSum>>16); + lSum += (lSum>>16); + return (~lSum)&0xFFFF; +} + +CICMP* CICMP::CreateICMP() +{ + if(m_mechanismus==_icmpUndetermined) + GuessMechanismus(); + switch(m_mechanismus){ + case _icmpWinsock: + return new CICMPWS; + break; + case _icmpDLL: + return new CICMPDll; + break; + } + return NULL; +} + +void CICMP::GuessMechanismus() +{ + m_mechanismus=_icmpUndetermined; +SOCKET testSocket = socket(AF_INET,SOCK_RAW,1); + if(testSocket!=INVALID_SOCKET){ + closesocket(testSocket); + m_mechanismus=_icmpWinsock; + }else{ + HINSTANCE hICMP = ::LoadLibraryEx("ICMP",NULL,0); + if(!hICMP) + return; + BOOL isThere = ( + ::GetProcAddress(hICMP,"IcmpCreateFile") + && ::GetProcAddress(hICMP,"IcmpSendEcho") + && ::GetProcAddress(hICMP,"IcmpCloseHandle") + ); + ::FreeLibrary(hICMP); + if(isThere) + m_mechanismus=_icmpDLL; + } +} \ No newline at end of file -- cgit v0.9.0.2