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.
1745 lines
47 KiB
1745 lines
47 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ApplicationGatewayServices.cpp : Implementation of CApplicationGatewayServices
|
|
|
|
Abstract:
|
|
|
|
This module contains routines for the ALG Manager module's
|
|
that expose a public api via COM.
|
|
|
|
Author:
|
|
|
|
Jon Burstein
|
|
Jean-Pierre Duplessis
|
|
|
|
JPDup 10-Nov-2000
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CApplicationGatewayServices
|
|
//
|
|
// ApplicationGatewayServices.cpp : Implementation of CApplicationGatewayServices
|
|
//
|
|
|
|
#include "PreComp.h"
|
|
#include "AlgController.h"
|
|
#include "ApplicationGatewayServices.h"
|
|
#include "PendingProxyConnection.h"
|
|
#include "DataChannel.h"
|
|
#include "PersistentDataChannel.h"
|
|
#include "EnumAdapterInfo.h"
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::CreatePrimaryControlChannel(
|
|
IN ALG_PROTOCOL eProtocol,
|
|
IN USHORT usPortToCapture,
|
|
IN ALG_CAPTURE eCaptureType,
|
|
IN BOOL fCaptureInbound,
|
|
IN ULONG ulListenAddress,
|
|
IN USHORT usListenPort,
|
|
OUT IPrimaryControlChannel** ppIControlChannel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
eProtocol,
|
|
usPortToCapture,
|
|
eCaptureType,
|
|
fCaptureInbound,
|
|
ulListenAddress,
|
|
usListenPort,
|
|
ppIControlChannel
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::CreatePrimaryControlChannel")
|
|
MYTRACE("eProtocol %s", eProtocol==1? "TCP" : "UDP");
|
|
MYTRACE("usPortToCapture %d", ntohs(usPortToCapture));
|
|
MYTRACE("eCaptureType %s", eCaptureType==eALG_SOURCE_CAPTURE ? "eALG_SOURCE_CAPTURE" : "eALG_DESTINATION_CAPTURE");
|
|
MYTRACE("fCaptureInbound %d", fCaptureInbound);
|
|
MYTRACE("ulListenAddress %s:%d", MYTRACE_IP(ulListenAddress), ntohs(usListenPort));
|
|
|
|
|
|
if ( !ppIControlChannel )
|
|
{
|
|
MYTRACE_ERROR("ppIControlChannel not supplied",0);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
if ( eProtocol != eALG_TCP && eProtocol != eALG_UDP )
|
|
{
|
|
MYTRACE_ERROR("Arg - eProtocol",0);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
if ( eCaptureType == eALG_SOURCE_CAPTURE && fCaptureInbound )
|
|
{
|
|
MYTRACE_ERROR("Can not have SOURCE CAPTURE and fCaptureInBount at same time",0);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Add new ControlChannel to List of RULES
|
|
//
|
|
CComObject<CPrimaryControlChannel>* pIChannel;
|
|
hr = CComObject<CPrimaryControlChannel>::CreateInstance(&pIChannel);
|
|
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
pIChannel->AddRef();
|
|
|
|
pIChannel->m_Properties.eProtocol = eProtocol;
|
|
pIChannel->m_Properties.eCaptureType = eCaptureType;
|
|
pIChannel->m_Properties.fCaptureInbound = fCaptureInbound;
|
|
pIChannel->m_Properties.ulListeningAddress = ulListenAddress;
|
|
pIChannel->m_Properties.usCapturePort = usPortToCapture;
|
|
pIChannel->m_Properties.usListeningPort = usListenPort;
|
|
|
|
hr = pIChannel->QueryInterface(IID_IPrimaryControlChannel, (void**)ppIControlChannel);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = g_pAlgController->m_ControlChannelsPrimary.Add(pIChannel);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("from m_ControlChannelsPrimary.Add", hr);
|
|
|
|
(*ppIControlChannel)->Release();
|
|
*ppIControlChannel = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MYTRACE_ERROR("from pIChannel->QueryInterface", hr);
|
|
}
|
|
|
|
pIChannel->Release();
|
|
|
|
}
|
|
else
|
|
{
|
|
MYTRACE_ERROR("CreateInstance(&pIChannel);", hr);
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::CreateSecondaryControlChannel(
|
|
IN ALG_PROTOCOL eProtocol,
|
|
|
|
IN ULONG ulPrivateAddress,
|
|
IN USHORT usPrivatePort,
|
|
|
|
IN ULONG ulPublicAddress,
|
|
IN USHORT usPublicPort,
|
|
|
|
IN ULONG ulRemoteAddress,
|
|
IN USHORT usRemotePort,
|
|
|
|
IN ULONG ulListenAddress,
|
|
IN USHORT usListenPort,
|
|
|
|
IN ALG_DIRECTION eDirection,
|
|
IN BOOL fPersistent,
|
|
OUT ISecondaryControlChannel** ppIControlChannel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
eProtocol,
|
|
ulPrivateAddress,
|
|
usPrivatePort,
|
|
ulPublicAddress,
|
|
usPublicPort,
|
|
ulRemoteAddress,
|
|
usRemotePort,
|
|
ulListenAddress,
|
|
usListenPort,
|
|
eDirection,
|
|
fPersistent,
|
|
ppIControlChannel
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::CreateSecondaryControlChannel");
|
|
|
|
if ( !ppIControlChannel )
|
|
{
|
|
MYTRACE_ERROR("ppIControlChannel not supplied",0);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
ULONG ulSourceAddress=0;
|
|
USHORT usSourcePort=0;
|
|
|
|
ULONG ulDestinationAddress=0;
|
|
USHORT usDestinationPort=0;
|
|
|
|
ULONG ulNewSourceAddress=0;
|
|
USHORT usNewSourcePort=0;
|
|
|
|
ULONG ulNewDestinationAddress=0;
|
|
USHORT usNewDestinationPort=0;
|
|
|
|
ULONG nFlags=0;
|
|
|
|
ULONG ulRestrictAdapterIndex=0;
|
|
|
|
|
|
|
|
if ( eALG_INBOUND == eDirection )
|
|
{
|
|
if ( ulPublicAddress == 0 || usPublicPort == 0 )
|
|
{
|
|
//
|
|
// Madatory arguments for INBOUND
|
|
//
|
|
MYTRACE_ERROR("ulPublicAddress == 0 || usPublicPort == 0", E_INVALIDARG);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// All inbound cases map to a single redirect; unlike a primary control channel, there's no need to create per-adapter redirects.
|
|
//
|
|
|
|
if ( ulRemoteAddress==0 && usRemotePort == 0 )
|
|
{
|
|
//
|
|
// Scenario #1a
|
|
//
|
|
// Inbound connection from unknown machine
|
|
//
|
|
MYTRACE("SCENARIO:eALG_INBOUND #1a");
|
|
|
|
nFlags = NatRedirectFlagReceiveOnly;
|
|
|
|
ulSourceAddress = 0;
|
|
usSourcePort = 0;
|
|
|
|
ulDestinationAddress = ulPublicAddress;
|
|
usDestinationPort = usPublicPort;
|
|
|
|
ulNewSourceAddress = 0;
|
|
usNewSourcePort = 0;
|
|
|
|
ulNewDestinationAddress = ulListenAddress;
|
|
usNewDestinationPort = usListenPort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
if ( ulRemoteAddress !=0 && usRemotePort == 0 )
|
|
{
|
|
//
|
|
// Scenario #1b
|
|
//
|
|
// Inbound connection from known machine, but unknown port
|
|
//
|
|
MYTRACE("SCENARIO:eALG_INBOUND #1b");
|
|
nFlags = NatRedirectFlagReceiveOnly|NatRedirectFlagRestrictSource;
|
|
|
|
ulSourceAddress = ulRemoteAddress;
|
|
usSourcePort = 0;
|
|
|
|
ulDestinationAddress = ulPublicAddress;
|
|
usDestinationPort = usPublicPort;
|
|
|
|
ulNewSourceAddress = 0;
|
|
usNewSourcePort = 0;
|
|
|
|
ulNewDestinationAddress = ulListenAddress;
|
|
usNewDestinationPort = usListenPort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
|
|
}
|
|
else
|
|
if ( ulRemoteAddress !=0 && usRemotePort != 0 )
|
|
{
|
|
//
|
|
// Scenario #1c
|
|
//
|
|
// Inbound connection from known machine and port
|
|
//
|
|
MYTRACE("SCENARIO:eALG_INBOUND #1c");
|
|
|
|
nFlags = NatRedirectFlagReceiveOnly;
|
|
|
|
ulSourceAddress = ulRemoteAddress;
|
|
usSourcePort = usRemotePort;
|
|
|
|
ulDestinationAddress = ulPublicAddress;
|
|
usDestinationPort = usPublicPort;
|
|
|
|
ulNewSourceAddress = ulRemoteAddress;
|
|
usNewSourcePort = usRemotePort;
|
|
|
|
ulNewDestinationAddress = ulListenAddress;
|
|
usNewDestinationPort = usListenPort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
else
|
|
if ( eALG_OUTBOUND == eDirection )
|
|
{
|
|
//
|
|
// These cases can also be handled by a single ul
|
|
//
|
|
|
|
if ( ulRemoteAddress !=0 && usRemotePort != 0 && ulPrivateAddress == 0 && usPrivatePort == 0 )
|
|
{
|
|
//
|
|
// Scenario #2a
|
|
//
|
|
// Outbound connection to known machine/port, from any private machine
|
|
//
|
|
MYTRACE("SCENARIO:eALG_OUTBOUND #2a");
|
|
|
|
nFlags = 0;
|
|
|
|
ulSourceAddress = 0;
|
|
usSourcePort = 0;
|
|
|
|
ulDestinationAddress = ulRemoteAddress;
|
|
usDestinationPort = usRemotePort;
|
|
|
|
ulNewSourceAddress = 0;
|
|
usNewSourcePort = 0;
|
|
|
|
ulNewDestinationAddress = ulListenAddress;
|
|
usNewDestinationPort = usListenPort;
|
|
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
if ( ulRemoteAddress !=0 && usRemotePort != 0 && ulPrivateAddress != 0 && usPrivatePort == 0 )
|
|
{
|
|
//
|
|
// Scenario #2b
|
|
//
|
|
// Outbound connection to known machine/port, from a specific private machine
|
|
//
|
|
MYTRACE("SCENARIO:eALG_OUTBOUND #2b");
|
|
nFlags = NatRedirectFlagRestrictSource;
|
|
|
|
ulSourceAddress = ulPrivateAddress;
|
|
usSourcePort = 0;
|
|
|
|
ulDestinationAddress = ulRemoteAddress;
|
|
usDestinationPort = usRemotePort;
|
|
|
|
ulNewSourceAddress = 0;
|
|
usNewSourcePort = 0;
|
|
|
|
ulNewDestinationAddress = ulListenAddress;
|
|
usNewDestinationPort = usListenPort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
if ( ulRemoteAddress !=0 && usRemotePort != 0 && ulPrivateAddress != 0 && usPrivatePort != 0 )
|
|
{
|
|
//
|
|
// Scenario #2c
|
|
//
|
|
// Outbound connection to known machine/port, from a specific port on a specific private machine
|
|
//
|
|
MYTRACE("SCENARIO:eALG_OUTBOUND #2c");
|
|
nFlags = 0;
|
|
|
|
ulSourceAddress = ulPrivateAddress;
|
|
usSourcePort = usPrivatePort;
|
|
|
|
ulDestinationAddress = ulRemoteAddress;
|
|
usDestinationPort = usRemotePort;
|
|
|
|
ulNewSourceAddress = ulPrivateAddress;
|
|
usNewSourcePort = usPrivatePort;
|
|
|
|
ulNewDestinationAddress = ulListenAddress;
|
|
usNewDestinationPort = usListenPort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
if ( ulPrivateAddress != 0 && usPrivatePort != 0 && ulRemoteAddress == 0 && usRemotePort == 0 )
|
|
{
|
|
//
|
|
// Scenario #2d
|
|
//
|
|
// Outbound connection from a specific port on a specific private machine, to an unknown machine
|
|
//
|
|
MYTRACE("SCENARIO:eALG_OUTBOUND #2d");
|
|
nFlags = NatRedirectFlagSourceRedirect;
|
|
|
|
ulSourceAddress = ulPrivateAddress;
|
|
usSourcePort = usPrivatePort;
|
|
|
|
ulDestinationAddress = 0;
|
|
usDestinationPort = 0;
|
|
|
|
ulNewSourceAddress = ulPrivateAddress;
|
|
usNewSourcePort = usPrivatePort;
|
|
|
|
ulNewDestinationAddress = ulListenAddress;
|
|
usNewDestinationPort = usListenPort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
if ( ulPrivateAddress != 0 && usPrivatePort != 0 && ulRemoteAddress != 0 && usRemotePort == 0 )
|
|
{
|
|
//
|
|
// Scenario #2e
|
|
//
|
|
// Outbound connection from a specific port on a specific private machine, to a known machine
|
|
//
|
|
MYTRACE("SCENARIO:eALG_OUTBOUND #2e");
|
|
nFlags = 0;
|
|
|
|
ulSourceAddress = ulPrivateAddress;
|
|
usSourcePort = usPrivatePort;
|
|
|
|
ulDestinationAddress = ulRemoteAddress;
|
|
usDestinationPort = 0;
|
|
|
|
ulNewSourceAddress = ulPrivateAddress;
|
|
usNewSourcePort = usPrivatePort;
|
|
|
|
ulNewDestinationAddress = ulListenAddress;
|
|
usNewDestinationPort = usListenPort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//
|
|
//
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr;
|
|
HANDLE_PTR HandleDynamicRedirect=NULL;
|
|
|
|
if ( fPersistent )
|
|
{
|
|
// Dynamic
|
|
hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
|
|
nFlags,
|
|
0, // Adapter Index
|
|
(UCHAR)eProtocol,
|
|
|
|
ulDestinationAddress, // ULONG DestinationAddress
|
|
usDestinationPort, // USHORT DestinationPort
|
|
|
|
ulSourceAddress, // ULONG SourceAddress
|
|
usSourcePort, // USHORT SourcePort
|
|
|
|
ulNewDestinationAddress, // ULONG NewDestinationAddress
|
|
usNewDestinationPort, // USHORT NewDestinationPort
|
|
|
|
ulNewSourceAddress, // ULONG NewSourceAddress
|
|
usNewSourcePort, // USHORT NewSourcePort
|
|
|
|
&HandleDynamicRedirect
|
|
);
|
|
}
|
|
else
|
|
{
|
|
|
|
// Normal
|
|
hr = g_pAlgController->GetNat()->CreateRedirect(
|
|
nFlags,
|
|
(UCHAR)eProtocol,
|
|
|
|
ulDestinationAddress, // ULONG DestinationAddress
|
|
usDestinationPort, // USHORT DestinationPort
|
|
|
|
ulSourceAddress, // ULONG SourceAddress
|
|
usSourcePort, // USHORT SourcePort
|
|
|
|
ulNewDestinationAddress, // ULONG NewDestinationAddress
|
|
usNewDestinationPort, // USHORT NewDestinationPort
|
|
|
|
ulNewSourceAddress, // ULONG NewSourceAddress
|
|
usNewSourcePort, // USHORT NewSourcePort
|
|
|
|
ulRestrictAdapterIndex, // ULONG RestrictAdapterIndex
|
|
|
|
0, // DWORD_PTR ThisProcessID
|
|
NULL, // HANDLE_PTR CreateEvent
|
|
NULL // HANDLE_PTR DeleteEvent
|
|
);
|
|
}
|
|
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("From g_pAlgController->GetNat()->CreateRedirect", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Add new ControlChannel to List
|
|
//
|
|
CComObject<CSecondaryControlChannel>* pIChannel;
|
|
hr = CComObject<CSecondaryControlChannel>::CreateInstance(&pIChannel);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
pIChannel->AddRef();
|
|
|
|
pIChannel->m_Properties.eProtocol = eProtocol;
|
|
pIChannel->m_Properties.ulPrivateAddress = ulPrivateAddress;
|
|
pIChannel->m_Properties.usPrivatePort = usPrivatePort;
|
|
pIChannel->m_Properties.ulPublicAddress = ulPublicAddress;
|
|
pIChannel->m_Properties.usPublicPort = usPublicPort;
|
|
pIChannel->m_Properties.ulRemoteAddress = ulRemoteAddress;
|
|
pIChannel->m_Properties.usRemotePort = usRemotePort;
|
|
pIChannel->m_Properties.ulListenAddress = ulListenAddress;
|
|
pIChannel->m_Properties.usListenPort = usListenPort;
|
|
pIChannel->m_Properties.eDirection = eDirection;
|
|
pIChannel->m_Properties.fPersistent = fPersistent;
|
|
|
|
//
|
|
// Cache calling parameters used to create the redirect we will need them to cancel the redirect
|
|
//
|
|
pIChannel->m_ulDestinationAddress = ulDestinationAddress;
|
|
pIChannel->m_usDestinationPort = usDestinationPort;
|
|
|
|
pIChannel->m_ulSourceAddress = ulSourceAddress;
|
|
pIChannel->m_usSourcePort = usSourcePort;
|
|
|
|
pIChannel->m_ulNewDestinationAddress = ulNewDestinationAddress;
|
|
pIChannel->m_usNewDestinationPort = usNewDestinationPort;
|
|
|
|
pIChannel->m_ulNewSourceAddress = ulNewSourceAddress;
|
|
pIChannel->m_usNewSourcePort = usNewSourcePort;
|
|
|
|
pIChannel->m_HandleDynamicRedirect = HandleDynamicRedirect;
|
|
|
|
|
|
hr = pIChannel->QueryInterface(IID_ISecondaryControlChannel, (void**)ppIControlChannel);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = g_pAlgController->m_ControlChannelsSecondary.Add(pIChannel);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Adding to list of SecondaryChannel", hr);
|
|
|
|
(*ppIControlChannel)->Release();
|
|
*ppIControlChannel=NULL;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MYTRACE_ERROR("QueryInterface(IID_ISecondaryControlChannel", hr);
|
|
}
|
|
|
|
pIChannel->Release();
|
|
|
|
}
|
|
else
|
|
{
|
|
MYTRACE_ERROR("From CreateInstance<CSecondaryControlChannel>", hr);
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::GetBestSourceAddressForDestinationAddress(
|
|
IN ULONG ulDestinationAddress,
|
|
IN BOOL fDemandDial,
|
|
OUT ULONG* pulBestSrcAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We create a temporary UDP socket, connect the socket to the
|
|
actual client's IP address, extract the IP address to which
|
|
the socket is implicitly bound by the TCP/IP driver, and
|
|
discard the socket. This leaves us with the exact IP address
|
|
that we need to use to contact the client.
|
|
|
|
Arguments:
|
|
|
|
ulDestinationAddress,
|
|
fDemandDial,
|
|
pulBestSrcAddress
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::GetBestSourceAddressForDestinationAddress");
|
|
|
|
HRESULT hr = g_pAlgController->GetNat()->GetBestSourceAddressForDestinationAddress(
|
|
ulDestinationAddress,
|
|
fDemandDial,
|
|
pulBestSrcAddress
|
|
);
|
|
|
|
MYTRACE("For Destination address of %s", MYTRACE_IP(ulDestinationAddress) );
|
|
MYTRACE("the Best source address is %s", MYTRACE_IP(*pulBestSrcAddress) );
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::PrepareProxyConnection(
|
|
IN ALG_PROTOCOL eProtocol,
|
|
|
|
IN ULONG ulSourceAddress,
|
|
IN USHORT usSourcePort,
|
|
|
|
IN ULONG ulDestinationAddress,
|
|
IN USHORT usDestinationPort,
|
|
|
|
IN BOOL fNoTimeout,
|
|
OUT IPendingProxyConnection** ppPendingConnection
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
If we have a firwewall interface, possibly install a
|
|
shadow redirect for this connection. The shadow redirect
|
|
is necessary to prevent this connection from also being
|
|
redirected to the proxy (setting in motion an infinite loop...)
|
|
|
|
|
|
Arguments:
|
|
|
|
eProtocol,
|
|
|
|
ulSourceAddress,
|
|
usSourcePort,
|
|
|
|
ulDestinationAddress,
|
|
usDestinationPort,
|
|
|
|
fNoTimeout,
|
|
ppPendingConnection
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::PrepareProxyConnection");
|
|
|
|
MYTRACE("eProtocol %s", eProtocol==1? "TCP" : "UDP");
|
|
MYTRACE("Source %s:%d", MYTRACE_IP(ulSourceAddress), ntohs(usSourcePort));
|
|
MYTRACE("Destination %s:%d", MYTRACE_IP(ulDestinationAddress), ntohs(usDestinationPort));
|
|
MYTRACE("NoTimeout %d", fNoTimeout);
|
|
|
|
ULONG ulFlags = NatRedirectFlagLoopback;
|
|
|
|
|
|
if ( !ppPendingConnection )
|
|
{
|
|
MYTRACE_ERROR("ppPendingConnection not supplied",0);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
if ( fNoTimeout )
|
|
{
|
|
MYTRACE("NoTimeout specified");
|
|
|
|
if ( eProtocol == eALG_UDP )
|
|
{
|
|
ulFlags |= NatRedirectFlagNoTimeout;
|
|
}
|
|
else
|
|
{
|
|
MYTRACE("Wrong use of fNoTimeout && eProtocol != eALG_UDP");
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT hr = g_pAlgController->GetNat()->CreateRedirect(
|
|
ulFlags,
|
|
(UCHAR)eProtocol,
|
|
|
|
ulDestinationAddress, // ULONG DestinationAddress,
|
|
usDestinationPort, // USHORT DestinationPort,
|
|
|
|
ulSourceAddress, // ULONG SourceAddress,
|
|
usSourcePort, // USHORT SourcePort,
|
|
|
|
ulDestinationAddress, // ULONG NewDestinationAddress
|
|
usDestinationPort, // USHORT NewDestinationPort
|
|
|
|
ulSourceAddress, // ULONG NewSourceAddress,
|
|
usSourcePort, // USHORT NewSourcePort,
|
|
|
|
0, // ULONG RestrictAdapterIndex
|
|
|
|
0, // DWORD_PTR ThisProcessID
|
|
NULL, // HANDLE_PTR CreateEvent
|
|
NULL // HANDLE_PTR DeleteEvent
|
|
);
|
|
|
|
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
CComObject<CPendingProxyConnection>* pIPendingProxyConnection;
|
|
CComObject<CPendingProxyConnection>::CreateInstance(&pIPendingProxyConnection);
|
|
|
|
pIPendingProxyConnection->m_eProtocol = eProtocol;
|
|
pIPendingProxyConnection->m_ulDestinationAddress = ulDestinationAddress;
|
|
pIPendingProxyConnection->m_usDestinationPort = usDestinationPort;
|
|
|
|
pIPendingProxyConnection->m_ulSourceAddress = ulSourceAddress;
|
|
pIPendingProxyConnection->m_usSourcePort = usSourcePort;
|
|
|
|
pIPendingProxyConnection->m_ulNewSourceAddress = ulSourceAddress; // Since the PendingProxyConenction is also used
|
|
pIPendingProxyConnection->m_usNewSourcePort = usSourcePort; // by PrepareSourceModifiedProxyConnection we use the NewSource
|
|
// for the Cancel
|
|
|
|
pIPendingProxyConnection->QueryInterface(ppPendingConnection);
|
|
|
|
}
|
|
else
|
|
{
|
|
MYTRACE_ERROR(">GetNat()->CreateRedirect failed", hr);
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::PrepareSourceModifiedProxyConnection(
|
|
IN ALG_PROTOCOL eProtocol,
|
|
IN ULONG ulSourceAddress,
|
|
IN USHORT usSrcPort,
|
|
IN ULONG ulDestinationAddress,
|
|
IN USHORT usDestinationPort,
|
|
IN ULONG ulNewSrcAddress,
|
|
IN USHORT usNewSourcePort,
|
|
OUT IPendingProxyConnection** ppPendingConnection
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
eProtocol,
|
|
ulSourceAddress,
|
|
usSrcPort,
|
|
ulDestinationAddress,
|
|
usDestinationPort,
|
|
ulNewSrcAddress,
|
|
usNewSourcePort,
|
|
ppPendingConnection
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::PrepareSourceModifiedProxyConnection");
|
|
MYTRACE("Source %s:%d", MYTRACE_IP(ulSourceAddress), ntohs(usSrcPort));
|
|
MYTRACE("Destination %s:%d", MYTRACE_IP(ulDestinationAddress), ntohs(usDestinationPort));
|
|
MYTRACE("NewSource %s:%d", MYTRACE_IP(ulNewSrcAddress), ntohs(usNewSourcePort));
|
|
|
|
if ( !ppPendingConnection )
|
|
{
|
|
MYTRACE_ERROR("IPendingProxyConnection** not supplied",0);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
|
|
HRESULT hr = g_pAlgController->GetNat()->CreateRedirect(
|
|
NatRedirectFlagLoopback,
|
|
(UCHAR)eProtocol,
|
|
|
|
ulDestinationAddress, // ULONG DestinationAddress,
|
|
usDestinationPort, // USHORT DestinationPort,
|
|
|
|
ulSourceAddress, // ULONG SourceAddress,
|
|
usSrcPort, // USHORT SourcePort,
|
|
|
|
ulDestinationAddress, // ULONG NewDestinationAddress
|
|
usDestinationPort, // USHORT NewDestinationPort
|
|
|
|
ulNewSrcAddress, // ULONG NewSourceAddress,
|
|
usNewSourcePort, // USHORT NewSourcePort,
|
|
|
|
0, // ULONG RestrictAdapterIndex
|
|
|
|
0, // DWORD_PTR ThisProcessID
|
|
NULL, // HANDLE_PTR CreateEvent
|
|
NULL // HANDLE_PTR DeleteEvent
|
|
);
|
|
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
CComObject<CPendingProxyConnection>* pIPendingProxyConnection;
|
|
CComObject<CPendingProxyConnection>::CreateInstance(&pIPendingProxyConnection);
|
|
|
|
pIPendingProxyConnection->m_eProtocol = eProtocol;
|
|
pIPendingProxyConnection->m_ulDestinationAddress = ulDestinationAddress;
|
|
pIPendingProxyConnection->m_usDestinationPort = usDestinationPort;
|
|
|
|
pIPendingProxyConnection->m_ulSourceAddress = ulSourceAddress;
|
|
pIPendingProxyConnection->m_usSourcePort = usSrcPort;
|
|
|
|
pIPendingProxyConnection->m_ulNewSourceAddress = ulNewSrcAddress;
|
|
pIPendingProxyConnection->m_usNewSourcePort = usNewSourcePort;
|
|
|
|
hr = pIPendingProxyConnection->QueryInterface(ppPendingConnection);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
GetRedirectParameters(
|
|
IN ALG_DIRECTION eDirection,
|
|
IN ALG_PROTOCOL eProtocol,
|
|
|
|
IN ULONG ulPrivateAddress,
|
|
IN USHORT usPrivatePort,
|
|
IN ULONG ulPublicAddress,
|
|
IN USHORT usPublicPort,
|
|
IN ULONG ulRemoteAddress,
|
|
IN USHORT usRemotePort,
|
|
|
|
OUT ULONG& ulFlags,
|
|
OUT ULONG& ulSourceAddress,
|
|
OUT USHORT& usSourcePort,
|
|
OUT ULONG& ulDestinationAddress,
|
|
OUT USHORT& usDestinationPort,
|
|
OUT ULONG& ulNewSourceAddress,
|
|
OUT USHORT& usNewSourcePort,
|
|
OUT ULONG& ulNewDestinationAddress,
|
|
OUT USHORT& usNewDestinationPort,
|
|
|
|
OUT ULONG& ulRestrictAdapterIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The logic in these scenario are use by CreateDataChannel and CreatePersitenDataChannel
|
|
|
|
Arguments:
|
|
|
|
eProtocol,
|
|
ulSourceAddress,
|
|
usSrcPort,
|
|
ulDestinationAddress,
|
|
usDestinationPort,
|
|
ulNewSrcAddress,
|
|
usNewSourcePort,
|
|
ppPendingConnection
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
|
|
|
|
if ( eALG_INBOUND == eDirection )
|
|
{
|
|
if ( ulRemoteAddress == 0 && usRemotePort == 0 )
|
|
{
|
|
// 1a
|
|
ulFlags = NatRedirectFlagReceiveOnly;
|
|
|
|
ulSourceAddress = 0;
|
|
usSourcePort = 0;
|
|
ulDestinationAddress = ulPublicAddress;
|
|
usDestinationPort = usPublicPort;
|
|
ulNewSourceAddress = 0;
|
|
usNewSourcePort = 0;
|
|
ulNewDestinationAddress = ulPrivateAddress;
|
|
usNewDestinationPort = usPrivatePort;
|
|
ulRestrictAdapterIndex = 0;
|
|
|
|
}
|
|
else
|
|
if ( ulRemoteAddress != 0 && usRemotePort == 0 )
|
|
{
|
|
// 1b
|
|
ulFlags = NatRedirectFlagReceiveOnly|NatRedirectFlagRestrictSource;
|
|
|
|
ulSourceAddress = ulRemoteAddress;
|
|
usSourcePort = 0;
|
|
ulDestinationAddress = ulPublicAddress;
|
|
usDestinationPort = usPublicPort;
|
|
ulNewSourceAddress = 0;
|
|
usNewSourcePort = 0;
|
|
ulNewDestinationAddress = ulPrivateAddress;
|
|
usNewDestinationPort = usPrivatePort;
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
if ( ulRemoteAddress != 0 && usRemotePort != 0 )
|
|
{
|
|
// 1c.
|
|
ulFlags = NatRedirectFlagReceiveOnly;
|
|
|
|
ulSourceAddress = ulRemoteAddress;
|
|
usSourcePort = usRemotePort;
|
|
ulDestinationAddress = ulPublicAddress;
|
|
usDestinationPort = usPublicPort;
|
|
ulNewSourceAddress = ulRemoteAddress;
|
|
usNewSourcePort = usRemotePort;
|
|
ulNewDestinationAddress = ulPrivateAddress;
|
|
usNewDestinationPort = usPrivatePort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
if ( eALG_OUTBOUND == eDirection )
|
|
{
|
|
if ( ulPrivateAddress == 0 && usPrivatePort == 0 )
|
|
{
|
|
// 2a.
|
|
ulFlags = 0;
|
|
ulSourceAddress = 0;
|
|
usSourcePort = 0;
|
|
ulDestinationAddress = ulRemoteAddress;
|
|
usDestinationPort = usRemotePort;
|
|
ulNewSourceAddress = ulPublicAddress;
|
|
usNewSourcePort = usPublicPort;
|
|
ulNewDestinationAddress = ulRemoteAddress;
|
|
usNewDestinationPort = usRemotePort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
if ( ulPrivateAddress != 0 && usPrivatePort == 0 )
|
|
{
|
|
// 2b.
|
|
ulFlags = NatRedirectFlagRestrictSource;
|
|
ulSourceAddress = ulPrivateAddress;
|
|
usSourcePort = 0;
|
|
ulDestinationAddress = ulRemoteAddress;
|
|
usDestinationPort = usRemotePort;
|
|
ulNewSourceAddress = ulPublicAddress;
|
|
usNewSourcePort = usPublicPort;
|
|
ulNewDestinationAddress = ulRemoteAddress;
|
|
usNewDestinationPort = usRemotePort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
if ( ulPrivateAddress != 0 && usPrivatePort != 0 )
|
|
{
|
|
// 2c.
|
|
ulFlags = 0;
|
|
ulSourceAddress = ulPrivateAddress;
|
|
usSourcePort = usPrivatePort;
|
|
ulDestinationAddress = ulRemoteAddress;
|
|
usDestinationPort = usRemotePort;
|
|
ulNewSourceAddress = ulPublicAddress;
|
|
usNewSourcePort = usPublicPort;
|
|
ulNewDestinationAddress = ulRemoteAddress;
|
|
usNewDestinationPort = usRemotePort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
if ( (eALG_INBOUND | eALG_OUTBOUND) == eDirection )
|
|
{
|
|
ulFlags = 0;
|
|
ulSourceAddress = ulRemoteAddress;
|
|
usSourcePort = usRemotePort;
|
|
ulDestinationAddress = ulPublicAddress;
|
|
usDestinationPort = usPublicPort;
|
|
ulNewSourceAddress = ulRemoteAddress;
|
|
usNewSourcePort = usRemotePort;
|
|
ulNewDestinationAddress = ulPrivateAddress;
|
|
usNewDestinationPort = usPrivatePort;
|
|
|
|
ulRestrictAdapterIndex = 0;
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::CreateDataChannel(
|
|
IN ALG_PROTOCOL eProtocol,
|
|
IN ULONG ulPrivateAddress,
|
|
IN USHORT usPrivatePort,
|
|
IN ULONG ulPublicAddress,
|
|
IN USHORT usPublicPort,
|
|
IN ULONG ulRemoteAddress,
|
|
IN USHORT usRemotePort,
|
|
IN ALG_DIRECTION eDirection,
|
|
IN ALG_NOTIFICATION eDesiredNotification,
|
|
IN BOOL fNoTimeout,
|
|
OUT IDataChannel** ppDataChannel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
eProtocol,
|
|
ulPrivateAddress,
|
|
usPrivatePort,
|
|
ulPublicAddress,
|
|
usPublicPort,
|
|
ulRemoteAddress,
|
|
usRemotePort,
|
|
eDirection,
|
|
eDesiredNotification,
|
|
fNoTimeout,
|
|
ppDataChannel
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::CreateDataChannel");
|
|
|
|
if ( !ppDataChannel )
|
|
{
|
|
MYTRACE_ERROR("IDataChannel** not supplied",0);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
MYTRACE("eProtocol %d", eProtocol);
|
|
MYTRACE("ulPrivateAddress %s:%d", MYTRACE_IP(ulPrivateAddress), ntohs(usPrivatePort));
|
|
MYTRACE("ulPublicAddress %s:%d", MYTRACE_IP(ulPublicAddress), ntohs(usPublicPort));
|
|
MYTRACE("ulRemoteAddress %s:%d", MYTRACE_IP(ulRemoteAddress), ntohs(usRemotePort));
|
|
MYTRACE("eDirection %d", eDirection);
|
|
MYTRACE("eDesiredNotification %d", eDesiredNotification);
|
|
MYTRACE("fNoTimeout %d", fNoTimeout);
|
|
|
|
|
|
ULONG ulFlags=0;
|
|
|
|
ULONG ulSourceAddress=0;
|
|
USHORT usSourcePort=0;
|
|
ULONG ulDestinationAddress=0;
|
|
USHORT usDestinationPort=0;
|
|
ULONG ulNewSourceAddress=0;
|
|
USHORT usNewSourcePort=0;
|
|
ULONG ulNewDestinationAddress=0;
|
|
USHORT usNewDestinationPort=0;
|
|
|
|
ULONG ulRestrictAdapterIndex=0;
|
|
|
|
|
|
HRESULT hr = GetRedirectParameters(
|
|
// IN Params
|
|
eDirection,
|
|
eProtocol,
|
|
ulPrivateAddress,
|
|
usPrivatePort,
|
|
ulPublicAddress,
|
|
usPublicPort,
|
|
ulRemoteAddress,
|
|
usRemotePort,
|
|
|
|
// OUT Params
|
|
ulFlags,
|
|
ulSourceAddress,
|
|
usSourcePort,
|
|
ulDestinationAddress,
|
|
usDestinationPort,
|
|
ulNewSourceAddress,
|
|
usNewSourcePort,
|
|
ulNewDestinationAddress,
|
|
usNewDestinationPort,
|
|
ulRestrictAdapterIndex
|
|
);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("Invalid parameters pass", hr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
//
|
|
// Check for timeout
|
|
//
|
|
if ( fNoTimeout && eALG_UDP == eProtocol)
|
|
ulFlags |= NatRedirectFlagNoTimeout;
|
|
|
|
HANDLE_PTR hCreateEvent = NULL;
|
|
HANDLE_PTR hDeleteEvent = NULL;
|
|
|
|
//
|
|
// We need to events Create and Delete
|
|
//
|
|
if ( eALG_SESSION_CREATION & eDesiredNotification )
|
|
{
|
|
hCreateEvent = (HANDLE_PTR)CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if ( !hCreateEvent )
|
|
{
|
|
MYTRACE_ERROR("Could not create hCreateEvent", GetLastError());
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MYTRACE("NO eALG_SESSION_CREATION notification requested");
|
|
}
|
|
|
|
if ( eALG_SESSION_DELETION & eDesiredNotification )
|
|
{
|
|
hDeleteEvent = (HANDLE_PTR)CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if ( !hDeleteEvent )
|
|
{
|
|
MYTRACE_ERROR("Could not create hDeleteEvent", GetLastError());
|
|
if ( hCreateEvent )
|
|
CloseHandle((HANDLE)hCreateEvent);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MYTRACE("NO eALG_SESSION_DELETION notification requested");
|
|
}
|
|
|
|
//
|
|
// Create a IDataChannel and cache arg to be able CancelRedirect
|
|
//
|
|
hr = g_pAlgController->GetNat()->CreateRedirect(
|
|
ulFlags|NatRedirectFlagLoopback,
|
|
(UCHAR)eProtocol,
|
|
|
|
ulDestinationAddress,
|
|
usDestinationPort,
|
|
|
|
ulSourceAddress,
|
|
usSourcePort,
|
|
|
|
ulNewDestinationAddress,
|
|
usNewDestinationPort,
|
|
|
|
ulNewSourceAddress,
|
|
usNewSourcePort,
|
|
|
|
ulRestrictAdapterIndex,
|
|
|
|
GetCurrentProcessId(),
|
|
hCreateEvent,
|
|
hDeleteEvent
|
|
);
|
|
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("GetNAT()->CreateRedirect",hr);
|
|
if ( hCreateEvent )
|
|
CloseHandle((HANDLE)hCreateEvent);
|
|
|
|
if ( hDeleteEvent )
|
|
CloseHandle((HANDLE)hDeleteEvent);
|
|
return hr;
|
|
}
|
|
|
|
|
|
CComObject<CDataChannel>* pIDataChannel;
|
|
hr = CComObject<CDataChannel>::CreateInstance(&pIDataChannel);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
//
|
|
// Save these settings so to be able to return them to the user
|
|
// if the IDataChannel->GetProperties is called
|
|
//
|
|
pIDataChannel->m_Properties.eProtocol = eProtocol;
|
|
pIDataChannel->m_Properties.ulPrivateAddress = ulPrivateAddress;
|
|
pIDataChannel->m_Properties.usPrivatePort = usPrivatePort;
|
|
pIDataChannel->m_Properties.ulPublicAddress = ulPublicAddress;
|
|
pIDataChannel->m_Properties.usPublicPort = usPublicPort;
|
|
pIDataChannel->m_Properties.ulRemoteAddress = ulRemoteAddress;
|
|
pIDataChannel->m_Properties.usRemotePort = usRemotePort;
|
|
pIDataChannel->m_Properties.eDirection = eDirection;
|
|
pIDataChannel->m_Properties.eDesiredNotification = eDesiredNotification;
|
|
|
|
|
|
|
|
//
|
|
// Cache these arguments in order to implement IDataChannel->Cancel
|
|
//
|
|
pIDataChannel->m_ulSourceAddress = ulSourceAddress;
|
|
pIDataChannel->m_usSourcePort = usSourcePort;
|
|
pIDataChannel->m_ulDestinationAddress = ulDestinationAddress;
|
|
pIDataChannel->m_usDestinationPort = usDestinationPort;
|
|
pIDataChannel->m_ulNewSourceAddress = ulNewSourceAddress;
|
|
pIDataChannel->m_usNewSourcePort = usNewSourcePort;
|
|
pIDataChannel->m_ulNewDestinationAddress = ulNewDestinationAddress;
|
|
pIDataChannel->m_usNewDestinationPort = usNewDestinationPort;
|
|
pIDataChannel->m_ulRestrictAdapterIndex = ulRestrictAdapterIndex;
|
|
|
|
pIDataChannel->m_hCreateEvent = (HANDLE)hCreateEvent;
|
|
pIDataChannel->m_hDeleteEvent = (HANDLE)hDeleteEvent;
|
|
|
|
hr = pIDataChannel->QueryInterface(ppDataChannel);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE_ERROR("QI on IDataChannel", hr);
|
|
}
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::CreatePersistentDataChannel(
|
|
IN ALG_PROTOCOL eProtocol,
|
|
IN ULONG ulPrivateAddress,
|
|
IN USHORT usPrivatePort,
|
|
IN ULONG ulPublicAddress,
|
|
IN USHORT usPublicPort,
|
|
IN ULONG ulRemoteAddress,
|
|
IN USHORT usRemotePort,
|
|
IN ALG_DIRECTION eDirection,
|
|
OUT IPersistentDataChannel** ppIPersistentDataChannel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
eProtocol,
|
|
ulPrivateAddress,
|
|
usPrivatePort,
|
|
ulPublicAddress,
|
|
usPublicPort,
|
|
ulRemoteAddress,
|
|
usRemotePort,
|
|
eDirection,
|
|
ppIPersistentDataChannel
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::CreatePersistentDataChannel");
|
|
|
|
if ( !ppIPersistentDataChannel )
|
|
{
|
|
MYTRACE_ERROR("IPersistentDataChannel** not supplied",0);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
ULONG ulFlags=0;
|
|
|
|
ULONG ulSourceAddress=0;
|
|
USHORT usSourcePort=0;
|
|
ULONG ulDestinationAddress=0;
|
|
USHORT usDestinationPort=0;
|
|
ULONG ulNewSourceAddress=0;
|
|
USHORT usNewSourcePort=0;
|
|
ULONG ulNewDestinationAddress=0;
|
|
USHORT usNewDestinationPort=0;
|
|
|
|
ULONG ulRestrictAdapterIndex=0;
|
|
|
|
|
|
HRESULT hr = GetRedirectParameters(
|
|
// IN Params
|
|
eDirection,
|
|
eProtocol,
|
|
ulPrivateAddress,
|
|
usPrivatePort,
|
|
ulPublicAddress,
|
|
usPublicPort,
|
|
ulRemoteAddress,
|
|
usRemotePort,
|
|
|
|
// OUT Params
|
|
ulFlags,
|
|
ulSourceAddress,
|
|
usSourcePort,
|
|
ulDestinationAddress,
|
|
usDestinationPort,
|
|
ulNewSourceAddress,
|
|
usNewSourcePort,
|
|
ulNewDestinationAddress,
|
|
usNewDestinationPort,
|
|
ulRestrictAdapterIndex
|
|
);
|
|
|
|
if ( FAILED(hr) )
|
|
return hr;
|
|
|
|
|
|
//
|
|
// Create a IDataChannel and cache arg so to CancelRedirect
|
|
//
|
|
|
|
HANDLE_PTR HandleDynamicRedirect=NULL;
|
|
|
|
// Dynamic
|
|
hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
|
|
ulFlags,
|
|
0, // Adapter Index
|
|
(UCHAR)eProtocol,
|
|
|
|
ulDestinationAddress, // ULONG DestinationAddress
|
|
usDestinationPort, // USHORT DestinationPort
|
|
|
|
ulSourceAddress, // ULONG SourceAddress
|
|
usSourcePort, // USHORT SourcePort
|
|
|
|
ulNewDestinationAddress, // ULONG NewDestinationAddress
|
|
usNewDestinationPort, // USHORT NewDestinationPort
|
|
|
|
ulNewSourceAddress, // ULONG NewSourceAddress
|
|
usNewSourcePort, // USHORT NewSourcePort
|
|
|
|
&HandleDynamicRedirect
|
|
);
|
|
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
|
|
CComObject<CPersistentDataChannel>* pIPersistentDataChannel;
|
|
CComObject<CPersistentDataChannel>::CreateInstance(&pIPersistentDataChannel);
|
|
|
|
|
|
//
|
|
// Save these settings so to be able to return them to the user
|
|
// if the IDataChannel->GetProperties is called
|
|
//
|
|
pIPersistentDataChannel->m_Properties.eProtocol = eProtocol;
|
|
pIPersistentDataChannel->m_Properties.ulPrivateAddress = ulPrivateAddress;
|
|
pIPersistentDataChannel->m_Properties.usPrivatePort = usPrivatePort;
|
|
pIPersistentDataChannel->m_Properties.ulPublicAddress = ulPublicAddress;
|
|
pIPersistentDataChannel->m_Properties.usPublicPort = usPublicPort;
|
|
pIPersistentDataChannel->m_Properties.ulRemoteAddress = ulRemoteAddress;
|
|
pIPersistentDataChannel->m_Properties.usRemotePort = usRemotePort;
|
|
pIPersistentDataChannel->m_Properties.eDirection = eDirection;
|
|
|
|
|
|
|
|
//
|
|
// Cache these hanlde in order to implement IPersistentDataChannel->Cancel
|
|
//
|
|
pIPersistentDataChannel->m_HandleDynamicRedirect = HandleDynamicRedirect;
|
|
|
|
|
|
hr = pIPersistentDataChannel->QueryInterface(ppIPersistentDataChannel);
|
|
|
|
}
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::ReservePort(
|
|
IN USHORT usPortCount, // must be 1 or more and not more then ALG_MAXIMUM_PORT_RANGE_SIZE
|
|
OUT USHORT* pusReservedPort // Received the base reserved port *pusReservedPort+usPortCount-1 are reserved for the caller
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reserve a number of port (usPortCount) port(s)
|
|
|
|
Arguments:
|
|
|
|
usPortCount - greated then 1 and not more then ALG_MAXIMUM_PORT_RANGE_SIZE
|
|
pusReservedPort - Received the base reserved port *pusReservedPort+usPortCount-1 are reserved for the caller
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::ReservePort")
|
|
|
|
if ( usPortCount < 0 || usPortCount > ALG_MAXIMUM_PORT_RANGE_SIZE )
|
|
return E_INVALIDARG;
|
|
|
|
_ASSERT(pusReservedPort);
|
|
|
|
HRESULT hr = g_pAlgController->GetNat()->ReservePort(usPortCount, pusReservedPort);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
MYTRACE("Reserving Ports", hr);
|
|
}
|
|
else
|
|
{
|
|
MYTRACE("%d port stating at %d", usPortCount, ntohs(*pusReservedPort) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
VOID CALLBACK
|
|
CApplicationGatewayServices::TimerCallbackReleasePort(
|
|
PVOID pParameter, // thread data
|
|
BOOLEAN TimerOrWaitFired // reason
|
|
)
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::TimerCallbackReleasePort");
|
|
|
|
CTimerQueueReleasePort* pTimerQueueReleasePort = (CTimerQueueReleasePort*)pParameter;
|
|
|
|
if ( pTimerQueueReleasePort )
|
|
{
|
|
MYTRACE("Releasing port Base %d count %d", ntohs(pTimerQueueReleasePort->m_usPortBase), pTimerQueueReleasePort->m_usPortCount);
|
|
g_pAlgController->GetNat()->ReleasePort(pTimerQueueReleasePort->m_usPortBase, pTimerQueueReleasePort->m_usPortCount);
|
|
|
|
delete pTimerQueueReleasePort;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::ReleaseReservedPort(
|
|
IN USHORT usPortBase, // Port to release
|
|
IN USHORT usPortCount // Number of port in the range starting at usPortBase
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Release the given port(s)
|
|
|
|
Arguments:
|
|
|
|
pusReservedPort - The starting base port number
|
|
usPortCount - greated then 1 and not more then ALG_MAXIMUM_PORT_RANGE_SIZE
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
- E_FAIL could no release the port
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::ReleaseReservedPort")
|
|
|
|
MYTRACE("BasePort %d, Count %d", ntohs(usPortBase), usPortCount);
|
|
|
|
//
|
|
// By creating a CTimerQueueReleasePort it will trigger a ReleaseReservePort after 4 minutes
|
|
// we need this delay to insure that a ReserverPort does not get the same port that just go Released
|
|
// because the connnection would not work (This is a TCP/IP TIME_WAIT restriction)
|
|
//
|
|
CTimerQueueReleasePort* pTimerReleasePort = new CTimerQueueReleasePort(m_hTimerQueue, usPortBase, usPortCount);
|
|
|
|
if ( pTimerReleasePort )
|
|
return S_OK;
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::EnumerateAdapters(
|
|
OUT IEnumAdapterInfo** ppEnumAdapterInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a list of IEnumAdapterInfo
|
|
the AddRef will be done soe caller needs to call Release
|
|
|
|
Arguments:
|
|
|
|
ppEnumAdapterInfo - receive the enumarator interface of the IAdapterInfo
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::EnumerateAdapters")
|
|
|
|
_ASSERT(ppEnumAdapterInfo==NULL);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CreateSTLEnumerator<ComEnumOnSTL_ForAdapters>(
|
|
(IUnknown**)ppEnumAdapterInfo,
|
|
NULL,
|
|
g_pAlgController->m_CollectionOfAdapters.m_ListOfAdapters
|
|
);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::StartAdapterNotifications(
|
|
IN IAdapterNotificationSink* pSink,
|
|
OUT DWORD* pdwCookie
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The ALG module calls this method to Register a notification sync with the ALG.exe
|
|
|
|
Arguments:
|
|
|
|
pSink - Interface to call back with future notification
|
|
pdwCookie - this cookie will be used to cancel this sink
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::StartAdapterNotifications")
|
|
|
|
if ( pSink==NULL || pdwCookie==NULL )
|
|
{
|
|
MYTRACE("Invalid argument pass");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
return g_pAlgController->m_AdapterNotificationSinks.Add(pSink, pdwCookie);
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CApplicationGatewayServices::StopAdapterNotifications(
|
|
IN DWORD dwCookieToRemove
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cancel a previously registered sink
|
|
|
|
Arguments:
|
|
|
|
|
|
pdwCookieToRemove - Pass the cookie that was return from the StartAdapterNotifications
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT - S_OK for success
|
|
|
|
Environment:
|
|
|
|
ALG module will call this method to:
|
|
|
|
--*/
|
|
{
|
|
MYTRACE_ENTER("CApplicationGatewayServices::StopAdapterNotifications")
|
|
|
|
return g_pAlgController->m_AdapterNotificationSinks.Remove(dwCookieToRemove);
|
|
}
|