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.

1586 lines
31 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. intfc.h
  5. Abstract:
  6. Definitions of data types and corresponding methods used to provide
  7. multiple-interface support in H.323/LDAP proxy.
  8. Revision History:
  9. 03/01/2000 File creation. Ilya Kleyman (IlyaK)
  10. --*/
  11. ///////////////////////////////////////////////////////////////////////////////
  12. // //
  13. // Include files //
  14. // //
  15. ///////////////////////////////////////////////////////////////////////////////
  16. #include "stdafx.h"
  17. ///////////////////////////////////////////////////////////////////////////////
  18. // //
  19. // Global Variables //
  20. // //
  21. ///////////////////////////////////////////////////////////////////////////////
  22. PROXY_INTERFACE_ARRAY InterfaceArray;
  23. ///////////////////////////////////////////////////////////////////////////////
  24. // //
  25. // Static definitions //
  26. // //
  27. ///////////////////////////////////////////////////////////////////////////////
  28. static
  29. int
  30. __cdecl
  31. CompareInterfacesByIndex (
  32. IN PROXY_INTERFACE * const * InterfaceA,
  33. IN PROXY_INTERFACE * const * InterfaceB
  34. );
  35. static
  36. INT
  37. SearchInterfaceByIndex (
  38. IN const DWORD * Index,
  39. IN PROXY_INTERFACE *const* Comparand
  40. );
  41. ///////////////////////////////////////////////////////////////////////////////
  42. // //
  43. // Definitions //
  44. // //
  45. ///////////////////////////////////////////////////////////////////////////////
  46. // PROXY_INTERFACE ------------------------------------------------------------
  47. PROXY_INTERFACE::PROXY_INTERFACE (
  48. IN ULONG ArgIndex,
  49. IN H323_INTERFACE_TYPE ArgInterfaceType,
  50. IN PIP_ADAPTER_BINDING_INFO BindingInfo
  51. )
  52. /*++
  53. Routine Description:
  54. Constructor for PROXY_INTERFACE class
  55. Arguments:
  56. ArgIndex - Index of the interface
  57. ArgInterfaceType - Interface type (public or private)
  58. BindingInfo - Binding information for the interface
  59. Return Values:
  60. None
  61. Notes:
  62. --*/
  63. {
  64. Address = ntohl (BindingInfo -> Address[0].Address);
  65. Mask = ntohl (BindingInfo -> Address[0].Mask);
  66. Index = ArgIndex;
  67. InterfaceType = ArgInterfaceType;
  68. AdapterIndex = 0;
  69. Q931RedirectHandle = NULL;
  70. LdapRedirectHandle1 = NULL;
  71. LdapRedirectHandle2 = NULL;
  72. Q931LocalRedirectHandle = NULL;
  73. LdapLocalRedirectHandle1 = NULL;
  74. LdapLocalRedirectHandle2 = NULL;
  75. ::ZeroMemory (&Q931PortMapping, sizeof (Q931PortMapping));
  76. ::ZeroMemory (&LdapPortMapping, sizeof (LdapPortMapping));
  77. ::ZeroMemory (&LdapAltPortMapping, sizeof (LdapAltPortMapping));
  78. } // PROXY_INTERFACE::PROXY_INTERFACE
  79. PROXY_INTERFACE::~PROXY_INTERFACE (
  80. void
  81. )
  82. /*++
  83. Routine Description:
  84. Destructor for PROXY_INTERFACE class
  85. Arguments:
  86. None
  87. Return Values:
  88. None
  89. Notes:
  90. --*/
  91. {
  92. assert (!Q931RedirectHandle);
  93. assert (!LdapRedirectHandle1);
  94. assert (!LdapRedirectHandle2);
  95. assert (!Q931LocalRedirectHandle);
  96. assert (!LdapLocalRedirectHandle1);
  97. assert (!LdapLocalRedirectHandle2);
  98. } // PROXY_INTERFACE::~PROXY_INTERFACE
  99. ULONG
  100. PROXY_INTERFACE::StartNatRedirects (
  101. void
  102. )
  103. /*++
  104. Routine Description:
  105. Creates two types of adapter-restricted NAT redirects:
  106. Type 1 -- for connections incoming on the interface
  107. Type 2 -- for locally-originated connections (NOT destined to
  108. the local machine) through the interface
  109. Arguments:
  110. None
  111. Return Values:
  112. Win32 error indicating what (if anything) went wrong
  113. when trying to set up the NAT redirects.
  114. Notes:
  115. Total number of redirects created is 6:
  116. 2 Type 1 redirects for LDAP
  117. 2 Type 2 redirects for LDAP
  118. 1 Type 1 redirect for Q.931
  119. 1 Type 2 redirect for Q.931
  120. --*/
  121. {
  122. ULONG Status;
  123. assert (!Q931RedirectHandle);
  124. assert (!LdapRedirectHandle1);
  125. assert (!LdapRedirectHandle2);
  126. assert (!Q931LocalRedirectHandle);
  127. assert (!LdapLocalRedirectHandle1);
  128. assert (!LdapLocalRedirectHandle2);
  129. // Type 1 redirects -- for redirecting inbound connections
  130. if (!IsFirewalled () || HasQ931PortMapping ())
  131. {
  132. Status = StartQ931ReceiveRedirect ();
  133. }
  134. if (!IsFirewalled () || HasLdapPortMapping ())
  135. {
  136. Status = NatCreateDynamicAdapterRestrictedPortRedirect (
  137. 0,
  138. IPPROTO_TCP,
  139. htons (LDAP_STANDARD_PORT),
  140. LdapListenSocketAddress.sin_addr.s_addr,
  141. LdapListenSocketAddress.sin_port,
  142. AdapterIndex,
  143. MAX_LISTEN_BACKLOG,
  144. &LdapRedirectHandle1
  145. );
  146. if (Status != STATUS_SUCCESS)
  147. {
  148. DebugError (Status, _T("LDAP: Failed to create receive redirect #1 for LDAP.\n"));
  149. return Status;
  150. }
  151. DebugF (_T ("LDAP: Incoming connections to %08X:%04X will be redirected to %08X:%04X.\n"),
  152. Address,
  153. LDAP_STANDARD_PORT,
  154. ntohl (LdapListenSocketAddress.sin_addr.s_addr),
  155. ntohs (LdapListenSocketAddress.sin_port));
  156. }
  157. if (!IsFirewalled () || HasLdapAltPortMapping ())
  158. {
  159. Status = NatCreateDynamicAdapterRestrictedPortRedirect (
  160. 0,
  161. IPPROTO_TCP,
  162. htons (LDAP_ALTERNATE_PORT),
  163. LdapListenSocketAddress.sin_addr.s_addr,
  164. LdapListenSocketAddress.sin_port,
  165. AdapterIndex,
  166. MAX_LISTEN_BACKLOG,
  167. &LdapRedirectHandle2
  168. );
  169. if (Status != STATUS_SUCCESS)
  170. {
  171. DebugError (Status, _T("LDAP: Failed to create receive redirect #2 for LDAP.\n"));
  172. return Status;
  173. }
  174. DebugF (_T ("LDAP: Incoming connections to %08X:%04X will be redirected to %08X:%04X.\n"),
  175. Address,
  176. LDAP_ALTERNATE_PORT,
  177. ntohl (LdapListenSocketAddress.sin_addr.s_addr),
  178. ntohs (LdapListenSocketAddress.sin_port));
  179. }
  180. // Type 2 redirects (for locally-originated traffic, NOT destined to the local machine)
  181. Status = NatCreateDynamicAdapterRestrictedPortRedirect (
  182. NatRedirectFlagSendOnly,
  183. IPPROTO_TCP,
  184. htons (Q931_TSAP_IP_TCP),
  185. Q931ListenSocketAddress.sin_addr.s_addr,
  186. Q931ListenSocketAddress.sin_port,
  187. AdapterIndex,
  188. MAX_LISTEN_BACKLOG,
  189. &Q931LocalRedirectHandle
  190. );
  191. if (Status != STATUS_SUCCESS)
  192. {
  193. DebugError (Status, _T("Q931: Failed to create send redirect for Q.931.\n"));
  194. return Status;
  195. }
  196. DebugF (_T ("Q931: Locally-originated connections through %08X:%04X will be redirected to %08X:%04X.\n"),
  197. Address,
  198. Q931_TSAP_IP_TCP,
  199. ntohl (Q931ListenSocketAddress.sin_addr.s_addr),
  200. ntohs (Q931ListenSocketAddress.sin_port));
  201. Status = NatCreateDynamicAdapterRestrictedPortRedirect (
  202. NatRedirectFlagSendOnly,
  203. IPPROTO_TCP,
  204. htons (LDAP_STANDARD_PORT),
  205. LdapListenSocketAddress.sin_addr.s_addr,
  206. LdapListenSocketAddress.sin_port,
  207. AdapterIndex,
  208. MAX_LISTEN_BACKLOG,
  209. &LdapLocalRedirectHandle1
  210. );
  211. if (Status != STATUS_SUCCESS)
  212. {
  213. DebugError (Status, _T("LDAP: Failed to create send redirect #1 for LDAP.\n"));
  214. return Status;
  215. }
  216. DebugF (_T ("LDAP: Locally-originated connections through %08X:%04X will be redirected to %08X:%04X.\n"),
  217. Address,
  218. LDAP_STANDARD_PORT,
  219. ntohl (LdapListenSocketAddress.sin_addr.s_addr),
  220. ntohs (LdapListenSocketAddress.sin_port));
  221. Status = NatCreateDynamicAdapterRestrictedPortRedirect (
  222. NatRedirectFlagSendOnly,
  223. IPPROTO_TCP,
  224. htons (LDAP_ALTERNATE_PORT),
  225. LdapListenSocketAddress.sin_addr.s_addr,
  226. LdapListenSocketAddress.sin_port,
  227. AdapterIndex,
  228. MAX_LISTEN_BACKLOG,
  229. &LdapLocalRedirectHandle2
  230. );
  231. if (Status != STATUS_SUCCESS)
  232. {
  233. DebugError (Status, _T("LDAP: Failed to create send redirect #2 for LDAP.\n"));
  234. return Status;
  235. }
  236. DebugF (_T ("LDAP: Locally-originated connections through %08X:%04X will be redirected to %08X:%04X.\n"),
  237. Address,
  238. LDAP_ALTERNATE_PORT,
  239. ntohl (LdapListenSocketAddress.sin_addr.s_addr),
  240. ntohs (LdapListenSocketAddress.sin_port));
  241. return Status;
  242. } // PROXY_INTERFACE::StartNatRedirects
  243. ULONG
  244. PROXY_INTERFACE::Start (
  245. void
  246. )
  247. /*++
  248. Routine Description:
  249. Starts an interface
  250. Arguments:
  251. None
  252. Return Values:
  253. Win32 error indicating what (if anything) went wrong when
  254. the interface was being started.
  255. Notes:
  256. --*/
  257. {
  258. ULONG Status;
  259. assert (0 == AdapterIndex);
  260. assert (0 == Q931PortMapping.PrivateAddress);
  261. assert (0 == LdapPortMapping.PrivateAddress);
  262. assert (0 == LdapAltPortMapping.PrivateAddress);
  263. AdapterIndex = ::NhMapAddressToAdapter (htonl (Address));
  264. if (INVALID_INTERFACE_INDEX == AdapterIndex)
  265. {
  266. AdapterIndex = 0;
  267. Status = ERROR_CAN_NOT_COMPLETE;
  268. DebugF (_T ("PROXY_INTERFACE: Unable to map %08X to an adapter index\n"),
  269. Address);
  270. return Status;
  271. }
  272. //
  273. // Load the port mappings for this interface. Since more often than not
  274. // there won't be a port mapping, we expect these routines to return
  275. // errors, and thus don't check for them. NatLookupPortMappingAdapter
  276. // will modify the out parameter (i.e., the port mapping structure) only
  277. // on success.
  278. //
  279. ::NatLookupPortMappingAdapter (
  280. AdapterIndex,
  281. NAT_PROTOCOL_TCP,
  282. IP_NAT_ADDRESS_UNSPECIFIED,
  283. htons (Q931_TSAP_IP_TCP),
  284. &Q931PortMapping
  285. );
  286. ::NatLookupPortMappingAdapter (
  287. AdapterIndex,
  288. NAT_PROTOCOL_TCP,
  289. IP_NAT_ADDRESS_UNSPECIFIED,
  290. htons (LDAP_STANDARD_PORT),
  291. &LdapPortMapping
  292. );
  293. ::NatLookupPortMappingAdapter (
  294. AdapterIndex,
  295. NAT_PROTOCOL_TCP,
  296. IP_NAT_ADDRESS_UNSPECIFIED,
  297. htons (LDAP_ALTERNATE_PORT),
  298. &LdapAltPortMapping
  299. );
  300. Status = StartNatRedirects ();
  301. if (STATUS_SUCCESS != Status)
  302. {
  303. StopNatRedirects ();
  304. }
  305. return Status;
  306. } // PROXY_INTERFACE::Start
  307. void
  308. PROXY_INTERFACE::StopNatRedirects (
  309. void
  310. )
  311. /*++
  312. Routine Description:
  313. Removes all NAT redirects created for the interface
  314. Arguments:
  315. None
  316. Return Values:
  317. None
  318. Notes:
  319. --*/
  320. {
  321. if (Q931RedirectHandle)
  322. {
  323. NatCancelDynamicRedirect (Q931RedirectHandle);
  324. Q931RedirectHandle = NULL;
  325. }
  326. if (LdapRedirectHandle1)
  327. {
  328. NatCancelDynamicRedirect (LdapRedirectHandle1);
  329. LdapRedirectHandle1 = NULL;
  330. }
  331. if (LdapRedirectHandle2)
  332. {
  333. NatCancelDynamicRedirect (LdapRedirectHandle2);
  334. LdapRedirectHandle2 = NULL;
  335. }
  336. if (Q931LocalRedirectHandle)
  337. {
  338. NatCancelDynamicRedirect (Q931LocalRedirectHandle);
  339. Q931LocalRedirectHandle = NULL;
  340. }
  341. if (LdapLocalRedirectHandle1)
  342. {
  343. NatCancelDynamicRedirect (LdapLocalRedirectHandle1);
  344. LdapLocalRedirectHandle1 = NULL;
  345. }
  346. if (LdapLocalRedirectHandle2)
  347. {
  348. NatCancelDynamicRedirect (LdapLocalRedirectHandle2);
  349. LdapLocalRedirectHandle2 = NULL;
  350. }
  351. } // PROXY_INTERFACE::StopNatRedirects
  352. ULONG
  353. PROXY_INTERFACE::StartQ931ReceiveRedirect (
  354. void
  355. )
  356. /*++
  357. Routine Description:
  358. Creates the type 1 (receive) redirect for Q931 traffic,
  359. if this has not already been done on the interface.
  360. Arguments:
  361. None
  362. Return Values:
  363. Win32 error indicating what (if anything) went wrong
  364. when trying to set up the redirect.
  365. --*/
  366. {
  367. ULONG Status = STATUS_SUCCESS;
  368. if (NULL == Q931RedirectHandle)
  369. {
  370. Status = NatCreateDynamicAdapterRestrictedPortRedirect (
  371. 0,
  372. IPPROTO_TCP,
  373. htons (Q931_TSAP_IP_TCP),
  374. Q931ListenSocketAddress.sin_addr.s_addr,
  375. Q931ListenSocketAddress.sin_port,
  376. AdapterIndex,
  377. MAX_LISTEN_BACKLOG,
  378. &Q931RedirectHandle
  379. );
  380. if (Status != STATUS_SUCCESS)
  381. {
  382. DebugError (Status, _T("Q931: Failed to create receive redirect for Q.931.\n"));
  383. return Status;
  384. }
  385. DebugF (_T ("Q931: Incoming connections to %08X:%04X will be redirected to %08X:%04X.\n"),
  386. Address,
  387. Q931_TSAP_IP_TCP,
  388. ntohl (Q931ListenSocketAddress.sin_addr.s_addr),
  389. ntohs (Q931ListenSocketAddress.sin_port));
  390. }
  391. return Status;
  392. } // PROXY_INTERFACE::StartQ931ReceiveRedirect
  393. void
  394. PROXY_INTERFACE::StopQ931ReceiveRedirect (
  395. void
  396. )
  397. /*++
  398. Routine Description:
  399. Stops the Q931 receive redirect, if it has been created.
  400. Arguments:
  401. None
  402. Return Values:
  403. None
  404. --*/
  405. {
  406. if (Q931RedirectHandle)
  407. {
  408. NatCancelDynamicRedirect (Q931RedirectHandle);
  409. Q931RedirectHandle = NULL;
  410. }
  411. } // PROXY_INTERFACE::StopQ931ReceiveRedirect
  412. void
  413. PROXY_INTERFACE::Stop (
  414. void
  415. )
  416. /*++
  417. Routine Description:
  418. 1. Terminate all connections through the interface.
  419. 2. Remove all translation entries registered via the interface.
  420. 3. Stop all NAT redirects created for this interface.
  421. Arguments:
  422. None
  423. Return Values:
  424. None
  425. Notes:
  426. The caller of this method should first remove the
  427. interface from the global array.
  428. --*/
  429. {
  430. CallBridgeList.OnInterfaceShutdown (Address);
  431. LdapConnectionArray.OnInterfaceShutdown (Address);
  432. LdapTranslationTable.OnInterfaceShutdown (Address);
  433. StopNatRedirects ();
  434. ::ZeroMemory (&Q931PortMapping, sizeof (Q931PortMapping));
  435. ::ZeroMemory (&LdapPortMapping, sizeof (LdapPortMapping));
  436. ::ZeroMemory (&LdapAltPortMapping, sizeof (LdapAltPortMapping));
  437. AdapterIndex = 0;
  438. } // PROXY_INTERFACE::Stop
  439. BOOL
  440. PROXY_INTERFACE::IsFirewalled (
  441. void
  442. )
  443. /*++
  444. Routine Description:
  445. Determines whether the interface was created as firewalled.
  446. Arguments:
  447. None
  448. Return Values:
  449. TRUE - if the interface was created as firewalled.
  450. FALSE - if the interface was created as non-firewalled.
  451. Notes:
  452. --*/
  453. {
  454. return InterfaceType == H323_INTERFACE_PUBLIC_FIREWALLED;
  455. } // PROXY_INTERFACE::IsFirewalled
  456. BOOL
  457. PROXY_INTERFACE::IsPrivate (
  458. void
  459. )
  460. /*++
  461. Routine Description:
  462. Determines whether the interface was created as private.
  463. Arguments:
  464. None
  465. Return Values:
  466. TRUE if the interface was created as private
  467. FALSE if the interface was created as non-private
  468. Notes:
  469. --*/
  470. {
  471. return InterfaceType == H323_INTERFACE_PRIVATE;
  472. } // PROXY_INTERFACE::IsPrivate
  473. BOOL
  474. PROXY_INTERFACE::IsPublic (
  475. void
  476. )
  477. /*++
  478. Routine Description:
  479. Determines whether the interface was created as public.
  480. Arguments:
  481. None
  482. Return Values:
  483. TRUE - if the interface was created as public.
  484. FALSE - if the interface was created as non-public.
  485. Notes:
  486. --*/
  487. {
  488. return InterfaceType == H323_INTERFACE_PUBLIC
  489. || InterfaceType == H323_INTERFACE_PUBLIC_FIREWALLED;
  490. } // PROXY_INTERFACE::IsPublic
  491. BOOL
  492. PROXY_INTERFACE::HasQ931PortMapping (
  493. void
  494. )
  495. /*++
  496. Routine Description:
  497. Determines whether the interface has a valid Q931 port mapping.
  498. Arguments:
  499. None
  500. Return Values:
  501. TRUE if the interface has a valid Q931 port mapping
  502. FALSE if the interface does not have a valid Q931 port mapping
  503. Notes:
  504. --*/
  505. {
  506. return Q931PortMapping.PrivateAddress != 0;
  507. } // PROXY_INTERFACE::HasQ931PortMapping
  508. BOOL
  509. PROXY_INTERFACE::HasLdapPortMapping (
  510. void
  511. )
  512. /*++
  513. Routine Description:
  514. Determines whether the interface has a valid Ldap port mapping.
  515. Arguments:
  516. None
  517. Return Values:
  518. TRUE if the interface has a valid Ldap port mapping
  519. FALSE if the interface does not have a valid Ldap port mapping
  520. Notes:
  521. --*/
  522. {
  523. return LdapPortMapping.PrivateAddress != 0;
  524. } // PROXY_INTERFACE::HasLdapPortMapping
  525. BOOL
  526. PROXY_INTERFACE::HasLdapAltPortMapping (
  527. void
  528. )
  529. /*++
  530. Routine Description:
  531. Determines whether the interface has a valid Ldap (alt) port mapping.
  532. Arguments:
  533. None
  534. Return Values:
  535. TRUE if the interface has a valid Ldap (alt) port mapping
  536. FALSE if the interface does not have a valid Ldap (alt) port mapping
  537. Notes:
  538. --*/
  539. {
  540. return LdapAltPortMapping.PrivateAddress != 0;
  541. } // PROXY_INTERFACE::HasLdapAltPortMapping
  542. ULONG
  543. PROXY_INTERFACE::GetQ931PortMappingDestination (
  544. void
  545. )
  546. /*++
  547. Routine Description:
  548. Returns the destination address of the interfaces
  549. Q931 port mapping.
  550. Arguments:
  551. None
  552. Return Values:
  553. The destination address of the port mapping, in network
  554. byte order. Returns 0 if no port mapping exists.
  555. Notes:
  556. --*/
  557. {
  558. return Q931PortMapping.PrivateAddress;
  559. } // PROXY_INTERFACE::GetQ931PortMappingDestination
  560. ULONG
  561. PROXY_INTERFACE::GetLdapPortMappingDestination (
  562. void
  563. )
  564. /*++
  565. Routine Description:
  566. Returns the destination address of the interfaces
  567. Ldap port mapping.
  568. Arguments:
  569. None
  570. Return Values:
  571. The destination address of the port mapping, in network
  572. byte order. Returns 0 if no port mapping exists.
  573. Notes:
  574. --*/
  575. {
  576. return LdapPortMapping.PrivateAddress;
  577. } // PROXY_INTERFACE::GetLdapPortMappingDestination
  578. ULONG
  579. PROXY_INTERFACE::GetLdapAltPortMappingDestination (
  580. void
  581. )
  582. /*++
  583. Routine Description:
  584. Returns the destination address of the interfaces
  585. Ldap-alt port mapping.
  586. Arguments:
  587. None
  588. Return Values:
  589. The destination address of the port mapping, in network
  590. byte order. Returns 0 if no port mapping exists.
  591. Notes:
  592. --*/
  593. {
  594. return LdapAltPortMapping.PrivateAddress;
  595. } // PROXY_INTERFACE::GetLdapAltPortMappingDestination
  596. // PROXY_INTERFACE_ARRAY ------------------------------------------------------
  597. HRESULT
  598. PROXY_INTERFACE_ARRAY::Add (
  599. IN PROXY_INTERFACE* Interface
  600. )
  601. /*++
  602. Routine Description:
  603. Adds an interface to the array.
  604. Arguments:
  605. Interface - interface to be added.
  606. Return Values:
  607. Error code indicating whether the operation succeeded.
  608. Notes:
  609. To be called from locked context.
  610. --*/
  611. {
  612. DWORD ReturnIndex;
  613. PROXY_INTERFACE** ElementPlaceholder;
  614. assert (Interface);
  615. if (Array.FindIndex (CompareInterfacesByIndex, &Interface, &ReturnIndex))
  616. {
  617. // Interface with this index already exists
  618. return E_FAIL;
  619. }
  620. ElementPlaceholder = Array.AllocAtPos (ReturnIndex);
  621. if (!ElementPlaceholder)
  622. return E_OUTOFMEMORY;
  623. *ElementPlaceholder = Interface;
  624. return S_OK;
  625. } // PROXY_INTERFACE_ARRAY::Add
  626. PROXY_INTERFACE**
  627. PROXY_INTERFACE_ARRAY::FindByIndex (
  628. IN DWORD Index
  629. )
  630. /*++
  631. Routine Description:
  632. Finds an interface by the interface index.
  633. Arguments:
  634. Index - index of the interface being searched for.
  635. Return Values:
  636. Pointer to the entry associated with the interface, if interface
  637. with the index is in the array.
  638. NULL if the interface with the index is not in the array.
  639. Notes:
  640. 1. To be called from locked context
  641. 2. Does not transfer ownership of the interface being searched for
  642. --*/
  643. {
  644. BOOL SearchResult;
  645. DWORD ArrayIndex;
  646. SearchResult = Array.BinarySearch (
  647. SearchInterfaceByIndex,
  648. &Index,
  649. &ArrayIndex);
  650. if (SearchResult)
  651. {
  652. return &Array [ArrayIndex];
  653. }
  654. return NULL;
  655. } // PROXY_INTERFACE_ARRAY::FindByIndex
  656. PROXY_INTERFACE *
  657. PROXY_INTERFACE_ARRAY::RemoveByIndex (
  658. IN DWORD Index
  659. )
  660. /*++
  661. Routine Description:
  662. Removes an interface with given index from the array.
  663. Arguments:
  664. Index - index of the interface to be removed.
  665. Return Values:
  666. Pointer to the removed interface, if interface with the
  667. index is in the array.
  668. NULL if interface with this index cannot be found in the
  669. array.
  670. Notes:
  671. 1. To be called from locked context
  672. 2. Transfers ownership of the interface being removed
  673. --*/
  674. {
  675. PROXY_INTERFACE * ReturnInterface = NULL;
  676. PROXY_INTERFACE ** Interface;
  677. Interface = FindByIndex (Index);
  678. if (Interface)
  679. {
  680. ReturnInterface = *Interface;
  681. Array.DeleteEntry (Interface);
  682. }
  683. return ReturnInterface;
  684. } // PROXY_INTERFACE_ARRAY::RemoveByIndex
  685. HRESULT
  686. PROXY_INTERFACE_ARRAY::IsPrivateAddress (
  687. IN DWORD Address, // host order
  688. OUT BOOL * IsPrivate
  689. )
  690. /*++
  691. Routine Description:
  692. Determines whether the address specified is
  693. reachable through a private interface.
  694. Arguments:
  695. Address - IP address for which the determination
  696. is to be made.
  697. IsPrivate - Result of the determination (TRUE or FALSE)
  698. Return Values:
  699. Error code indicating whether the query succeeded.
  700. Notes:
  701. --*/
  702. {
  703. DWORD ArrayIndex;
  704. PROXY_INTERFACE * Interface;
  705. DWORD BestInterfaceAddress;
  706. ULONG Error;
  707. Error = GetBestInterfaceAddress (Address, &BestInterfaceAddress);
  708. if (ERROR_SUCCESS != Error)
  709. {
  710. return E_FAIL;
  711. }
  712. *IsPrivate = FALSE;
  713. Lock ();
  714. for (ArrayIndex = 0; ArrayIndex < Array.Length; ArrayIndex++)
  715. {
  716. Interface = Array [ArrayIndex];
  717. if (Interface -> Address == BestInterfaceAddress && Interface -> IsPrivate ())
  718. {
  719. *IsPrivate = TRUE;
  720. break;
  721. }
  722. }
  723. Unlock ();
  724. return S_OK;
  725. } // PROXY_INTERFACE_ARRAY::IsPrivateAddress
  726. HRESULT
  727. PROXY_INTERFACE_ARRAY::IsPublicAddress (
  728. IN DWORD Address, // host order
  729. OUT BOOL * IsPublic
  730. )
  731. /*++
  732. Routine Description:
  733. Determines whether the address specified is
  734. reachable through a public interface.
  735. Arguments:
  736. Address - IP address for which the determination
  737. is to be made.
  738. IsPrivate - Result of the determination (TRUE or FALSE)
  739. Return Values:
  740. Error code indicating whether the query succeded.
  741. Notes:
  742. --*/
  743. {
  744. DWORD ArrayIndex;
  745. PROXY_INTERFACE * Interface;
  746. DWORD BestInterfaceAddress;
  747. ULONG Error;
  748. Error = GetBestInterfaceAddress (Address, &BestInterfaceAddress);
  749. if (ERROR_SUCCESS != Error)
  750. {
  751. return E_FAIL;
  752. }
  753. *IsPublic = FALSE;
  754. Lock ();
  755. for (ArrayIndex = 0; ArrayIndex < Array.Length; ArrayIndex++)
  756. {
  757. Interface = Array [ArrayIndex];
  758. if (Interface -> Address == BestInterfaceAddress && Interface -> IsPublic ())
  759. {
  760. *IsPublic = TRUE;
  761. break;
  762. }
  763. }
  764. Unlock ();
  765. return S_OK;
  766. } // PROXY_INTERFACE_ARRAY::IsPublicAddress
  767. void
  768. PROXY_INTERFACE_ARRAY::Stop (
  769. void
  770. )
  771. /*++
  772. Routine Description:
  773. Stops all interfaces (in the array) that were not previously stopped.
  774. Arguments:
  775. None
  776. Return Values:
  777. None
  778. Notes:
  779. Normally, all the interfaces should have been individually stopped
  780. prior to calling this method, in which case it does nothing.
  781. If some interfaces were not stopped, when the method is called, it
  782. will issue a warning and stop them.
  783. --*/
  784. {
  785. DWORD Index;
  786. Lock ();
  787. if (Array.Length)
  788. {
  789. DebugF (_T("WARNING: Some interfaces are still active (should have already been deactivated). Starting deactivation procedures...\n"));
  790. for (Index = 0; Index < Array.Length; Index++)
  791. {
  792. Array[Index] -> Stop ();
  793. }
  794. }
  795. Array.Free ();
  796. Unlock ();
  797. } // PROXY_INTERFACE_ARRAY::Stop
  798. ULONG
  799. PROXY_INTERFACE_ARRAY::AddStartInterface (
  800. IN ULONG Index,
  801. IN H323_INTERFACE_TYPE ArgInterfaceType,
  802. IN PIP_ADAPTER_BINDING_INFO BindingInfo
  803. )
  804. /*++
  805. Routine Description:
  806. Creates new interface, adds it to the array, and starts it.
  807. Arguments:
  808. Index - Index of the interface to be created.
  809. ArgInterfaceType - Type of the interface to be created (PRIVATE
  810. or PUBLIC)
  811. BindingInfo - Binding information for the interface (address, mask, and
  812. adapter index)
  813. Return Values:
  814. Win32 error code indicating success or failure of any of
  815. the above three operations.
  816. Notes:
  817. --*/
  818. {
  819. HRESULT Result;
  820. ULONG Error = ERROR_NOT_READY; // anything but ERROR_SUCCESS
  821. PROXY_INTERFACE * Interface;
  822. Lock ();
  823. if (FindByIndex (Index))
  824. {
  825. Error = ERROR_INTERFACE_ALREADY_EXISTS;
  826. } else {
  827. Interface = new PROXY_INTERFACE (Index, ArgInterfaceType, BindingInfo);
  828. if (Interface)
  829. {
  830. Result = Add (Interface);
  831. if (S_OK == Result)
  832. {
  833. Error = Interface -> Start ();
  834. if (ERROR_SUCCESS == Error)
  835. {
  836. DebugF(_T("H323: Interface %S activated, index %d\n"),
  837. INET_NTOA (BindingInfo -> Address[0].Address), Index);
  838. if (Q931ReceiveRedirectStartCount > 0
  839. && Interface -> IsFirewalled ()
  840. && !Interface -> HasQ931PortMapping ())
  841. {
  842. Interface -> StartQ931ReceiveRedirect ();
  843. }
  844. } else {
  845. RemoveByIndex (Interface -> Index);
  846. delete Interface;
  847. }
  848. } else {
  849. switch (Result) {
  850. case E_FAIL:
  851. Error = ERROR_INTERFACE_ALREADY_EXISTS;
  852. break;
  853. case E_OUTOFMEMORY:
  854. Error = ERROR_NOT_ENOUGH_MEMORY;
  855. break;
  856. default:
  857. Error = ERROR_CAN_NOT_COMPLETE;
  858. break;
  859. }
  860. delete Interface;
  861. }
  862. } else {
  863. Error = ERROR_NOT_ENOUGH_MEMORY;
  864. }
  865. }
  866. Unlock ();
  867. return Error;
  868. } // PROXY_INTERFACE_ARRAY::AddStartInterface
  869. void
  870. PROXY_INTERFACE_ARRAY::RemoveStopInterface (
  871. IN DWORD Index
  872. )
  873. /*++
  874. Routine Description:
  875. Removes an interface from the array, and stops it.
  876. Arguments:
  877. Index - index of the interface to be removed and stopped.
  878. Return Values:
  879. None
  880. Notes:
  881. --*/
  882. {
  883. PROXY_INTERFACE* Interface;
  884. Lock ();
  885. Interface = RemoveByIndex (Index);
  886. if (Interface)
  887. {
  888. Interface -> Stop ();
  889. delete Interface;
  890. Interface = NULL;
  891. } else {
  892. DebugF (_T("PROXY_INTERFACE_ARRAY::StopRemoveByIndex -- Tried to deactivate interface (index %d), but it does not exist.\n"),
  893. Index);
  894. }
  895. Unlock ();
  896. } // PROXY_INTERFACE_ARRAY::RemoveStopInterface
  897. void
  898. PROXY_INTERFACE_ARRAY::StartQ931ReceiveRedirects (
  899. void
  900. )
  901. {
  902. Lock();
  903. if (0 == Q931ReceiveRedirectStartCount++)
  904. {
  905. for (DWORD dwIndex = 0; dwIndex < Array.Length; dwIndex++)
  906. {
  907. Array[dwIndex] -> StartQ931ReceiveRedirect ();
  908. }
  909. }
  910. Unlock();
  911. } // PROXY_INTERFACE_ARRAY::StartQ931ReceiveRedirects
  912. void
  913. PROXY_INTERFACE_ARRAY::StopQ931ReceiveRedirects (
  914. void
  915. )
  916. {
  917. Lock();
  918. assert (Q931ReceiveRedirectStartCount > 0);
  919. if (0 == --Q931ReceiveRedirectStartCount)
  920. {
  921. for (DWORD dwIndex = 0; dwIndex < Array.Length; dwIndex++)
  922. {
  923. if (Array[dwIndex] -> IsFirewalled ()
  924. && !Array[dwIndex] -> HasQ931PortMapping ())
  925. {
  926. Array[dwIndex] -> StopQ931ReceiveRedirect ();
  927. }
  928. }
  929. }
  930. Unlock();
  931. } // PROXY_INTERFACE_ARRAY::StopQ931ReceiveRedirects
  932. ///////////////////////////////////////////////////////////////////////////////
  933. // //
  934. // Auxiliary Functions //
  935. // //
  936. ///////////////////////////////////////////////////////////////////////////////
  937. static
  938. int
  939. __cdecl
  940. CompareInterfacesByIndex (
  941. IN PROXY_INTERFACE * const * InterfaceA,
  942. IN PROXY_INTERFACE * const * InterfaceB
  943. )
  944. /*++
  945. Routine Description:
  946. Compares two interfaces by their corresponding indices.
  947. Arguments:
  948. InterfaceA - first comparand
  949. InterfaceB - second comparand
  950. Return Values:
  951. 1 if InterfaceA is considered to be greater than InterfaceB
  952. 0 if InterfaceA is considered to be equal to the InterfaceB
  953. -1 if InterfaceA is considered to be equal to the InterfaceB
  954. Notes:
  955. --*/
  956. {
  957. assert (InterfaceA);
  958. assert (InterfaceB);
  959. assert (*InterfaceA);
  960. assert (*InterfaceB);
  961. if ((*InterfaceA) -> GetIndex () > (*InterfaceB) -> GetIndex ())
  962. {
  963. return 1;
  964. } else if ((*InterfaceA) -> GetIndex () < (*InterfaceB) -> GetIndex ()) {
  965. return -1;
  966. } else {
  967. return 0;
  968. }
  969. } // ::CompareInterfacesByIndex
  970. static
  971. INT
  972. SearchInterfaceByIndex (
  973. IN const DWORD * Index,
  974. IN PROXY_INTERFACE * const * Comparand
  975. )
  976. /*++
  977. Routine Description:
  978. Compares an interface and a key (index of the interface)
  979. Arguments:
  980. Index - key to which the interface is to be compared
  981. Comparand - interface to be compared with the key
  982. Return Values:
  983. 1 if key is considered to be greater than the comparand
  984. 0 if key is considered to be equal to the comparand
  985. -1 if key is considered to be less than the comparand
  986. Notes:
  987. --*/
  988. {
  989. assert (Comparand);
  990. assert (*Comparand);
  991. assert (Index);
  992. if (*Index > (*Comparand) -> GetIndex ())
  993. {
  994. return 1;
  995. } else if (*Index < (*Comparand) -> GetIndex ()) {
  996. return -1;
  997. } else {
  998. return 0;
  999. }
  1000. } // ::SearchInterfaceByIndex
  1001. HRESULT
  1002. IsPrivateAddress (
  1003. IN DWORD Address,
  1004. OUT BOOL * IsPrivate
  1005. )
  1006. /*++
  1007. Routine Description:
  1008. Determines whether the address specified is
  1009. reachable through a private interface.
  1010. Arguments:
  1011. Address - IP address for which the determination
  1012. is to be made.
  1013. IsPrivate - Result of the determination (TRUE or FALSE)
  1014. Return Values:
  1015. Error code indicating whether the query succeded.
  1016. Notes:
  1017. --*/
  1018. {
  1019. assert (IsPrivate);
  1020. return InterfaceArray.IsPrivateAddress (Address, IsPrivate);
  1021. } // ::IsPrivateAddress
  1022. HRESULT
  1023. IsPublicAddress (
  1024. IN DWORD Address,
  1025. OUT BOOL * IsPublic
  1026. )
  1027. /*++
  1028. Routine Description:
  1029. Determines whether the address specified is
  1030. reachable through a public interface.
  1031. Arguments:
  1032. Address - IP address for which the determination
  1033. is to be made.
  1034. IsPrivate - Result of the determination (TRUE or FALSE)
  1035. Return Values:
  1036. Error code indicating whether the query succeded.
  1037. Notes:
  1038. --*/
  1039. {
  1040. assert (IsPublic);
  1041. return InterfaceArray.IsPublicAddress (Address, IsPublic);
  1042. } // ::IsPublicAddress