602 lines
13 KiB
C++
602 lines
13 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MyALG.cpp : Implementation of CMyALG
|
|
//
|
|
// Main interface called by ALG.exe it wil call Initialise and stop when the ALG.exe is unloading
|
|
// or this ALG Module is disable/removed
|
|
//
|
|
|
|
#include "PreComp.h"
|
|
|
|
#include "MyALG.h"
|
|
#include "MyAdapterNotify.h"
|
|
|
|
|
|
#include <winsock.h>
|
|
#pragma comment(lib, "wsock32.lib")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CMyALG
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#define PORTNUM 1313
|
|
#define HOSTNAME "localhost" // Server name string
|
|
#define MAX_PENDING_CONNECTS 4 // Maximum length of the queue of pending connections
|
|
|
|
IApplicationGatewayServices* g_pIAlgServices=NULL; // Cache main interface of ALG
|
|
IAdapterNotificationSink* g_pIAdapterNotificationSink=NULL;
|
|
IPrimaryControlChannel* g_pIControlChannel=NULL;
|
|
|
|
USHORT g_usPort= 0; // Test Reserve some ports
|
|
DWORD g_dwAdapterSinkCookie=0;
|
|
|
|
DWORD g_dwThreadID_Listen;
|
|
SOCKET g_ClientSock = INVALID_SOCKET; // Socket for communicating
|
|
|
|
//
|
|
// Forward declaration
|
|
//
|
|
DWORD WINAPI ThreadListenRedirect(LPVOID lpThreadParameter);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
//
|
|
// Main entry point for ALG Modules
|
|
//
|
|
//
|
|
STDMETHODIMP
|
|
CMyALG::Initialize(
|
|
IApplicationGatewayServices* pIAlgServices
|
|
)
|
|
{
|
|
MYTRACE_ENTER("CMyALG::Initialize");
|
|
|
|
USES_CONVERSION;
|
|
HRESULT hr;
|
|
|
|
|
|
ULONG nAddress;
|
|
|
|
//
|
|
// Keep the service alive (this is optional since the ALG Manager is loading us it will always be around)
|
|
//
|
|
g_pIAlgServices = pIAlgServices;
|
|
g_pIAlgServices->AddRef();
|
|
|
|
|
|
#if 1
|
|
//
|
|
// Requesting Notification of adapter ADD/REMOVE/MODIFY
|
|
// when an adapter gets Added Removed or is modified this ALG will receive a notification
|
|
//
|
|
{
|
|
MYTRACE_ENTER("###TEST### - STARTADAPTERNOTIFICATIONS");
|
|
|
|
CComObject<CMyAdapterNotify>* pIAdapterNotify;
|
|
CComObject<CMyAdapterNotify>::CreateInstance(&pIAdapterNotify);
|
|
hr = pIAdapterNotify->QueryInterface(IID_IAdapterNotificationSink, (void**)&g_pIAdapterNotificationSink);
|
|
|
|
if ( FAILED(hr) )
|
|
MYTRACE_ERROR("No QI on IID_IAdapterNotificationSink", hr);
|
|
|
|
hr = g_pIAlgServices->StartAdapterNotifications(g_pIAdapterNotificationSink, &g_dwAdapterSinkCookie);
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
#if 1
|
|
//
|
|
// Reserver some ports, these port will be garantied to be free and available for this ALG
|
|
//
|
|
{
|
|
MYTRACE_ENTER("###TEST### - RESERVE PORT");
|
|
hr = g_pIAlgServices->ReservePort(4, &g_usPort);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
MYTRACE("ALG_TEST->ReservePorts (%d) to (%d)", ntohs(g_usPort), ntohs(g_usPort)+3);
|
|
else
|
|
{
|
|
MYTRACE_ERROR("Could no reserver port", hr);
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
#if 1
|
|
//
|
|
// Redirect traffic of a well unknown port here we invented port 5000 as a port of interest
|
|
//
|
|
{
|
|
MYTRACE_ENTER("###TEST### - CREATE PRIMARY CONTROL CHANNEL");
|
|
|
|
|
|
|
|
hr = g_pIAlgServices->CreatePrimaryControlChannel(
|
|
eALG_TCP,
|
|
htons(5000),
|
|
eALG_DESTINATION_CAPTURE,
|
|
true,
|
|
inet_addr("127.0.0.1"),
|
|
htons(PORTNUM),
|
|
&g_pIControlChannel
|
|
);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("FAILED the CreatePrimaryControlChannel", hr);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
#if 1
|
|
//
|
|
// SECONDARY CHANNEL
|
|
//
|
|
{
|
|
MYTRACE_ENTER("###TEST### - CREATE SECONDARY CHANNAL");
|
|
|
|
ISecondaryControlChannel* mySecondaryDataChannel=NULL;
|
|
hr = g_pIAlgServices->CreateSecondaryControlChannel(
|
|
eALG_UDP,
|
|
|
|
inet_addr("192.168.0.2"),
|
|
htons(99),
|
|
|
|
inet_addr("157.157.157.2"),
|
|
htons(5001),
|
|
|
|
inet_addr("205.157.157.1"),
|
|
htons(5002),
|
|
|
|
inet_addr("127.0.0.1"),
|
|
htons(666),
|
|
|
|
eALG_INBOUND,
|
|
false,
|
|
&mySecondaryDataChannel
|
|
);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Could not create SecondaryDataChannel", hr);
|
|
}
|
|
else
|
|
{
|
|
hr = mySecondaryDataChannel->Cancel();
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Failed to cancel", hr);
|
|
}
|
|
|
|
mySecondaryDataChannel->Release();
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// Listen on another thread for redirected packet
|
|
//
|
|
|
|
|
|
|
|
HANDLE hThread = CreateThread(
|
|
NULL, // SecurityDesc
|
|
0, // initial stack size
|
|
ThreadListenRedirect, // thread function
|
|
NULL, // thread argument
|
|
0, // creation option
|
|
&g_dwThreadID_Listen // thread identifier
|
|
);
|
|
|
|
|
|
if ( !hThread )
|
|
MYTRACE_ERROR("Could not start listenning thread", 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
//
|
|
// TEST GetBestSourceAddressForDestinationAddress
|
|
// should return the best IP Address to use
|
|
//
|
|
{
|
|
MYTRACE_ENTER("###TEST### - GET BEST SOURCE ADDRESS FOR DESTINATION ADDRESS");
|
|
|
|
ULONG nAddressDest = inet_addr("157.157.157.2");
|
|
|
|
hr = g_pIAlgServices->GetBestSourceAddressForDestinationAddress(
|
|
nAddressDest, // IP Address of destination
|
|
false, // if Dialup is involved
|
|
&nAddress // the Address to use
|
|
);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("FAILED the CreatePrimaryControlChannel", hr);
|
|
}
|
|
|
|
MYTRACE( "Best address is %s", MYTRACE_IP(nAddress) );
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
#if 1
|
|
//
|
|
// D A T A C H A N N E L
|
|
//
|
|
{
|
|
MYTRACE_ENTER("###TEST### - CREATE DATA CHANNEL");
|
|
|
|
IDataChannel* myDataChannel=NULL;
|
|
hr = g_pIAlgServices->CreateDataChannel(
|
|
eALG_TCP,
|
|
nAddress,
|
|
g_usPort,
|
|
inet_addr("157.157.157.2"),
|
|
htons(5001),
|
|
inet_addr("157.157.157.1"),
|
|
htons(5001),
|
|
eALG_INBOUND,
|
|
eALG_NONE,
|
|
false,
|
|
&myDataChannel
|
|
);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Could not create DataChannel", hr);
|
|
}
|
|
else
|
|
{
|
|
hr = myDataChannel->Cancel();
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Failed to cancel", hr);
|
|
}
|
|
|
|
myDataChannel->Release();
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
//
|
|
// TEST - PrepareProxyConnection
|
|
//
|
|
//
|
|
|
|
#if 1
|
|
{
|
|
MYTRACE_ENTER("###TEST### - PREPARE PROXY CONNECTION");
|
|
|
|
IPendingProxyConnection* myPendingProxyConnection=NULL;
|
|
|
|
hr = g_pIAlgServices->PrepareProxyConnection(
|
|
eALG_TCP, // Protocal
|
|
nAddress, // Source Address
|
|
g_usPort, // Source Port
|
|
inet_addr("172.31.77.13"), // Public Destination Address
|
|
htons(21), // Public Destination port
|
|
FALSE,
|
|
&myPendingProxyConnection
|
|
);
|
|
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Could not create shadow redirect", hr);
|
|
}
|
|
else
|
|
{
|
|
hr = myPendingProxyConnection->Cancel();
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Failed to cancel", hr);
|
|
}
|
|
|
|
myPendingProxyConnection->Release();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
#if 1
|
|
//
|
|
//
|
|
// TEST - PrepareSourceModifiedProxyConnection
|
|
//
|
|
//
|
|
{
|
|
MYTRACE_ENTER("###TEST### - PREPARE SOURCE MODIFIED PROXY CONNECTION");
|
|
|
|
IPendingProxyConnection* myPendingProxyConnection2=NULL;
|
|
|
|
hr = g_pIAlgServices->PrepareSourceModifiedProxyConnection(
|
|
eALG_TCP,
|
|
nAddress,
|
|
htons(1212),
|
|
inet_addr("172.31.77.13"),
|
|
htons(21),
|
|
inet_addr("172.31.77.14"),
|
|
htons(22),
|
|
&myPendingProxyConnection2
|
|
);
|
|
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Could not create shadow redirect", hr);
|
|
}
|
|
else
|
|
{
|
|
hr = myPendingProxyConnection2->Cancel();
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Failed to cancel", hr);
|
|
}
|
|
|
|
myPendingProxyConnection2->Release();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
STDMETHODIMP
|
|
CMyALG::Stop()
|
|
{
|
|
MYTRACE_ENTER("CMyALG::Stop(void)");
|
|
|
|
closesocket(g_ClientSock);
|
|
g_ClientSock = INVALID_SOCKET;
|
|
|
|
if ( g_dwAdapterSinkCookie )
|
|
{
|
|
HRESULT hr = g_pIAlgServices->StopAdapterNotifications(g_dwAdapterSinkCookie);
|
|
g_pIAdapterNotificationSink->Release();
|
|
}
|
|
|
|
|
|
if ( g_pIControlChannel )
|
|
{
|
|
g_pIControlChannel->Cancel();
|
|
}
|
|
|
|
MYTRACE("ReleaseReservedPort %d", g_usPort);
|
|
g_pIAlgServices->ReleaseReservedPort(g_usPort, 4);
|
|
|
|
MYTRACE("About To Release");
|
|
// g_pIAlgServices->Release();
|
|
|
|
MYTRACE("Return");
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
HRESULT
|
|
WaitForData()
|
|
{
|
|
MYTRACE_ENTER("WaitForData()");
|
|
//
|
|
// Prepare winsock
|
|
//
|
|
|
|
int index = 0; // Integer index
|
|
SOCKET WinSocket = INVALID_SOCKET; // Window socket
|
|
|
|
// between the server and client
|
|
SOCKADDR_IN local_sin; // Local socket address
|
|
|
|
WSADATA WSAData; // Contains details of the Winsock implementation
|
|
|
|
// Initialize Winsock.
|
|
if ( WSAStartup (MAKEWORD(1,1), &WSAData) != 0 )
|
|
{
|
|
MYTRACE_ERROR("WSAStartup failed.", WSAGetLastError ());
|
|
}
|
|
|
|
// Create a TCP/IP socket, WinSocket.
|
|
if ((WinSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
|
|
{
|
|
MYTRACE_ERROR("Allocating socket failed", WSAGetLastError());
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
// Fill out the local socket's address information.
|
|
local_sin.sin_family = AF_INET;
|
|
local_sin.sin_port = htons(PORTNUM); //g_usPort;
|
|
local_sin.sin_addr.s_addr = inet_addr("127.0.0.1");
|
|
|
|
|
|
// Associate the local address with WinSocket.
|
|
if ( bind(WinSocket, (struct sockaddr *) &local_sin, sizeof (local_sin)) == SOCKET_ERROR )
|
|
{
|
|
MYTRACE_ERROR("Binding socket failed.", WSAGetLastError ());
|
|
closesocket (WinSocket);
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
// Establish a socket to listen for incoming connections.
|
|
if ( listen(WinSocket, MAX_PENDING_CONNECTS) == SOCKET_ERROR )
|
|
{
|
|
MYTRACE_ERROR("Listening to the client failed.", WSAGetLastError ());
|
|
closesocket (WinSocket);
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Accept an incoming connection attempt on WinSocket.
|
|
SOCKADDR_IN accept_sin; // Receives the address of the
|
|
// connecting entity
|
|
int accept_sin_len; // Length of accept_sin
|
|
accept_sin_len = sizeof (accept_sin);
|
|
|
|
MYTRACE("*** Accept is waiting for a connection");
|
|
|
|
|
|
g_ClientSock = accept(
|
|
WinSocket,
|
|
(struct sockaddr *) &accept_sin,
|
|
(int *) &accept_sin_len
|
|
);
|
|
|
|
// Stop listening for connections from clients.
|
|
closesocket (WinSocket);
|
|
|
|
{
|
|
MYTRACE ("Getting original address");
|
|
//
|
|
ULONG ulOriginalDestinationAddress;
|
|
USHORT usOriginalDestinationPort;
|
|
|
|
|
|
IAdapterInfo* pAdapterInfo;
|
|
|
|
HRESULT hr = g_pIControlChannel->GetOriginalDestinationInformation(
|
|
accept_sin.sin_addr.S_un.S_addr,
|
|
accept_sin.sin_port,
|
|
&ulOriginalDestinationAddress,
|
|
&usOriginalDestinationPort,
|
|
&pAdapterInfo
|
|
);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("GetOriginalDestinationInformation did not work", hr);
|
|
}
|
|
else
|
|
{
|
|
MYTRACE("Original Address %s:%d", MYTRACE_IP(ulOriginalDestinationAddress), ntohs(usOriginalDestinationPort));
|
|
|
|
ULONG nIndex;
|
|
pAdapterInfo->GetAdapterIndex(&nIndex);
|
|
|
|
ALG_ADAPTER_TYPE eType;
|
|
pAdapterInfo->GetAdapterType(&eType);
|
|
|
|
MYTRACE("AdapterIndex %d", nIndex);
|
|
MYTRACE("AdapterType %d", eType);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if ( g_ClientSock == INVALID_SOCKET)
|
|
{
|
|
MYTRACE_ERROR("Accepting connection with client failed. Error: %d", WSAGetLastError ());
|
|
return E_FAIL;
|
|
}
|
|
|
|
MYTRACE("**** AFTER Listen on port %d", g_usPort);
|
|
|
|
TCHAR cData;
|
|
|
|
int iReturn;
|
|
|
|
for (;;)
|
|
{
|
|
// Receive data from the client.
|
|
iReturn = recv(
|
|
g_ClientSock,
|
|
(char*)&cData,
|
|
sizeof(cData),
|
|
0);
|
|
|
|
|
|
// Check if there is any data received. If there is, display it.
|
|
if (iReturn == SOCKET_ERROR)
|
|
{
|
|
MYTRACE("Received failed. Error: %d", WSAGetLastError ());
|
|
return E_FAIL;
|
|
}
|
|
else if (iReturn == 0)
|
|
{
|
|
MYTRACE("Finished receiving data");
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
MYTRACE("%c", cData);
|
|
}
|
|
}
|
|
|
|
closesocket(g_ClientSock);
|
|
|
|
|
|
|
|
//
|
|
// Enumerate The Adapters
|
|
//
|
|
IEnumAdapterInfo* pAdapters = NULL;
|
|
|
|
HRESULT hr = g_pIAlgServices->EnumerateAdapters(&pAdapters);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Call EnumerateAdapters did not worked", hr);
|
|
}
|
|
else
|
|
pAdapters->Release();
|
|
|
|
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
DWORD WINAPI
|
|
ThreadListenRedirect(LPVOID lpThreadParameter)
|
|
{
|
|
MYTRACE_ENTER("ThreadListenRedirect()");
|
|
|
|
while ( WaitForData() == S_OK );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|