400 lines
7.7 KiB
C++
400 lines
7.7 KiB
C++
|
///////////////////////////////
|
||
|
// File: tcp.cpp
|
||
|
//
|
||
|
// Description:
|
||
|
|
||
|
// #include statements
|
||
|
//
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <winsock.h>
|
||
|
#include "tcp.h"
|
||
|
#include "util.h"
|
||
|
#include "rw_common.h"
|
||
|
|
||
|
|
||
|
#define RW_TCP_NOT_INITILIZED 0
|
||
|
#define RW_TCP_INITILIZED 1
|
||
|
|
||
|
#define RW_ICMP_NOT_INITILIZED 0
|
||
|
#define RW_ICMP_INITILIZED 1
|
||
|
|
||
|
static int siTcpStatus = RW_TCP_NOT_INITILIZED;
|
||
|
static HINSTANCE hIcmp= NULL;
|
||
|
static WSADATA wsa;
|
||
|
|
||
|
int ResolveHostByThread(LPSTR pHost);
|
||
|
int ResolveHostByAddrThread(LPSTR pHost);
|
||
|
|
||
|
#define GET_HOST_TOUT (15 * 1000)
|
||
|
#define PING_TOUT (15 * 1000)
|
||
|
static struct hostent *gphostent= NULL;
|
||
|
|
||
|
BOOL InitForTcp()
|
||
|
{
|
||
|
BOOL bRet= FALSE;
|
||
|
|
||
|
|
||
|
if( siTcpStatus == RW_TCP_INITILIZED )
|
||
|
return TRUE;
|
||
|
|
||
|
if (! WSAStartup(0x0101, &wsa )) {
|
||
|
siTcpStatus = RW_TCP_INITILIZED;
|
||
|
bRet= TRUE;
|
||
|
}
|
||
|
return bRet;
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL InitForIcmp()
|
||
|
{
|
||
|
if(hIcmp)
|
||
|
return TRUE;
|
||
|
hIcmp = LoadLibrary( _T("ICMP.DLL") ); // Load ICMP.DLL and store globally
|
||
|
if( ! hIcmp )
|
||
|
{ // Whine if unable to load the DLL
|
||
|
DisplayMessage("Unable to locate ICMP.DLL");
|
||
|
return( FALSE );
|
||
|
}
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
void CloseForTcpIcmp()
|
||
|
{
|
||
|
if (hIcmp)
|
||
|
FreeLibrary(hIcmp); // When app is closed, free the ICMP DLL
|
||
|
if(siTcpStatus == RW_TCP_INITILIZED)
|
||
|
WSACleanup(); // And clean up sockets
|
||
|
hIcmp = NULL;
|
||
|
siTcpStatus = RW_TCP_NOT_INITILIZED;
|
||
|
|
||
|
}
|
||
|
//
|
||
|
// Tries to get the host name and pings using ICMP
|
||
|
// returns
|
||
|
// RWZ_PINGSTATUS_NOTCPIP : if no socket library or get hostname fails
|
||
|
// RWZ_PINGSTATUS_SUCCESS : if gethostname and ping is successful
|
||
|
// RWZ_PINGSTATUS_FAIL : if gethostname is succesful and ping via icmp fails
|
||
|
|
||
|
DWORD PingHost()
|
||
|
{
|
||
|
DWORD dwRet= 0;
|
||
|
char szIPAddress[80];
|
||
|
dwRet = RWZ_PINGSTATUS_NOTCPIP;
|
||
|
if(!InitForTcp()) {
|
||
|
return dwRet; // Tcp is not installed
|
||
|
}
|
||
|
memset(szIPAddress, '\0', 80);
|
||
|
if (!gethostname(szIPAddress, 80))
|
||
|
{
|
||
|
|
||
|
if (Ping(szIPAddress)){
|
||
|
dwRet = RWZ_PINGSTATUS_SUCCESS;
|
||
|
}else {
|
||
|
dwRet = RWZ_PINGSTATUS_FAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return dwRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL Ping(LPSTR szIPAddress)
|
||
|
{
|
||
|
BOOL bRet= FALSE;
|
||
|
|
||
|
if( !InitForIcmp())
|
||
|
return bRet;
|
||
|
|
||
|
if(!InitForTcp()) {
|
||
|
return FALSE; // Tcp is not installed
|
||
|
}
|
||
|
|
||
|
|
||
|
static struct sockaddr_in saDestAddr;
|
||
|
|
||
|
char szBuffer[64];
|
||
|
DWORD *dwIPAddr, dwStatus;
|
||
|
HANDLE hIP;
|
||
|
struct hostent *phostent;
|
||
|
PIP_ECHO_REPLY pIpe;
|
||
|
|
||
|
if(!ResolveHostByThread(szIPAddress)) {
|
||
|
gphostent = gethostbyname(szIPAddress);
|
||
|
phostent = gphostent;
|
||
|
}else {
|
||
|
phostent= NULL;
|
||
|
}
|
||
|
if( ! phostent ){
|
||
|
RW_DEBUG << "\n Resolving by Address " << flush;
|
||
|
int iError;
|
||
|
iError = 0;
|
||
|
iError = WSAGetLastError ();
|
||
|
RW_DEBUG << "\n Get Host By Name Error " << iError << flush;
|
||
|
if(iError){
|
||
|
WSASetLastError (0);
|
||
|
//return 0;
|
||
|
}
|
||
|
|
||
|
saDestAddr.sin_addr.s_addr = inet_addr(szIPAddress);
|
||
|
if( saDestAddr.sin_addr.s_addr !=INADDR_NONE ) {
|
||
|
if(!ResolveHostByAddrThread((LPSTR)&saDestAddr.sin_addr.s_addr)) {
|
||
|
gphostent = gethostbyaddr((LPSTR)&saDestAddr.sin_addr.s_addr,4, PF_INET) ;
|
||
|
phostent = gphostent;
|
||
|
}else {
|
||
|
phostent= NULL;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
if(!phostent)
|
||
|
{
|
||
|
DisplayMessage(szIPAddress , "Unable to obtain an IP address for %s");
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
dwIPAddr = (DWORD *)( *phostent->h_addr_list );
|
||
|
|
||
|
ICMPCREATEFILE pIcmpCreateFile;
|
||
|
pIcmpCreateFile = (ICMPCREATEFILE) GetProcAddress(hIcmp, "IcmpCreateFile");
|
||
|
if (NULL == pIcmpCreateFile)
|
||
|
{
|
||
|
DisplayMessage("IcmpCreateFile GetProc Error", "");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ICMPCLOSEHANDLE pIcmpCloseHandle;
|
||
|
pIcmpCloseHandle = (ICMPCLOSEHANDLE) GetProcAddress(hIcmp, "IcmpCloseHandle");
|
||
|
if (NULL == pIcmpCloseHandle)
|
||
|
{
|
||
|
DisplayMessage("IcmpCloseHandle GetProc Error", "");
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
ICMPSENDECHO pIcmpSendEcho;
|
||
|
pIcmpSendEcho = (ICMPSENDECHO) GetProcAddress(hIcmp, "IcmpSendEcho");
|
||
|
if (NULL == pIcmpSendEcho)
|
||
|
{
|
||
|
DisplayMessage("IcmpSendEcho GetProc Error", "");
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
if( ! pIcmpCreateFile || ! pIcmpCloseHandle || ! pIcmpSendEcho )
|
||
|
{
|
||
|
DisplayMessage("Unable to locate required API functions", "");
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
hIP = pIcmpCreateFile();
|
||
|
if( hIP == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
DisplayMessage("Unable to open PING service");
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
memset( szBuffer, '\xAA', 64 );
|
||
|
pIpe = (PIP_ECHO_REPLY)LocalAlloc(LPTR, sizeof(IP_ECHO_REPLY) + 64);
|
||
|
if (pIpe)
|
||
|
{
|
||
|
pIpe->Data = szIPAddress;
|
||
|
pIpe->DataSize = 64;
|
||
|
|
||
|
dwStatus = pIcmpSendEcho( hIP, *dwIPAddr, szBuffer, 64, NULL, pIpe,
|
||
|
sizeof(IP_ECHO_REPLY) + 64, PING_TOUT );
|
||
|
if(dwStatus)
|
||
|
{
|
||
|
bRet = TRUE;
|
||
|
}
|
||
|
LocalFree(pIpe);
|
||
|
pIcmpCloseHandle(hIP);
|
||
|
}
|
||
|
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CheckHostName(LPSTR szIISServer)
|
||
|
{
|
||
|
// WSAStartup() is already called
|
||
|
if(!InitForTcp()) {
|
||
|
return FALSE; // Tcp is not installed
|
||
|
}
|
||
|
struct hostent *phostent;
|
||
|
|
||
|
if(!ResolveHostByThread(szIISServer)) {
|
||
|
phostent = gphostent;
|
||
|
}else {
|
||
|
phostent= NULL;
|
||
|
}
|
||
|
|
||
|
if (phostent == NULL)
|
||
|
return FALSE;
|
||
|
else
|
||
|
return TRUE;
|
||
|
// WSACleanup() will be called later
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Returns 1 if there is an Error
|
||
|
// 0 if Successful
|
||
|
DWORD GetHostThread(void *vp)
|
||
|
{
|
||
|
DWORD dwIsError=1;
|
||
|
LPSTR szHost;
|
||
|
szHost = (LPSTR) vp;
|
||
|
int iError = 0;
|
||
|
|
||
|
gphostent = gethostbyname(szHost);
|
||
|
if( ! gphostent ){
|
||
|
|
||
|
iError = WSAGetLastError ();
|
||
|
if(iError) {
|
||
|
WSASetLastError (0); // Reset the error
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
dwIsError =0;
|
||
|
}
|
||
|
ExitThread(dwIsError);
|
||
|
return dwIsError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This function returns Calls the gethostbyname and
|
||
|
// returns 0 if Successful and 1 if failure
|
||
|
// the return
|
||
|
//
|
||
|
//
|
||
|
int ResolveHostByThread(LPSTR pHost)
|
||
|
{
|
||
|
int iRet=0;
|
||
|
DWORD dwThreadExitCode;
|
||
|
DWORD dwCreationFlags=0; // Start CREATE_SUSPENDED
|
||
|
DWORD ThreadId;
|
||
|
RW_DEBUG << "\nResolve " << pHost << flush;
|
||
|
|
||
|
HANDLE hParent = CreateThread(NULL,
|
||
|
0,
|
||
|
(LPTHREAD_START_ROUTINE) GetHostThread,
|
||
|
(void *) pHost,
|
||
|
dwCreationFlags,
|
||
|
&ThreadId );
|
||
|
|
||
|
DWORD dwRet = WaitForSingleObject(hParent,GET_HOST_TOUT);
|
||
|
switch(dwRet) {
|
||
|
case WAIT_ABANDONED :
|
||
|
iRet = 1; // Error In Get Host Name
|
||
|
break;
|
||
|
case WAIT_OBJECT_0 :
|
||
|
RW_DEBUG << "\n\tResolved ( 1 Error, 0 Ok) ";
|
||
|
|
||
|
if( GetExitCodeThread(hParent,&dwThreadExitCode) ) {
|
||
|
iRet = (int) dwThreadExitCode;
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
}
|
||
|
RW_DEBUG << iRet;
|
||
|
break;
|
||
|
case WAIT_TIMEOUT :
|
||
|
RW_DEBUG << "\n\t*** Error Resolving " << flush;
|
||
|
iRet = 1; // Error In Get Host Name
|
||
|
TerminateThread(hParent,0);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return iRet;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Returns 1 if there is an Error
|
||
|
// 0 if Successful
|
||
|
DWORD GetHostByAddrThread(void *vp)
|
||
|
{
|
||
|
DWORD dwIsError=1;
|
||
|
LPSTR szAddr;
|
||
|
int iError = 0;
|
||
|
szAddr = (LPSTR) vp;
|
||
|
|
||
|
gphostent = gethostbyaddr(szAddr,
|
||
|
4, PF_INET) ;
|
||
|
if( ! gphostent ){
|
||
|
|
||
|
iError = WSAGetLastError ();
|
||
|
if(iError) {
|
||
|
WSASetLastError (0); // Reset the error
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
dwIsError =0;
|
||
|
}
|
||
|
return dwIsError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This function returns Calls the gethostbyaddr and
|
||
|
// returns 0 if Successful and 1 if failure
|
||
|
// the return
|
||
|
//
|
||
|
//
|
||
|
int ResolveHostByAddrThread(LPSTR pHost)
|
||
|
{
|
||
|
int iRet=0;
|
||
|
DWORD dwThreadExitCode;
|
||
|
DWORD dwCreationFlags=0; // Start CREATE_SUSPENDED
|
||
|
DWORD ThreadId;
|
||
|
RW_DEBUG << "\nResolve " << pHost << " By Address " << flush;
|
||
|
HANDLE hParent = CreateThread(NULL,
|
||
|
0,
|
||
|
(LPTHREAD_START_ROUTINE) GetHostByAddrThread,
|
||
|
(void *) pHost,
|
||
|
dwCreationFlags,
|
||
|
&ThreadId );
|
||
|
|
||
|
DWORD dwRet = WaitForSingleObject(hParent,GET_HOST_TOUT);
|
||
|
switch(dwRet) {
|
||
|
case WAIT_ABANDONED :
|
||
|
iRet = 1; // Error In Get Host Name
|
||
|
break;
|
||
|
case WAIT_OBJECT_0 :
|
||
|
RW_DEBUG << "\n\tResolved ( 1 Error, 0 Ok) ";
|
||
|
if( GetExitCodeThread(hParent,&dwThreadExitCode) ) {
|
||
|
iRet = (int) dwThreadExitCode;
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
}
|
||
|
RW_DEBUG << iRet << flush;
|
||
|
break;
|
||
|
case WAIT_TIMEOUT :
|
||
|
RW_DEBUG << "\n\t*** Error Resolving " << flush;
|
||
|
iRet = 1; // Error In Get Host Name
|
||
|
TerminateThread(hParent,0);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return iRet;
|
||
|
|
||
|
|
||
|
}
|