windows-nt/Source/XPSP1/NT/net/rras/ip/nath323/intfc.cpp
2020-09-26 16:20:57 +08:00

1587 lines
31 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
intfc.h
Abstract:
Definitions of data types and corresponding methods used to provide
multiple-interface support in H.323/LDAP proxy.
Revision History:
03/01/2000 File creation. Ilya Kleyman (IlyaK)
--*/
///////////////////////////////////////////////////////////////////////////////
// //
// Include files //
// //
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
///////////////////////////////////////////////////////////////////////////////
// //
// Global Variables //
// //
///////////////////////////////////////////////////////////////////////////////
PROXY_INTERFACE_ARRAY InterfaceArray;
///////////////////////////////////////////////////////////////////////////////
// //
// Static definitions //
// //
///////////////////////////////////////////////////////////////////////////////
static
int
__cdecl
CompareInterfacesByIndex (
IN PROXY_INTERFACE * const * InterfaceA,
IN PROXY_INTERFACE * const * InterfaceB
);
static
INT
SearchInterfaceByIndex (
IN const DWORD * Index,
IN PROXY_INTERFACE *const* Comparand
);
///////////////////////////////////////////////////////////////////////////////
// //
// Definitions //
// //
///////////////////////////////////////////////////////////////////////////////
// PROXY_INTERFACE ------------------------------------------------------------
PROXY_INTERFACE::PROXY_INTERFACE (
IN ULONG ArgIndex,
IN H323_INTERFACE_TYPE ArgInterfaceType,
IN PIP_ADAPTER_BINDING_INFO BindingInfo
)
/*++
Routine Description:
Constructor for PROXY_INTERFACE class
Arguments:
ArgIndex - Index of the interface
ArgInterfaceType - Interface type (public or private)
BindingInfo - Binding information for the interface
Return Values:
None
Notes:
--*/
{
Address = ntohl (BindingInfo -> Address[0].Address);
Mask = ntohl (BindingInfo -> Address[0].Mask);
Index = ArgIndex;
InterfaceType = ArgInterfaceType;
AdapterIndex = 0;
Q931RedirectHandle = NULL;
LdapRedirectHandle1 = NULL;
LdapRedirectHandle2 = NULL;
Q931LocalRedirectHandle = NULL;
LdapLocalRedirectHandle1 = NULL;
LdapLocalRedirectHandle2 = NULL;
::ZeroMemory (&Q931PortMapping, sizeof (Q931PortMapping));
::ZeroMemory (&LdapPortMapping, sizeof (LdapPortMapping));
::ZeroMemory (&LdapAltPortMapping, sizeof (LdapAltPortMapping));
} // PROXY_INTERFACE::PROXY_INTERFACE
PROXY_INTERFACE::~PROXY_INTERFACE (
void
)
/*++
Routine Description:
Destructor for PROXY_INTERFACE class
Arguments:
None
Return Values:
None
Notes:
--*/
{
assert (!Q931RedirectHandle);
assert (!LdapRedirectHandle1);
assert (!LdapRedirectHandle2);
assert (!Q931LocalRedirectHandle);
assert (!LdapLocalRedirectHandle1);
assert (!LdapLocalRedirectHandle2);
} // PROXY_INTERFACE::~PROXY_INTERFACE
ULONG
PROXY_INTERFACE::StartNatRedirects (
void
)
/*++
Routine Description:
Creates two types of adapter-restricted NAT redirects:
Type 1 -- for connections incoming on the interface
Type 2 -- for locally-originated connections (NOT destined to
the local machine) through the interface
Arguments:
None
Return Values:
Win32 error indicating what (if anything) went wrong
when trying to set up the NAT redirects.
Notes:
Total number of redirects created is 6:
2 Type 1 redirects for LDAP
2 Type 2 redirects for LDAP
1 Type 1 redirect for Q.931
1 Type 2 redirect for Q.931
--*/
{
ULONG Status;
assert (!Q931RedirectHandle);
assert (!LdapRedirectHandle1);
assert (!LdapRedirectHandle2);
assert (!Q931LocalRedirectHandle);
assert (!LdapLocalRedirectHandle1);
assert (!LdapLocalRedirectHandle2);
// Type 1 redirects -- for redirecting inbound connections
if (!IsFirewalled () || HasQ931PortMapping ())
{
Status = StartQ931ReceiveRedirect ();
}
if (!IsFirewalled () || HasLdapPortMapping ())
{
Status = NatCreateDynamicAdapterRestrictedPortRedirect (
0,
IPPROTO_TCP,
htons (LDAP_STANDARD_PORT),
LdapListenSocketAddress.sin_addr.s_addr,
LdapListenSocketAddress.sin_port,
AdapterIndex,
MAX_LISTEN_BACKLOG,
&LdapRedirectHandle1
);
if (Status != STATUS_SUCCESS)
{
DebugError (Status, _T("LDAP: Failed to create receive redirect #1 for LDAP.\n"));
return Status;
}
DebugF (_T ("LDAP: Incoming connections to %08X:%04X will be redirected to %08X:%04X.\n"),
Address,
LDAP_STANDARD_PORT,
ntohl (LdapListenSocketAddress.sin_addr.s_addr),
ntohs (LdapListenSocketAddress.sin_port));
}
if (!IsFirewalled () || HasLdapAltPortMapping ())
{
Status = NatCreateDynamicAdapterRestrictedPortRedirect (
0,
IPPROTO_TCP,
htons (LDAP_ALTERNATE_PORT),
LdapListenSocketAddress.sin_addr.s_addr,
LdapListenSocketAddress.sin_port,
AdapterIndex,
MAX_LISTEN_BACKLOG,
&LdapRedirectHandle2
);
if (Status != STATUS_SUCCESS)
{
DebugError (Status, _T("LDAP: Failed to create receive redirect #2 for LDAP.\n"));
return Status;
}
DebugF (_T ("LDAP: Incoming connections to %08X:%04X will be redirected to %08X:%04X.\n"),
Address,
LDAP_ALTERNATE_PORT,
ntohl (LdapListenSocketAddress.sin_addr.s_addr),
ntohs (LdapListenSocketAddress.sin_port));
}
// Type 2 redirects (for locally-originated traffic, NOT destined to the local machine)
Status = NatCreateDynamicAdapterRestrictedPortRedirect (
NatRedirectFlagSendOnly,
IPPROTO_TCP,
htons (Q931_TSAP_IP_TCP),
Q931ListenSocketAddress.sin_addr.s_addr,
Q931ListenSocketAddress.sin_port,
AdapterIndex,
MAX_LISTEN_BACKLOG,
&Q931LocalRedirectHandle
);
if (Status != STATUS_SUCCESS)
{
DebugError (Status, _T("Q931: Failed to create send redirect for Q.931.\n"));
return Status;
}
DebugF (_T ("Q931: Locally-originated connections through %08X:%04X will be redirected to %08X:%04X.\n"),
Address,
Q931_TSAP_IP_TCP,
ntohl (Q931ListenSocketAddress.sin_addr.s_addr),
ntohs (Q931ListenSocketAddress.sin_port));
Status = NatCreateDynamicAdapterRestrictedPortRedirect (
NatRedirectFlagSendOnly,
IPPROTO_TCP,
htons (LDAP_STANDARD_PORT),
LdapListenSocketAddress.sin_addr.s_addr,
LdapListenSocketAddress.sin_port,
AdapterIndex,
MAX_LISTEN_BACKLOG,
&LdapLocalRedirectHandle1
);
if (Status != STATUS_SUCCESS)
{
DebugError (Status, _T("LDAP: Failed to create send redirect #1 for LDAP.\n"));
return Status;
}
DebugF (_T ("LDAP: Locally-originated connections through %08X:%04X will be redirected to %08X:%04X.\n"),
Address,
LDAP_STANDARD_PORT,
ntohl (LdapListenSocketAddress.sin_addr.s_addr),
ntohs (LdapListenSocketAddress.sin_port));
Status = NatCreateDynamicAdapterRestrictedPortRedirect (
NatRedirectFlagSendOnly,
IPPROTO_TCP,
htons (LDAP_ALTERNATE_PORT),
LdapListenSocketAddress.sin_addr.s_addr,
LdapListenSocketAddress.sin_port,
AdapterIndex,
MAX_LISTEN_BACKLOG,
&LdapLocalRedirectHandle2
);
if (Status != STATUS_SUCCESS)
{
DebugError (Status, _T("LDAP: Failed to create send redirect #2 for LDAP.\n"));
return Status;
}
DebugF (_T ("LDAP: Locally-originated connections through %08X:%04X will be redirected to %08X:%04X.\n"),
Address,
LDAP_ALTERNATE_PORT,
ntohl (LdapListenSocketAddress.sin_addr.s_addr),
ntohs (LdapListenSocketAddress.sin_port));
return Status;
} // PROXY_INTERFACE::StartNatRedirects
ULONG
PROXY_INTERFACE::Start (
void
)
/*++
Routine Description:
Starts an interface
Arguments:
None
Return Values:
Win32 error indicating what (if anything) went wrong when
the interface was being started.
Notes:
--*/
{
ULONG Status;
assert (0 == AdapterIndex);
assert (0 == Q931PortMapping.PrivateAddress);
assert (0 == LdapPortMapping.PrivateAddress);
assert (0 == LdapAltPortMapping.PrivateAddress);
AdapterIndex = ::NhMapAddressToAdapter (htonl (Address));
if (INVALID_INTERFACE_INDEX == AdapterIndex)
{
AdapterIndex = 0;
Status = ERROR_CAN_NOT_COMPLETE;
DebugF (_T ("PROXY_INTERFACE: Unable to map %08X to an adapter index\n"),
Address);
return Status;
}
//
// Load the port mappings for this interface. Since more often than not
// there won't be a port mapping, we expect these routines to return
// errors, and thus don't check for them. NatLookupPortMappingAdapter
// will modify the out parameter (i.e., the port mapping structure) only
// on success.
//
::NatLookupPortMappingAdapter (
AdapterIndex,
NAT_PROTOCOL_TCP,
IP_NAT_ADDRESS_UNSPECIFIED,
htons (Q931_TSAP_IP_TCP),
&Q931PortMapping
);
::NatLookupPortMappingAdapter (
AdapterIndex,
NAT_PROTOCOL_TCP,
IP_NAT_ADDRESS_UNSPECIFIED,
htons (LDAP_STANDARD_PORT),
&LdapPortMapping
);
::NatLookupPortMappingAdapter (
AdapterIndex,
NAT_PROTOCOL_TCP,
IP_NAT_ADDRESS_UNSPECIFIED,
htons (LDAP_ALTERNATE_PORT),
&LdapAltPortMapping
);
Status = StartNatRedirects ();
if (STATUS_SUCCESS != Status)
{
StopNatRedirects ();
}
return Status;
} // PROXY_INTERFACE::Start
void
PROXY_INTERFACE::StopNatRedirects (
void
)
/*++
Routine Description:
Removes all NAT redirects created for the interface
Arguments:
None
Return Values:
None
Notes:
--*/
{
if (Q931RedirectHandle)
{
NatCancelDynamicRedirect (Q931RedirectHandle);
Q931RedirectHandle = NULL;
}
if (LdapRedirectHandle1)
{
NatCancelDynamicRedirect (LdapRedirectHandle1);
LdapRedirectHandle1 = NULL;
}
if (LdapRedirectHandle2)
{
NatCancelDynamicRedirect (LdapRedirectHandle2);
LdapRedirectHandle2 = NULL;
}
if (Q931LocalRedirectHandle)
{
NatCancelDynamicRedirect (Q931LocalRedirectHandle);
Q931LocalRedirectHandle = NULL;
}
if (LdapLocalRedirectHandle1)
{
NatCancelDynamicRedirect (LdapLocalRedirectHandle1);
LdapLocalRedirectHandle1 = NULL;
}
if (LdapLocalRedirectHandle2)
{
NatCancelDynamicRedirect (LdapLocalRedirectHandle2);
LdapLocalRedirectHandle2 = NULL;
}
} // PROXY_INTERFACE::StopNatRedirects
ULONG
PROXY_INTERFACE::StartQ931ReceiveRedirect (
void
)
/*++
Routine Description:
Creates the type 1 (receive) redirect for Q931 traffic,
if this has not already been done on the interface.
Arguments:
None
Return Values:
Win32 error indicating what (if anything) went wrong
when trying to set up the redirect.
--*/
{
ULONG Status = STATUS_SUCCESS;
if (NULL == Q931RedirectHandle)
{
Status = NatCreateDynamicAdapterRestrictedPortRedirect (
0,
IPPROTO_TCP,
htons (Q931_TSAP_IP_TCP),
Q931ListenSocketAddress.sin_addr.s_addr,
Q931ListenSocketAddress.sin_port,
AdapterIndex,
MAX_LISTEN_BACKLOG,
&Q931RedirectHandle
);
if (Status != STATUS_SUCCESS)
{
DebugError (Status, _T("Q931: Failed to create receive redirect for Q.931.\n"));
return Status;
}
DebugF (_T ("Q931: Incoming connections to %08X:%04X will be redirected to %08X:%04X.\n"),
Address,
Q931_TSAP_IP_TCP,
ntohl (Q931ListenSocketAddress.sin_addr.s_addr),
ntohs (Q931ListenSocketAddress.sin_port));
}
return Status;
} // PROXY_INTERFACE::StartQ931ReceiveRedirect
void
PROXY_INTERFACE::StopQ931ReceiveRedirect (
void
)
/*++
Routine Description:
Stops the Q931 receive redirect, if it has been created.
Arguments:
None
Return Values:
None
--*/
{
if (Q931RedirectHandle)
{
NatCancelDynamicRedirect (Q931RedirectHandle);
Q931RedirectHandle = NULL;
}
} // PROXY_INTERFACE::StopQ931ReceiveRedirect
void
PROXY_INTERFACE::Stop (
void
)
/*++
Routine Description:
1. Terminate all connections through the interface.
2. Remove all translation entries registered via the interface.
3. Stop all NAT redirects created for this interface.
Arguments:
None
Return Values:
None
Notes:
The caller of this method should first remove the
interface from the global array.
--*/
{
CallBridgeList.OnInterfaceShutdown (Address);
LdapConnectionArray.OnInterfaceShutdown (Address);
LdapTranslationTable.OnInterfaceShutdown (Address);
StopNatRedirects ();
::ZeroMemory (&Q931PortMapping, sizeof (Q931PortMapping));
::ZeroMemory (&LdapPortMapping, sizeof (LdapPortMapping));
::ZeroMemory (&LdapAltPortMapping, sizeof (LdapAltPortMapping));
AdapterIndex = 0;
} // PROXY_INTERFACE::Stop
BOOL
PROXY_INTERFACE::IsFirewalled (
void
)
/*++
Routine Description:
Determines whether the interface was created as firewalled.
Arguments:
None
Return Values:
TRUE - if the interface was created as firewalled.
FALSE - if the interface was created as non-firewalled.
Notes:
--*/
{
return InterfaceType == H323_INTERFACE_PUBLIC_FIREWALLED;
} // PROXY_INTERFACE::IsFirewalled
BOOL
PROXY_INTERFACE::IsPrivate (
void
)
/*++
Routine Description:
Determines whether the interface was created as private.
Arguments:
None
Return Values:
TRUE if the interface was created as private
FALSE if the interface was created as non-private
Notes:
--*/
{
return InterfaceType == H323_INTERFACE_PRIVATE;
} // PROXY_INTERFACE::IsPrivate
BOOL
PROXY_INTERFACE::IsPublic (
void
)
/*++
Routine Description:
Determines whether the interface was created as public.
Arguments:
None
Return Values:
TRUE - if the interface was created as public.
FALSE - if the interface was created as non-public.
Notes:
--*/
{
return InterfaceType == H323_INTERFACE_PUBLIC
|| InterfaceType == H323_INTERFACE_PUBLIC_FIREWALLED;
} // PROXY_INTERFACE::IsPublic
BOOL
PROXY_INTERFACE::HasQ931PortMapping (
void
)
/*++
Routine Description:
Determines whether the interface has a valid Q931 port mapping.
Arguments:
None
Return Values:
TRUE if the interface has a valid Q931 port mapping
FALSE if the interface does not have a valid Q931 port mapping
Notes:
--*/
{
return Q931PortMapping.PrivateAddress != 0;
} // PROXY_INTERFACE::HasQ931PortMapping
BOOL
PROXY_INTERFACE::HasLdapPortMapping (
void
)
/*++
Routine Description:
Determines whether the interface has a valid Ldap port mapping.
Arguments:
None
Return Values:
TRUE if the interface has a valid Ldap port mapping
FALSE if the interface does not have a valid Ldap port mapping
Notes:
--*/
{
return LdapPortMapping.PrivateAddress != 0;
} // PROXY_INTERFACE::HasLdapPortMapping
BOOL
PROXY_INTERFACE::HasLdapAltPortMapping (
void
)
/*++
Routine Description:
Determines whether the interface has a valid Ldap (alt) port mapping.
Arguments:
None
Return Values:
TRUE if the interface has a valid Ldap (alt) port mapping
FALSE if the interface does not have a valid Ldap (alt) port mapping
Notes:
--*/
{
return LdapAltPortMapping.PrivateAddress != 0;
} // PROXY_INTERFACE::HasLdapAltPortMapping
ULONG
PROXY_INTERFACE::GetQ931PortMappingDestination (
void
)
/*++
Routine Description:
Returns the destination address of the interfaces
Q931 port mapping.
Arguments:
None
Return Values:
The destination address of the port mapping, in network
byte order. Returns 0 if no port mapping exists.
Notes:
--*/
{
return Q931PortMapping.PrivateAddress;
} // PROXY_INTERFACE::GetQ931PortMappingDestination
ULONG
PROXY_INTERFACE::GetLdapPortMappingDestination (
void
)
/*++
Routine Description:
Returns the destination address of the interfaces
Ldap port mapping.
Arguments:
None
Return Values:
The destination address of the port mapping, in network
byte order. Returns 0 if no port mapping exists.
Notes:
--*/
{
return LdapPortMapping.PrivateAddress;
} // PROXY_INTERFACE::GetLdapPortMappingDestination
ULONG
PROXY_INTERFACE::GetLdapAltPortMappingDestination (
void
)
/*++
Routine Description:
Returns the destination address of the interfaces
Ldap-alt port mapping.
Arguments:
None
Return Values:
The destination address of the port mapping, in network
byte order. Returns 0 if no port mapping exists.
Notes:
--*/
{
return LdapAltPortMapping.PrivateAddress;
} // PROXY_INTERFACE::GetLdapAltPortMappingDestination
// PROXY_INTERFACE_ARRAY ------------------------------------------------------
HRESULT
PROXY_INTERFACE_ARRAY::Add (
IN PROXY_INTERFACE* Interface
)
/*++
Routine Description:
Adds an interface to the array.
Arguments:
Interface - interface to be added.
Return Values:
Error code indicating whether the operation succeeded.
Notes:
To be called from locked context.
--*/
{
DWORD ReturnIndex;
PROXY_INTERFACE** ElementPlaceholder;
assert (Interface);
if (Array.FindIndex (CompareInterfacesByIndex, &Interface, &ReturnIndex))
{
// Interface with this index already exists
return E_FAIL;
}
ElementPlaceholder = Array.AllocAtPos (ReturnIndex);
if (!ElementPlaceholder)
return E_OUTOFMEMORY;
*ElementPlaceholder = Interface;
return S_OK;
} // PROXY_INTERFACE_ARRAY::Add
PROXY_INTERFACE**
PROXY_INTERFACE_ARRAY::FindByIndex (
IN DWORD Index
)
/*++
Routine Description:
Finds an interface by the interface index.
Arguments:
Index - index of the interface being searched for.
Return Values:
Pointer to the entry associated with the interface, if interface
with the index is in the array.
NULL if the interface with the index is not in the array.
Notes:
1. To be called from locked context
2. Does not transfer ownership of the interface being searched for
--*/
{
BOOL SearchResult;
DWORD ArrayIndex;
SearchResult = Array.BinarySearch (
SearchInterfaceByIndex,
&Index,
&ArrayIndex);
if (SearchResult)
{
return &Array [ArrayIndex];
}
return NULL;
} // PROXY_INTERFACE_ARRAY::FindByIndex
PROXY_INTERFACE *
PROXY_INTERFACE_ARRAY::RemoveByIndex (
IN DWORD Index
)
/*++
Routine Description:
Removes an interface with given index from the array.
Arguments:
Index - index of the interface to be removed.
Return Values:
Pointer to the removed interface, if interface with the
index is in the array.
NULL if interface with this index cannot be found in the
array.
Notes:
1. To be called from locked context
2. Transfers ownership of the interface being removed
--*/
{
PROXY_INTERFACE * ReturnInterface = NULL;
PROXY_INTERFACE ** Interface;
Interface = FindByIndex (Index);
if (Interface)
{
ReturnInterface = *Interface;
Array.DeleteEntry (Interface);
}
return ReturnInterface;
} // PROXY_INTERFACE_ARRAY::RemoveByIndex
HRESULT
PROXY_INTERFACE_ARRAY::IsPrivateAddress (
IN DWORD Address, // host order
OUT BOOL * IsPrivate
)
/*++
Routine Description:
Determines whether the address specified is
reachable through a private interface.
Arguments:
Address - IP address for which the determination
is to be made.
IsPrivate - Result of the determination (TRUE or FALSE)
Return Values:
Error code indicating whether the query succeeded.
Notes:
--*/
{
DWORD ArrayIndex;
PROXY_INTERFACE * Interface;
DWORD BestInterfaceAddress;
ULONG Error;
Error = GetBestInterfaceAddress (Address, &BestInterfaceAddress);
if (ERROR_SUCCESS != Error)
{
return E_FAIL;
}
*IsPrivate = FALSE;
Lock ();
for (ArrayIndex = 0; ArrayIndex < Array.Length; ArrayIndex++)
{
Interface = Array [ArrayIndex];
if (Interface -> Address == BestInterfaceAddress && Interface -> IsPrivate ())
{
*IsPrivate = TRUE;
break;
}
}
Unlock ();
return S_OK;
} // PROXY_INTERFACE_ARRAY::IsPrivateAddress
HRESULT
PROXY_INTERFACE_ARRAY::IsPublicAddress (
IN DWORD Address, // host order
OUT BOOL * IsPublic
)
/*++
Routine Description:
Determines whether the address specified is
reachable through a public interface.
Arguments:
Address - IP address for which the determination
is to be made.
IsPrivate - Result of the determination (TRUE or FALSE)
Return Values:
Error code indicating whether the query succeded.
Notes:
--*/
{
DWORD ArrayIndex;
PROXY_INTERFACE * Interface;
DWORD BestInterfaceAddress;
ULONG Error;
Error = GetBestInterfaceAddress (Address, &BestInterfaceAddress);
if (ERROR_SUCCESS != Error)
{
return E_FAIL;
}
*IsPublic = FALSE;
Lock ();
for (ArrayIndex = 0; ArrayIndex < Array.Length; ArrayIndex++)
{
Interface = Array [ArrayIndex];
if (Interface -> Address == BestInterfaceAddress && Interface -> IsPublic ())
{
*IsPublic = TRUE;
break;
}
}
Unlock ();
return S_OK;
} // PROXY_INTERFACE_ARRAY::IsPublicAddress
void
PROXY_INTERFACE_ARRAY::Stop (
void
)
/*++
Routine Description:
Stops all interfaces (in the array) that were not previously stopped.
Arguments:
None
Return Values:
None
Notes:
Normally, all the interfaces should have been individually stopped
prior to calling this method, in which case it does nothing.
If some interfaces were not stopped, when the method is called, it
will issue a warning and stop them.
--*/
{
DWORD Index;
Lock ();
if (Array.Length)
{
DebugF (_T("WARNING: Some interfaces are still active (should have already been deactivated). Starting deactivation procedures...\n"));
for (Index = 0; Index < Array.Length; Index++)
{
Array[Index] -> Stop ();
}
}
Array.Free ();
Unlock ();
} // PROXY_INTERFACE_ARRAY::Stop
ULONG
PROXY_INTERFACE_ARRAY::AddStartInterface (
IN ULONG Index,
IN H323_INTERFACE_TYPE ArgInterfaceType,
IN PIP_ADAPTER_BINDING_INFO BindingInfo
)
/*++
Routine Description:
Creates new interface, adds it to the array, and starts it.
Arguments:
Index - Index of the interface to be created.
ArgInterfaceType - Type of the interface to be created (PRIVATE
or PUBLIC)
BindingInfo - Binding information for the interface (address, mask, and
adapter index)
Return Values:
Win32 error code indicating success or failure of any of
the above three operations.
Notes:
--*/
{
HRESULT Result;
ULONG Error = ERROR_NOT_READY; // anything but ERROR_SUCCESS
PROXY_INTERFACE * Interface;
Lock ();
if (FindByIndex (Index))
{
Error = ERROR_INTERFACE_ALREADY_EXISTS;
} else {
Interface = new PROXY_INTERFACE (Index, ArgInterfaceType, BindingInfo);
if (Interface)
{
Result = Add (Interface);
if (S_OK == Result)
{
Error = Interface -> Start ();
if (ERROR_SUCCESS == Error)
{
DebugF(_T("H323: Interface %S activated, index %d\n"),
INET_NTOA (BindingInfo -> Address[0].Address), Index);
if (Q931ReceiveRedirectStartCount > 0
&& Interface -> IsFirewalled ()
&& !Interface -> HasQ931PortMapping ())
{
Interface -> StartQ931ReceiveRedirect ();
}
} else {
RemoveByIndex (Interface -> Index);
delete Interface;
}
} else {
switch (Result) {
case E_FAIL:
Error = ERROR_INTERFACE_ALREADY_EXISTS;
break;
case E_OUTOFMEMORY:
Error = ERROR_NOT_ENOUGH_MEMORY;
break;
default:
Error = ERROR_CAN_NOT_COMPLETE;
break;
}
delete Interface;
}
} else {
Error = ERROR_NOT_ENOUGH_MEMORY;
}
}
Unlock ();
return Error;
} // PROXY_INTERFACE_ARRAY::AddStartInterface
void
PROXY_INTERFACE_ARRAY::RemoveStopInterface (
IN DWORD Index
)
/*++
Routine Description:
Removes an interface from the array, and stops it.
Arguments:
Index - index of the interface to be removed and stopped.
Return Values:
None
Notes:
--*/
{
PROXY_INTERFACE* Interface;
Lock ();
Interface = RemoveByIndex (Index);
if (Interface)
{
Interface -> Stop ();
delete Interface;
Interface = NULL;
} else {
DebugF (_T("PROXY_INTERFACE_ARRAY::StopRemoveByIndex -- Tried to deactivate interface (index %d), but it does not exist.\n"),
Index);
}
Unlock ();
} // PROXY_INTERFACE_ARRAY::RemoveStopInterface
void
PROXY_INTERFACE_ARRAY::StartQ931ReceiveRedirects (
void
)
{
Lock();
if (0 == Q931ReceiveRedirectStartCount++)
{
for (DWORD dwIndex = 0; dwIndex < Array.Length; dwIndex++)
{
Array[dwIndex] -> StartQ931ReceiveRedirect ();
}
}
Unlock();
} // PROXY_INTERFACE_ARRAY::StartQ931ReceiveRedirects
void
PROXY_INTERFACE_ARRAY::StopQ931ReceiveRedirects (
void
)
{
Lock();
assert (Q931ReceiveRedirectStartCount > 0);
if (0 == --Q931ReceiveRedirectStartCount)
{
for (DWORD dwIndex = 0; dwIndex < Array.Length; dwIndex++)
{
if (Array[dwIndex] -> IsFirewalled ()
&& !Array[dwIndex] -> HasQ931PortMapping ())
{
Array[dwIndex] -> StopQ931ReceiveRedirect ();
}
}
}
Unlock();
} // PROXY_INTERFACE_ARRAY::StopQ931ReceiveRedirects
///////////////////////////////////////////////////////////////////////////////
// //
// Auxiliary Functions //
// //
///////////////////////////////////////////////////////////////////////////////
static
int
__cdecl
CompareInterfacesByIndex (
IN PROXY_INTERFACE * const * InterfaceA,
IN PROXY_INTERFACE * const * InterfaceB
)
/*++
Routine Description:
Compares two interfaces by their corresponding indices.
Arguments:
InterfaceA - first comparand
InterfaceB - second comparand
Return Values:
1 if InterfaceA is considered to be greater than InterfaceB
0 if InterfaceA is considered to be equal to the InterfaceB
-1 if InterfaceA is considered to be equal to the InterfaceB
Notes:
--*/
{
assert (InterfaceA);
assert (InterfaceB);
assert (*InterfaceA);
assert (*InterfaceB);
if ((*InterfaceA) -> GetIndex () > (*InterfaceB) -> GetIndex ())
{
return 1;
} else if ((*InterfaceA) -> GetIndex () < (*InterfaceB) -> GetIndex ()) {
return -1;
} else {
return 0;
}
} // ::CompareInterfacesByIndex
static
INT
SearchInterfaceByIndex (
IN const DWORD * Index,
IN PROXY_INTERFACE * const * Comparand
)
/*++
Routine Description:
Compares an interface and a key (index of the interface)
Arguments:
Index - key to which the interface is to be compared
Comparand - interface to be compared with the key
Return Values:
1 if key is considered to be greater than the comparand
0 if key is considered to be equal to the comparand
-1 if key is considered to be less than the comparand
Notes:
--*/
{
assert (Comparand);
assert (*Comparand);
assert (Index);
if (*Index > (*Comparand) -> GetIndex ())
{
return 1;
} else if (*Index < (*Comparand) -> GetIndex ()) {
return -1;
} else {
return 0;
}
} // ::SearchInterfaceByIndex
HRESULT
IsPrivateAddress (
IN DWORD Address,
OUT BOOL * IsPrivate
)
/*++
Routine Description:
Determines whether the address specified is
reachable through a private interface.
Arguments:
Address - IP address for which the determination
is to be made.
IsPrivate - Result of the determination (TRUE or FALSE)
Return Values:
Error code indicating whether the query succeded.
Notes:
--*/
{
assert (IsPrivate);
return InterfaceArray.IsPrivateAddress (Address, IsPrivate);
} // ::IsPrivateAddress
HRESULT
IsPublicAddress (
IN DWORD Address,
OUT BOOL * IsPublic
)
/*++
Routine Description:
Determines whether the address specified is
reachable through a public interface.
Arguments:
Address - IP address for which the determination
is to be made.
IsPrivate - Result of the determination (TRUE or FALSE)
Return Values:
Error code indicating whether the query succeded.
Notes:
--*/
{
assert (IsPublic);
return InterfaceArray.IsPublicAddress (Address, IsPublic);
} // ::IsPublicAddress