////////////////////////////////////////////////////////////////////////////// // // 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 #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* pIAdapterNotify; CComObject::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; }