mirror of https://github.com/tongzx/nt5src
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.
1450 lines
28 KiB
1450 lines
28 KiB
/*++
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|