Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

601 lines
13 KiB

//////////////////////////////////////////////////////////////////////////////
//
// 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;
}