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

527 lines
15 KiB

/*++
Copyright (c) 2000, Microsoft Corporation
Module Name:
PrimaryControlChannel.cpp.cpp
Abstract:
Control channel a created to control the life time of a newly created DynamicRedirection
Author:
JP Duplessis (jpdup) 08-Dec-2000
Revision History:
--*/
#include "PreComp.h"
#include "PrimaryControlChannel.h"
#include "AlgController.h"
/////////////////////////////////////////////////////////////////////////////
//
// CPrimaryControlChannel
//
//
// Cancel the control channel. Cleans up by Reversing the Redirection
//
STDMETHODIMP CPrimaryControlChannel::Cancel()
{
MYTRACE_ENTER("STDMETHODIMP CPrimaryControlChannel::Cancel()");
//
// No longer valid so no need to keep track of this Channel
//
g_pAlgController->m_ControlChannelsPrimary.Remove(this);
return S_OK;
}
//
//
//
STDMETHODIMP
CPrimaryControlChannel::GetChannelProperties(
OUT ALG_PRIMARY_CHANNEL_PROPERTIES** ppProperties
)
{
HRESULT hr = S_OK;
if (NULL != ppProperties)
{
*ppProperties = reinterpret_cast<ALG_PRIMARY_CHANNEL_PROPERTIES*>(
CoTaskMemAlloc(sizeof(ALG_PRIMARY_CHANNEL_PROPERTIES))
);
if (NULL != *ppProperties)
{
CopyMemory(*ppProperties, &m_Properties, sizeof(ALG_PRIMARY_CHANNEL_PROPERTIES));
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_POINTER;
}
return hr;
}
//
// Small helper class to get the IP address of an adapter
// and release the memory allocated on the destructor
//
class CAdapterAddresses
{
public:
LRESULT m_hResultLastState;
IAdapterInfo* m_pIAdapter;
ULONG m_ulAddressCount;
ULONG* m_arAddresses;
CAdapterAddresses(
ULONG nIndexOfAdapter
)
{
MYTRACE_ENTER_NOSHOWEXIT("CAdapterAddresses:NEW");
m_pIAdapter = NULL;
m_ulAddressCount = 0;
m_hResultLastState = g_pAlgController->m_CollectionOfAdapters.GetAdapterInfo(
nIndexOfAdapter,
&m_pIAdapter
);
if ( SUCCEEDED(m_hResultLastState) )
{
m_arAddresses = NULL;
m_hResultLastState = m_pIAdapter->GetAdapterAddresses(
&m_ulAddressCount,
&m_arAddresses
);
if ( FAILED(m_hResultLastState) )
{
MYTRACE_ERROR("Could not get the address", m_hResultLastState);
}
}
else
{
MYTRACE_ERROR("On GetAdapterInfo", m_hResultLastState);
}
}
~CAdapterAddresses()
{
MYTRACE_ENTER_NOSHOWEXIT("CAdapterAddresses:DELETE");
if ( m_pIAdapter )
{
m_pIAdapter->Release();
if ( m_arAddresses )
CoTaskMemFree(m_arAddresses);
}
}
bool
FindAddress(
ULONG ulAddressToFind
)
{
int nAddress = (int)m_ulAddressCount;
//
// Is the original address on the edgebox adapter
//
while ( --nAddress >= 0 )
{
if ( m_arAddresses[nAddress] == ulAddressToFind )
return true;
}
return false;
}
};
//
//
//
STDMETHODIMP
CPrimaryControlChannel::GetOriginalDestinationInformation(
IN ULONG ulSourceAddress,
IN USHORT usSourcePort,
OUT ULONG* pulOriginalDestinationAddress,
OUT USHORT* pusOriginalDestinationPort,
OUT IAdapterInfo** ppReceiveAdapter
)
{
MYTRACE_ENTER("CPrimaryControlChannel::GetOriginalDestinationInformation");
MYTRACE("Source %s:%d", MYTRACE_IP(ulSourceAddress), ntohs(usSourcePort));
if ( !ppReceiveAdapter )
{
MYTRACE_ERROR("Invalid Arg no Pointer supplied for the AdapterInfo", E_INVALIDARG);
return E_INVALIDARG;
}
ULONG nAdapterIndex;
HRESULT hr = g_pAlgController->GetNat()->GetOriginalDestinationInformation(
m_Properties.eProtocol,
m_Properties.ulListeningAddress, // ULONG DestinationAddress,
m_Properties.usListeningPort, // USHORT DestinationPort,
ulSourceAddress,
usSourcePort,
pulOriginalDestinationAddress,
pusOriginalDestinationPort,
&nAdapterIndex
);
if ( FAILED(hr) )
{
MYTRACE_ERROR("Could not GetNat()->GetOriginalDestinationInformation", hr);
return hr;
}
MYTRACE("Original destination is %s:%d", MYTRACE_IP(*pulOriginalDestinationAddress), ntohs(*pusOriginalDestinationPort));
//
// Get the AdapterInfo interface object and list of IP Address
//
CAdapterAddresses Adapter(nAdapterIndex);
if ( FAILED(Adapter.m_hResultLastState) )
{
MYTRACE_ERROR("On GetAdapterInfo", hr);
return Adapter.m_hResultLastState;
}
if ( Adapter.m_ulAddressCount==0 )
{
//
// We have a problem there is no IP address on this adapter
//
MYTRACE_ERROR("No address on adapter %d", nAdapterIndex);
return E_FAIL;
}
//
// Return the AdapterInfo to the caller
//
Adapter.m_pIAdapter->AddRef(); // The destructor of CAdapterAddress does a release on this interface so we need to pump it up by one
*ppReceiveAdapter = Adapter.m_pIAdapter;
bool bOriginalAddressIsOnTheEdgeAdapters = Adapter.FindAddress(*pulOriginalDestinationAddress);
//
// if pulOriginalDestinationAddress match one of the adapter on the edge box
// then lookup for a remap port
//
if ( bOriginalAddressIsOnTheEdgeAdapters )
{
//
// This may be an inbound
//
ULONG nRemapAddress;
USHORT nRemapPort;
HRESULT hr = g_pAlgController->GetNat()->LookupAdapterPortMapping(
nAdapterIndex,
m_Properties.eProtocol,
*pulOriginalDestinationAddress,
*pusOriginalDestinationPort,
&nRemapAddress,
&nRemapPort
);
if ( SUCCEEDED(hr) )
{
//
// Theres a remap address/Port
//
*pulOriginalDestinationAddress = nRemapAddress;
*pusOriginalDestinationPort = nRemapPort;
MYTRACE("Remap destination to %s:%d", MYTRACE_IP(*pulOriginalDestinationAddress), ntohs(*pusOriginalDestinationPort));
}
else
{
//
// This is just a soft error meaning no mapping where found we can still continue
//
MYTRACE("LookupAdapterPortMapping did not find a port maping %x", hr);
}
}
return hr;
}
//
// Need to remove any redirect that was set for this Adapter
//
HRESULT
CPrimaryControlChannel::CancelRedirectsForAdapter(
ULONG nAdapterIndex
)
{
return m_CollectionRedirects.RemoveForAdapter(nAdapterIndex);
}
//
//
//
HRESULT
CPrimaryControlChannel::SetRedirect(
ALG_ADAPTER_TYPE eAdapterType,
ULONG nAdapterIndex,
ULONG nAdapterAddress
)
{
MYTRACE_ENTER("CPrimaryControlChannel::SetRedirect");
HANDLE_PTR hCookie;
HRESULT hr=S_OK;
ULONG nFlags=NatRedirectFlagPortRedirect|NatRedirectFlagRestrictAdapter;
ULONG nProtocol=0;
ULONG nDestinationAddress=0;
USHORT nDestinationPort=0;
ULONG nSourceAddress=0;
USHORT nSourcePort=0;
//
// What type of port is supplied
//
if ( m_Properties.eCaptureType == eALG_DESTINATION_CAPTURE )
{
MYTRACE("CAPTURE TYPE is eALG_DESTINATION_CAPTURE");
nDestinationPort = m_Properties.usCapturePort;
}
if ( m_Properties.eCaptureType == eALG_SOURCE_CAPTURE )
{
MYTRACE("CAPTURE TYPE is eALG_SOURCE_CAPTURE");
nFlags |= NatRedirectFlagSourceRedirect;
nSourcePort = m_Properties.usCapturePort;
}
//
// ADAPTER IS FIREWALL or SHARED
//
if ( (eAdapterType & eALG_FIREWALLED) || (eAdapterType & eALG_BOUNDARY) )
{
nFlags |= NatRedirectFlagSendOnly;
MYTRACE("ADAPTER TYPE is %s %s",
eAdapterType & eALG_FIREWALLED ? "FIREWALLED" : "",
eAdapterType & eALG_BOUNDARY ? "SHARED" : ""
);
MYTRACE("Destination %s:%d", MYTRACE_IP(nDestinationAddress), ntohs(nDestinationPort));
MYTRACE("Source %s:%d", MYTRACE_IP(nSourceAddress), ntohs(nSourcePort));
MYTRACE("NewDestination %s:%d", MYTRACE_IP(m_Properties.ulListeningAddress), ntohs(m_Properties.usListeningPort));
//
// INBOUND Additional Redirect needed
//
if ( m_Properties.fCaptureInbound == TRUE)
{
MYTRACE("INBOUND requested - Lookup Remap port service to see if we should allow it");
//
// Create an additional Redirect for inbound from the Public side to the ICS box
//
//
// before we allow the redirection
// See if a maping was set by the user ("under the SERVICE Tab of ICS")
//
ULONG nRemapAddress;
USHORT nRemapPort;
hr = g_pAlgController->GetNat()->LookupAdapterPortMapping(
nAdapterIndex,
m_Properties.eProtocol,
nDestinationAddress,
nDestinationPort,
&nRemapAddress,
&nRemapPort
);
if ( SUCCEEDED(hr) )
{
MYTRACE("RemapAddress is %s:%d", MYTRACE_IP(nRemapAddress), ntohs(nRemapPort));
hr = CreateInboundRedirect(nAdapterIndex);
}
else
{
MYTRACE_ERROR("LookupPortMappingAdapter Failed", hr);
}
}
}
else
{
//
// ADAPTER IS PRIVATE
//
if ( eAdapterType & eALG_PRIVATE )
{
MYTRACE("ADAPTER TYPE is PRIVATE");
CAdapterAddresses PrivateAdapter(nAdapterIndex);
if ( PrivateAdapter.m_ulAddressCount > 0 )
{
MYTRACE("Create Shadow redirect between any private computers to private adapter %s", MYTRACE_IP(PrivateAdapter.m_arAddresses[0]) );
hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
NatRedirectFlagReceiveOnly,
nAdapterIndex,
(UCHAR) m_Properties.eProtocol,
PrivateAdapter.m_arAddresses[0], // ULONG DestinationAddress,
nDestinationPort, // USHORT DestinationPort,
0, // ULONG SourceAddress,
0, // USHORT SourcePort,
PrivateAdapter.m_arAddresses[0], // ULONG NewDestinationAddress
nDestinationPort, // USHORT NewDestinationPort
0, // ULONG NewSourceAddress,
0, // USHORT NewSourcePort,
&hCookie
);
}
if ( SUCCEEDED(hr) )
{
hr = m_CollectionRedirects.Add(hCookie, nAdapterIndex, FALSE); // Cache the Dynamic redirect Handle
}
else
{
MYTRACE_ERROR("Failed to createDynamicRedirect PRIVATE", hr);
}
nFlags |= NatRedirectFlagReceiveOnly;
if ( m_Properties.eCaptureType == eALG_SOURCE_CAPTURE )
{
nFlags |= NatRedirectFlagSourceRedirect;
}
}
}
MYTRACE("CreateDynamicRedirect for OUTBOUND");
hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
nFlags,
nAdapterIndex,
(UCHAR) m_Properties.eProtocol,
nDestinationAddress, // ULONG DestinationAddress,
nDestinationPort, // USHORT DestinationPort,
nSourceAddress, // ULONG SourceAddress,
nSourcePort, // USHORT SourcePort,
m_Properties.ulListeningAddress, // ULONG NewDestinationAddress
m_Properties.usListeningPort, // USHORT NewDestinationPort
0, // ULONG NewSourceAddress,
0, // USHORT NewSourcePort,
&hCookie
);
if ( SUCCEEDED(hr) )
{
hr = m_CollectionRedirects.Add(hCookie, nAdapterIndex, FALSE); // Cache the Dynamic redirect Handle
}
else
{
MYTRACE_ERROR("Failed to createDynamicRedirect PRIVATE", hr);
}
return hr;
}
HRESULT
CPrimaryControlChannel::CreateInboundRedirect(
ULONG nAdapterIndex
)
{
HRESULT hr;
HANDLE_PTR hCookie;
MYTRACE_ENTER("CPrimaryControlChannel::SetRedirect");
hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
NatRedirectFlagPortRedirect|NatRedirectFlagReceiveOnly|NatRedirectFlagRestrictAdapter,
nAdapterIndex,
(UCHAR)m_Properties.eProtocol,
0, // ULONG DestinationAddress,
m_Properties.usCapturePort, // USHORT DestinationPort,
0, // ULONG SourceAddress,
0, // USHORT SourcePort,
m_Properties.ulListeningAddress, // ULONG NewDestinationAddress
m_Properties.usListeningPort, // USHORT NewDestinationPort
0, // ULONG NewSourceAddress,
0, // USHORT NewSourcePort,
&hCookie
);
if ( SUCCEEDED(hr) )
{
hr = m_CollectionRedirects.Add(hCookie, nAdapterIndex, TRUE); // Cache the Dynamic redirect Handle
}
else
{
MYTRACE_ERROR("Failed to CreateDynamicRedirect INBOUND", hr);
}
return hr;
}