1451 lines
28 KiB
C++
1451 lines
28 KiB
C++
/*++
|
||
|
||
Copyright (c) 2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
rmALG.cpp
|
||
|
||
Abstract:
|
||
|
||
This module contains routines for the ALG Manager module's
|
||
interface to the IP router-manager. (See ROUTPROT.H for details).
|
||
|
||
Author:
|
||
|
||
JPDup 10-Nov-2000
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
#include <ipnatapi.h>
|
||
|
||
#include <initguid.h>
|
||
#include <atlbase.h>
|
||
extern CComModule _Module;
|
||
#include <atlcom.h>
|
||
|
||
|
||
|
||
#include "Alg_private.h"
|
||
#include "NatPrivateAPI_Imp.h"
|
||
|
||
#include <MyTrace.h>
|
||
|
||
|
||
MYTRACE_ENABLE
|
||
|
||
|
||
|
||
//
|
||
// Globals
|
||
//
|
||
|
||
|
||
|
||
COMPONENT_REFERENCE AlgComponentReference;
|
||
PIP_ALG_GLOBAL_INFO AlgGlobalInfo = NULL;
|
||
CRITICAL_SECTION AlgGlobalInfoLock;
|
||
|
||
HANDLE AlgNotificationEvent;
|
||
HANDLE AlgTimerQueueHandle = NULL;
|
||
HANDLE AlgPortReservationHandle = NULL;
|
||
HANDLE AlgTranslatorHandle = NULL;
|
||
ULONG AlgProtocolStopped = 0;
|
||
IP_ALG_STATISTICS AlgStatistics;
|
||
SUPPORT_FUNCTIONS AlgSupportFunctions;
|
||
|
||
//
|
||
// GIT cookie for the IHNetCfgMgr instance
|
||
//
|
||
DWORD AlgGITcookie = 0;
|
||
IGlobalInterfaceTable* AlgGITp = NULL;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
const MPR_ROUTING_CHARACTERISTICS AlgRoutingCharacteristics =
|
||
{
|
||
MS_ROUTER_VERSION,
|
||
MS_IP_ALG,
|
||
RF_ROUTING|RF_ADD_ALL_INTERFACES,
|
||
AlgRmStartProtocol,
|
||
AlgRmStartComplete,
|
||
AlgRmStopProtocol,
|
||
AlgRmGetGlobalInfo,
|
||
AlgRmSetGlobalInfo,
|
||
NULL,
|
||
NULL,
|
||
AlgRmAddInterface,
|
||
AlgRmDeleteInterface,
|
||
AlgRmInterfaceStatus,
|
||
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL, //AlgRmMibGet,
|
||
NULL, //AlgRmMibSet,
|
||
NULL, //AlgRmMibGetFirst,
|
||
NULL, //AlgRmMibGetNext,
|
||
NULL,
|
||
NULL
|
||
};
|
||
|
||
|
||
#define COMINIT_BEGIN \
|
||
bool bComInitialized = true; \
|
||
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE ); \
|
||
if ( FAILED(hr) ) \
|
||
{ \
|
||
bComInitialized = FALSE; \
|
||
if (RPC_E_CHANGED_MODE == hr) \
|
||
hr = S_OK; \
|
||
} \
|
||
|
||
#define COMINIT_END if (TRUE == bComInitialized) { CoUninitialize(); }
|
||
|
||
|
||
#define IID_PPV_ARG(Type, Expr) \
|
||
__uuidof(Type), reinterpret_cast<void**>(static_cast<Type **>((Expr)))
|
||
|
||
|
||
|
||
|
||
//
|
||
//
|
||
//
|
||
HRESULT
|
||
GetAlgControllerInterface(
|
||
IAlgController** ppAlgController
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine obtains a pointer to the home networking configuration
|
||
manager.
|
||
|
||
Arguments:
|
||
|
||
ppAlgController - receives the IAlgController pointer. The caller must release this pointer.
|
||
|
||
Return Value:
|
||
|
||
standard HRESULT
|
||
|
||
Environment:
|
||
|
||
COM must be initialized on the calling thread
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
HRESULT hr = S_OK;
|
||
|
||
if ( NULL == AlgGITp )
|
||
{
|
||
IAlgController* pIAlgController;
|
||
|
||
//
|
||
// Create the global interface table
|
||
//
|
||
|
||
hr = CoCreateInstance(
|
||
CLSID_StdGlobalInterfaceTable,
|
||
NULL,
|
||
CLSCTX_INPROC_SERVER,
|
||
IID_PPV_ARG(IGlobalInterfaceTable, &AlgGITp)
|
||
);
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
//
|
||
// Create the ALG Interface (ALG.exe will start as a service by COM)
|
||
//
|
||
|
||
hr = CoCreateInstance(
|
||
CLSID_AlgController,
|
||
NULL,
|
||
CLSCTX_LOCAL_SERVER,
|
||
IID_PPV_ARG(IAlgController, &pIAlgController)
|
||
);
|
||
|
||
if ( FAILED(hr) )
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"GetAlgControllerInterface: Unable to create pIAlgController (0x%08x)",
|
||
hr
|
||
);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"GetAlgControllerInterface: Unable to create GIT (0x%08x)",
|
||
hr
|
||
);
|
||
}
|
||
|
||
if (SUCCEEDED(hr))
|
||
{
|
||
//
|
||
// Store the CfgMgr pointer in the GIT
|
||
//
|
||
|
||
hr = AlgGITp->RegisterInterfaceInGlobal(
|
||
pIAlgController,
|
||
IID_IAlgController,
|
||
&AlgGITcookie
|
||
);
|
||
|
||
pIAlgController->Release();
|
||
|
||
if ( FAILED(hr) )
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"GetAlgControllerInterface: Unable to register pIAlgController (0x%08x)",
|
||
hr
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
hr = AlgGITp->GetInterfaceFromGlobal(
|
||
AlgGITcookie,
|
||
IID_PPV_ARG(IAlgController, ppAlgController)
|
||
);
|
||
}
|
||
|
||
return hr;
|
||
|
||
} // GetAlgControllerInterface
|
||
|
||
|
||
|
||
//
|
||
//
|
||
//
|
||
void
|
||
FreeAlgControllerInterface()
|
||
{
|
||
//
|
||
// Free up HNetCfgMgr pointers
|
||
//
|
||
|
||
if ( !AlgGITp )
|
||
return; // nothing to free
|
||
|
||
//
|
||
// Make sure COM is initialized
|
||
//
|
||
HRESULT hr;
|
||
|
||
COMINIT_BEGIN;
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
//
|
||
// Release the ALG.exe private interface from the GIT
|
||
//
|
||
|
||
AlgGITp->RevokeInterfaceFromGlobal(AlgGITcookie);
|
||
AlgGITcookie = 0;
|
||
|
||
//
|
||
// Release the GIT
|
||
//
|
||
|
||
AlgGITp->Release();
|
||
AlgGITp = NULL;
|
||
}
|
||
|
||
COMINIT_END;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
AlgCleanupModule(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to cleanup the ALG transparent proxy module.
|
||
|
||
Arguments:
|
||
|
||
none.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
Environment:
|
||
|
||
Invoked from within a 'DllMain' routine on 'DLL_PROCESS_DETACH'.
|
||
|
||
--*/
|
||
|
||
{
|
||
DeleteCriticalSection(&AlgGlobalInfoLock);
|
||
DeleteComponentReference(&AlgComponentReference);
|
||
|
||
} // AlgCleanupModule
|
||
|
||
|
||
VOID
|
||
AlgCleanupProtocol(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to cleanup the ALG transparent proxy
|
||
protocol-component after a 'StopProtocol'. It runs when the last reference
|
||
to the component is released. (See 'COMPREF.H').
|
||
|
||
Arguments:
|
||
|
||
none.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
Environment:
|
||
|
||
Invoked from within an arbitrary context with no locks held.
|
||
|
||
--*/
|
||
|
||
{
|
||
PROFILE("AlgCleanupProtocol");
|
||
if (AlgGlobalInfo) { NH_FREE(AlgGlobalInfo); AlgGlobalInfo = NULL; }
|
||
if (AlgTimerQueueHandle) {
|
||
DeleteTimerQueueEx(AlgTimerQueueHandle, INVALID_HANDLE_VALUE);
|
||
AlgTimerQueueHandle = NULL;
|
||
}
|
||
if (AlgPortReservationHandle) {
|
||
NatShutdownPortReservation(AlgPortReservationHandle);
|
||
AlgPortReservationHandle = NULL;
|
||
}
|
||
if (AlgTranslatorHandle) {
|
||
NatShutdownTranslator(AlgTranslatorHandle); AlgTranslatorHandle = NULL;
|
||
}
|
||
InterlockedExchange(reinterpret_cast<LPLONG>(&AlgProtocolStopped), 1);
|
||
SetEvent(AlgNotificationEvent);
|
||
ResetComponentReference(&AlgComponentReference);
|
||
|
||
//
|
||
// Free the GIT and AlgController interface
|
||
//
|
||
FreeAlgControllerInterface();
|
||
|
||
} // AlgCleanupProtocol
|
||
|
||
|
||
BOOLEAN
|
||
AlgInitializeModule(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to initialize the FnP module.
|
||
|
||
Arguments:
|
||
|
||
none.
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - TRUE if initialization succeeded, FALSE otherwise
|
||
|
||
Environment:
|
||
|
||
Invoked in the context of a 'DllMain' routine on 'DLL_PROCESS_ATTACH'.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
if (InitializeComponentReference(
|
||
&AlgComponentReference, AlgCleanupProtocol
|
||
))
|
||
{
|
||
return FALSE;
|
||
}
|
||
__try
|
||
{
|
||
InitializeCriticalSection(&AlgGlobalInfoLock);
|
||
}
|
||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||
{
|
||
DeleteComponentReference(&AlgComponentReference);
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
} // AlgInitializeModule
|
||
|
||
|
||
|
||
|
||
//
|
||
// Get ALG COM Interface to Start the ALG and give call back Interface
|
||
//
|
||
HRESULT
|
||
Initialise_ALG()
|
||
{
|
||
HRESULT hr;
|
||
|
||
COMINIT_BEGIN;
|
||
|
||
if ( FAILED(hr) )
|
||
return hr;
|
||
|
||
//
|
||
// Get COM to load the ALG.exe
|
||
// The ALG will be launch using a LOCAL_SERVICE priviledge
|
||
// See the RunAs entry under the AppID of the ALG.exe
|
||
//
|
||
|
||
IAlgController* pIAlgController=NULL;
|
||
|
||
hr = GetAlgControllerInterface(&pIAlgController);
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
//
|
||
// We create our Private COM interface to the NAT api
|
||
//
|
||
CComObject<CNat>* pComponentNat;
|
||
hr = CComObject<CNat>::CreateInstance(&pComponentNat);
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
pComponentNat->AddRef();
|
||
|
||
//
|
||
// Make sure we pass a INat interface
|
||
//
|
||
INat* pINat=NULL;
|
||
hr = pComponentNat->QueryInterface(IID_INat, (void**)&pINat);
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
|
||
//
|
||
// Let the ALG manager start the loading of all the ALG modules
|
||
//
|
||
hr = pIAlgController->Start(pINat);
|
||
|
||
if ( FAILED(hr) )
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"Initialise_ALG: Error (0x%08x) on pIAlgController->Start(pINat)",
|
||
hr
|
||
);
|
||
}
|
||
|
||
//
|
||
// ALG manager will have AddRef this INat so we can release
|
||
//
|
||
pINat->Release();
|
||
|
||
}
|
||
|
||
pComponentNat->Release();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"Initialise_ALG: Error (0x%08x) Getting the IAlgController interface",
|
||
hr
|
||
);
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
if ( pIAlgController )
|
||
pIAlgController->Release();
|
||
|
||
COMINIT_END;
|
||
|
||
return S_OK;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
ULONG
|
||
APIENTRY
|
||
AlgRmStartProtocol(
|
||
HANDLE NotificationEvent,
|
||
PSUPPORT_FUNCTIONS SupportFunctions,
|
||
PVOID GlobalInfo,
|
||
ULONG StructureVersion,
|
||
ULONG StructureSize,
|
||
ULONG StructureCount
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to indicate the component's operation should begin.
|
||
|
||
Arguments:
|
||
|
||
NotificationEvent - event on which we notify the router-manager
|
||
about asynchronous occurrences
|
||
|
||
SupportFunctions - functions for initiating router-related operations
|
||
|
||
GlobalInfo - configuration for the component
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code.
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
MYTRACE_START(L"rmALG");
|
||
MYTRACE_ENTER("AlgRmStartProtocol");
|
||
PROFILE("AlgRmStartProtocol");
|
||
|
||
ULONG Error = NO_ERROR;
|
||
ULONG Size;
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
|
||
if (!GlobalInfo) { DEREFERENCE_ALG_AND_RETURN(ERROR_INVALID_PARAMETER); }
|
||
|
||
do {
|
||
|
||
//
|
||
// Copy the global configuration
|
||
//
|
||
|
||
EnterCriticalSection(&AlgGlobalInfoLock);
|
||
|
||
Size = sizeof(*AlgGlobalInfo);
|
||
|
||
AlgGlobalInfo =
|
||
reinterpret_cast<PIP_ALG_GLOBAL_INFO>(NH_ALLOCATE(Size));
|
||
|
||
if (!AlgGlobalInfo) {
|
||
LeaveCriticalSection(&AlgGlobalInfoLock);
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"AlgRmStartProtocol: cannot allocate global info"
|
||
);
|
||
NhErrorLog(
|
||
IP_ALG_LOG_ALLOCATION_FAILED,
|
||
0,
|
||
"%d",
|
||
Size
|
||
);
|
||
Error = ERROR_NOT_ENOUGH_MEMORY;
|
||
break;
|
||
}
|
||
|
||
CopyMemory(AlgGlobalInfo, GlobalInfo, Size);
|
||
|
||
//
|
||
// Save the notification event
|
||
//
|
||
|
||
AlgNotificationEvent = NotificationEvent;
|
||
|
||
//
|
||
// Save the support functions
|
||
//
|
||
|
||
if (!SupportFunctions) {
|
||
ZeroMemory(&AlgSupportFunctions, sizeof(AlgSupportFunctions));
|
||
} else {
|
||
CopyMemory(
|
||
&AlgSupportFunctions,
|
||
SupportFunctions,
|
||
sizeof(*SupportFunctions)
|
||
);
|
||
}
|
||
|
||
//
|
||
// Obtain a handle to the kernel-mode translation module.
|
||
//
|
||
|
||
Error = NatInitializeTranslator(&AlgTranslatorHandle);
|
||
if (Error) {
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"AlgRmStartProtocol: error %d initializing translator",
|
||
Error
|
||
);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Obtain a port-reservation handle
|
||
//
|
||
|
||
Error = NatInitializePortReservation(
|
||
ALG_PORT_RESERVATION_BLOCK_SIZE,
|
||
&AlgPortReservationHandle
|
||
);
|
||
|
||
|
||
if (Error)
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"AlgRmStartProtocol: error %d initializing port-reservation",
|
||
Error
|
||
);
|
||
break;
|
||
}
|
||
|
||
AlgTimerQueueHandle = CreateTimerQueue();
|
||
if (AlgTimerQueueHandle == NULL) {
|
||
Error = GetLastError();
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"AlgRmStartProtocol: error %d initializing timer queue",
|
||
Error
|
||
);
|
||
break;
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Start the ALG.exe
|
||
//
|
||
Initialise_ALG();
|
||
|
||
|
||
|
||
LeaveCriticalSection(&AlgGlobalInfoLock);
|
||
InterlockedExchange(reinterpret_cast<LPLONG>(&AlgProtocolStopped), 0);
|
||
|
||
} while (FALSE);
|
||
|
||
DEREFERENCE_ALG_AND_RETURN(Error);
|
||
|
||
} // AlgRmStartProtocol
|
||
|
||
|
||
ULONG
|
||
APIENTRY
|
||
AlgRmStartComplete(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked when the router has finished adding the initial
|
||
configuration.
|
||
|
||
Arguments:
|
||
|
||
none.
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
return NO_ERROR;
|
||
|
||
} // AlgRmStartComplete
|
||
|
||
|
||
ULONG
|
||
APIENTRY
|
||
AlgRmStopProtocol(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to stop the protocol.
|
||
|
||
Arguments:
|
||
|
||
none.
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
MYTRACE_ENTER("AlgRmStopProtocol");
|
||
PROFILE("AlgRmStopProtocol");
|
||
|
||
//
|
||
// Reference the module to make sure it's running
|
||
//
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
|
||
|
||
//
|
||
// Stop all ALG
|
||
//
|
||
HRESULT hr;
|
||
COMINIT_BEGIN;
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
|
||
IAlgController* pIAlgController=NULL;
|
||
hr = GetAlgControllerInterface(&pIAlgController);
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
hr = pIAlgController->Stop();
|
||
|
||
if ( FAILED(hr) )
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"AlgRmStopProtocol: Error (0x%08x) returned from pIalgController->Stop()",
|
||
hr
|
||
);
|
||
}
|
||
|
||
ULONG nRef = pIAlgController->Release();
|
||
|
||
//
|
||
// We are done with the ALG
|
||
// Free the GIT and AlgController interface
|
||
//
|
||
FreeAlgControllerInterface();
|
||
}
|
||
}
|
||
|
||
COMINIT_END;
|
||
|
||
|
||
|
||
//
|
||
// Drop the initial reference to cause a cleanup
|
||
//
|
||
ReleaseInitialComponentReference(&AlgComponentReference);
|
||
|
||
|
||
MYTRACE_STOP;
|
||
|
||
return DEREFERENCE_ALG() ? NO_ERROR : ERROR_PROTOCOL_STOP_PENDING;
|
||
|
||
} // AlgRmStopProtocol
|
||
|
||
|
||
|
||
|
||
ULONG
|
||
APIENTRY
|
||
AlgRmAddInterface(
|
||
PWCHAR Name,
|
||
ULONG Index,
|
||
NET_INTERFACE_TYPE Type,
|
||
ULONG MediaType,
|
||
USHORT AccessType,
|
||
USHORT ConnectionType,
|
||
PVOID InterfaceInfo,
|
||
ULONG StructureVersion,
|
||
ULONG StructureSize,
|
||
ULONG StructureCount
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to add an interface to the component.
|
||
|
||
Arguments:
|
||
|
||
Name - the name of the interface (unused)
|
||
|
||
Index - the index of the interface
|
||
|
||
Type - the type of the interface
|
||
|
||
InterfaceInfo - the configuration information for the interface
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code.
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
PROFILE("AlgRmAddInterface");
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
|
||
|
||
ULONG Error = NO_ERROR;
|
||
|
||
//
|
||
// Also notify the ALG.exe manager
|
||
//
|
||
HRESULT hr;
|
||
|
||
COMINIT_BEGIN;
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
IAlgController* pIAlgController=NULL;
|
||
HRESULT hr = GetAlgControllerInterface(&pIAlgController);
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
|
||
ULONG nInterfaceCharacteristics = NatGetInterfaceCharacteristics(Index);
|
||
|
||
short nTypeOfAdapter = 0;
|
||
|
||
if ( NAT_IFC_BOUNDARY(nInterfaceCharacteristics) )
|
||
nTypeOfAdapter |= eALG_BOUNDARY;
|
||
|
||
if ( NAT_IFC_FW(nInterfaceCharacteristics) )
|
||
nTypeOfAdapter |= eALG_FIREWALLED;
|
||
|
||
if ( NAT_IFC_PRIVATE(nInterfaceCharacteristics) )
|
||
nTypeOfAdapter |= eALG_PRIVATE;
|
||
|
||
|
||
hr = pIAlgController->Adapter_Add(
|
||
Index,
|
||
(short)nTypeOfAdapter
|
||
);
|
||
|
||
if ( FAILED(hr) )
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"AlgRmAddInterface: Error (0x%08x) returned from pIalgController->Adapter_Add()",
|
||
hr
|
||
);
|
||
}
|
||
|
||
pIAlgController->Release();
|
||
}
|
||
}
|
||
|
||
COMINIT_END;
|
||
|
||
DEREFERENCE_ALG_AND_RETURN(Error);
|
||
|
||
} // AlgRmAddInterface
|
||
|
||
|
||
ULONG
|
||
APIENTRY
|
||
AlgRmDeleteInterface(
|
||
ULONG Index
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to delete an interface from the component.
|
||
|
||
Arguments:
|
||
|
||
Index - the index of the interface
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Error = S_OK;
|
||
PROFILE("AlgRmDeleteInterface");
|
||
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
|
||
//
|
||
// Also notify the ALG.exe manager
|
||
//
|
||
HRESULT hr;
|
||
|
||
COMINIT_BEGIN;
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
IAlgController* pIAlgController=NULL;
|
||
HRESULT hr = GetAlgControllerInterface(&pIAlgController);
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
hr = pIAlgController->Adapter_Remove(Index);
|
||
|
||
if ( FAILED(hr) )
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"AlgRmAddInterface: Error (0x%08x) returned from pIalgController->Adapter_Remove()",
|
||
hr
|
||
);
|
||
}
|
||
|
||
pIAlgController->Release();
|
||
}
|
||
}
|
||
|
||
COMINIT_END;
|
||
DEREFERENCE_ALG_AND_RETURN(Error);
|
||
|
||
} // AlgRmDeleteInterface
|
||
|
||
|
||
|
||
|
||
|
||
ULONG
|
||
APIENTRY
|
||
AlgRmInterfaceStatus(
|
||
ULONG Index,
|
||
BOOL InterfaceActive,
|
||
ULONG StatusType,
|
||
PVOID StatusInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to bind/unbind, enable/disable an interface
|
||
|
||
Arguments:
|
||
|
||
Index - the interface to be bound
|
||
|
||
InterfaceActive - whether the interface is active
|
||
|
||
StatusType - type of status being changed (bind or enabled)
|
||
|
||
StatusInfo - Info pertaining to the state being changed
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 Status code
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Error = NO_ERROR;
|
||
|
||
switch(StatusType) {
|
||
case RIS_INTERFACE_ADDRESS_CHANGE: {
|
||
PIP_ADAPTER_BINDING_INFO BindInfo =
|
||
(PIP_ADAPTER_BINDING_INFO)StatusInfo;
|
||
|
||
if (BindInfo->AddressCount) {
|
||
Error = AlgRmBindInterface(Index, StatusInfo);
|
||
} else {
|
||
Error = AlgRmUnbindInterface(Index);
|
||
}
|
||
break;
|
||
}
|
||
|
||
case RIS_INTERFACE_ENABLED: {
|
||
Error = AlgRmEnableInterface(Index);
|
||
break;
|
||
}
|
||
|
||
case RIS_INTERFACE_DISABLED: {
|
||
Error = AlgRmDisableInterface(Index);
|
||
break;
|
||
}
|
||
}
|
||
|
||
return Error;
|
||
|
||
} // AlgRmInterfaceStatus
|
||
|
||
|
||
ULONG
|
||
AlgRmBindInterface(
|
||
ULONG Index,
|
||
PVOID BindingInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to bind an interface to its IP address(es).
|
||
|
||
Arguments:
|
||
|
||
Index - the interface to be bound
|
||
|
||
BindingInfo - the addressing information
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code.
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Error = NO_ERROR;
|
||
PROFILE("AlgRmBindInterface");
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
|
||
HRESULT hr;
|
||
|
||
//
|
||
// Also notify the ALG.exe manager
|
||
//
|
||
ULONG nAddressCount = ((PIP_ADAPTER_BINDING_INFO)BindingInfo)->AddressCount;
|
||
|
||
//
|
||
// Build a simple array of address(DWORD) to send over RPC
|
||
//
|
||
DWORD* apdwAddress = new DWORD[((PIP_ADAPTER_BINDING_INFO)BindingInfo)->AddressCount];
|
||
if(NULL != apdwAddress)
|
||
{
|
||
|
||
|
||
for ( ULONG nAddress=0; nAddress < nAddressCount; nAddress++ )
|
||
{
|
||
apdwAddress[nAddress] = ((PIP_ADAPTER_BINDING_INFO)BindingInfo)->Address[nAddress].Address;
|
||
}
|
||
|
||
|
||
COMINIT_BEGIN;
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
IAlgController* pIAlgController=NULL;
|
||
HRESULT hr = GetAlgControllerInterface(&pIAlgController);
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
ULONG nRealAdapterIndex = NhMapAddressToAdapter(apdwAddress[0]);
|
||
|
||
hr = pIAlgController->Adapter_Bind(
|
||
Index,
|
||
nRealAdapterIndex,
|
||
nAddressCount,
|
||
apdwAddress
|
||
);
|
||
|
||
if ( FAILED(hr) )
|
||
{
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"AlgRmBinInterface: Error (0x%08x) returned from pIalgController->Adapter_Bind()",
|
||
hr
|
||
);
|
||
}
|
||
|
||
pIAlgController->Release();
|
||
}
|
||
}
|
||
|
||
COMINIT_END;
|
||
|
||
delete [] apdwAddress;
|
||
}
|
||
|
||
DEREFERENCE_ALG_AND_RETURN(Error);
|
||
|
||
} // AlgRmBindInterface
|
||
|
||
|
||
ULONG
|
||
AlgRmUnbindInterface(
|
||
ULONG Index
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to unbind an interface from its IP address(es).
|
||
|
||
Arguments:
|
||
|
||
Index - the interface to be unbound
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code.
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Error = NO_ERROR;
|
||
PROFILE("AlgRmUnbindInterface");
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
/*
|
||
Error =
|
||
AlgUnbindInterface(
|
||
Index
|
||
);
|
||
*/
|
||
DEREFERENCE_ALG_AND_RETURN(Error);
|
||
|
||
} // AlgRmUnbindInterface
|
||
|
||
|
||
ULONG
|
||
AlgRmEnableInterface(
|
||
ULONG Index
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to enable operation on an interface.
|
||
|
||
Arguments:
|
||
|
||
Index - the interface to be enabled.
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code.
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Error = NO_ERROR;
|
||
PROFILE("AlgRmEnableInterface");
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
/*
|
||
Error =
|
||
AlgEnableInterface(
|
||
Index
|
||
);
|
||
*/
|
||
DEREFERENCE_ALG_AND_RETURN(Error);
|
||
|
||
} // AlgRmEnableInterface
|
||
|
||
|
||
ULONG
|
||
AlgRmDisableInterface(
|
||
ULONG Index
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to disable operation on an interface.
|
||
|
||
Arguments:
|
||
|
||
Index - the interface to be disabled.
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code.
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Error = NO_ERROR;
|
||
PROFILE("AlgRmDisableInterface");
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
DEREFERENCE_ALG_AND_RETURN(Error);
|
||
} // AlgRmDisableInterface
|
||
|
||
|
||
ULONG
|
||
APIENTRY
|
||
AlgRmGetGlobalInfo(
|
||
PVOID GlobalInfo,
|
||
IN OUT PULONG GlobalInfoSize,
|
||
IN OUT PULONG StructureVersion,
|
||
IN OUT PULONG StructureSize,
|
||
IN OUT PULONG StructureCount
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to retrieve the configuration for the component.
|
||
|
||
Arguments:
|
||
|
||
GlobalInfo - receives the configuration
|
||
|
||
GlobalInfoSize - receives the size of the configuration
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Size;
|
||
PROFILE("AlgRmGetGlobalInfo");
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
|
||
if (!GlobalInfoSize || (*GlobalInfoSize && !GlobalInfo)) {
|
||
DEREFERENCE_ALG_AND_RETURN(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
EnterCriticalSection(&AlgGlobalInfoLock);
|
||
Size = sizeof(*AlgGlobalInfo);
|
||
if (*GlobalInfoSize < Size) {
|
||
LeaveCriticalSection(&AlgGlobalInfoLock);
|
||
*StructureSize = *GlobalInfoSize = Size;
|
||
if (StructureCount) {*StructureCount = 1;}
|
||
DEREFERENCE_ALG_AND_RETURN(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
CopyMemory(GlobalInfo, AlgGlobalInfo, Size);
|
||
LeaveCriticalSection(&AlgGlobalInfoLock);
|
||
*StructureSize = *GlobalInfoSize = Size;
|
||
if (StructureCount) {*StructureCount = 1;}
|
||
|
||
DEREFERENCE_ALG_AND_RETURN(NO_ERROR);
|
||
} // AlgRmGetGlobalInfo
|
||
|
||
|
||
ULONG
|
||
APIENTRY
|
||
AlgRmSetGlobalInfo(
|
||
PVOID GlobalInfo,
|
||
ULONG StructureVersion,
|
||
ULONG StructureSize,
|
||
ULONG StructureCount
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to change the configuration for the component.
|
||
|
||
Arguments:
|
||
|
||
GlobalInfo - the new configuration
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code
|
||
|
||
Environment:
|
||
|
||
The routine runs in the context of an IP router-manager thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG OldFlags;
|
||
ULONG NewFlags;
|
||
PIP_ALG_GLOBAL_INFO NewInfo;
|
||
ULONG Size;
|
||
|
||
PROFILE("AlgRmSetGlobalInfo");
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
|
||
if (!GlobalInfo) { DEREFERENCE_ALG_AND_RETURN(ERROR_INVALID_PARAMETER); }
|
||
|
||
Size = sizeof(*AlgGlobalInfo);
|
||
NewInfo = reinterpret_cast<PIP_ALG_GLOBAL_INFO>(NH_ALLOCATE(Size));
|
||
if (!NewInfo) {
|
||
NhTrace(
|
||
TRACE_FLAG_INIT,
|
||
"AlgRmSetGlobalInfo: error reallocating global info"
|
||
);
|
||
NhErrorLog(
|
||
IP_ALG_LOG_ALLOCATION_FAILED,
|
||
0,
|
||
"%d",
|
||
Size
|
||
);
|
||
DEREFERENCE_ALG_AND_RETURN(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
CopyMemory(NewInfo, GlobalInfo, Size);
|
||
|
||
EnterCriticalSection(&AlgGlobalInfoLock);
|
||
OldFlags = AlgGlobalInfo->Flags;
|
||
NH_FREE(AlgGlobalInfo);
|
||
AlgGlobalInfo = NewInfo;
|
||
NewFlags = AlgGlobalInfo->Flags;
|
||
LeaveCriticalSection(&AlgGlobalInfoLock);
|
||
|
||
DEREFERENCE_ALG_AND_RETURN(NO_ERROR);
|
||
} // AlgRmSetGlobalInfo
|
||
|
||
ULONG
|
||
AlgRmPortMappingChanged(
|
||
ULONG Index,
|
||
UCHAR Protocol,
|
||
USHORT Port
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked when a port mapping has changed for
|
||
an interface.
|
||
|
||
Arguments:
|
||
|
||
Index - the index of the interface on which the port mapping
|
||
changed.
|
||
|
||
Protcol - the IP protocol for the port mapping
|
||
|
||
Port - the port for the port mapping
|
||
|
||
Return Value:
|
||
|
||
ULONG - Win32 status code
|
||
|
||
Environment:
|
||
|
||
This method must be called by a COM-initialized thread.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Error = NO_ERROR;
|
||
HRESULT hr;
|
||
IAlgController* pIAlgController;
|
||
|
||
PROFILE("AlgRmPortMappingChanged");
|
||
|
||
REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
|
||
|
||
hr = GetAlgControllerInterface(&pIAlgController);
|
||
if (SUCCEEDED(hr))
|
||
{
|
||
hr = pIAlgController->Adapter_PortMappingChanged(
|
||
Index,
|
||
Protocol,
|
||
Port
|
||
);
|
||
|
||
pIAlgController->Release();
|
||
}
|
||
|
||
if (FAILED(hr))
|
||
{
|
||
Error = ERROR_CAN_NOT_COMPLETE;
|
||
}
|
||
|
||
DEREFERENCE_ALG_AND_RETURN(Error);
|
||
} // AlgRmPortMappingChanged
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|