/*++ 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