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.

1321 lines
27 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. h323if.c
  5. Abstract:
  6. This module contains code for the H.323 transparent proxy's interface
  7. management.
  8. Author:
  9. Abolade Gbadegesin (aboladeg) 18-Jun-1999
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <h323icsp.h>
  15. //
  16. // GLOBAL DATA DEFINITIONS
  17. //
  18. LIST_ENTRY H323InterfaceList;
  19. CRITICAL_SECTION H323InterfaceLock;
  20. //
  21. // FORWARD DECLARATIONS
  22. //
  23. ULONG
  24. H323ActivateInterface(
  25. PH323_INTERFACE Interfacep
  26. )
  27. /*++
  28. Routine Description:
  29. This routine is called to activate an interface, when the interface
  30. becomes both enabled and bound.
  31. Arguments:
  32. Interfacep - the interface to be activated
  33. Return Value:
  34. ULONG - Win32 status code indicating success or failure.
  35. Environment:
  36. Always invoked locally, with 'Interfacep' referenced by caller and/or
  37. 'H323InterfaceLock' held by caller.
  38. --*/
  39. {
  40. ULONG Error;
  41. ULONG i;
  42. ULONG InterfaceCharacteristics;
  43. H323_INTERFACE_TYPE H323InterfaceType;
  44. PROFILE("H323ActivateInterface");
  45. EnterCriticalSection(&H323InterfaceLock);
  46. if (H323_INTERFACE_ADMIN_DISABLED(Interfacep)) {
  47. LeaveCriticalSection(&H323InterfaceLock);
  48. return NO_ERROR;
  49. }
  50. InterfaceCharacteristics =
  51. NatGetInterfaceCharacteristics(
  52. Interfacep->Index
  53. );
  54. if (!InterfaceCharacteristics) {
  55. LeaveCriticalSection(&H323InterfaceLock);
  56. NhTrace(
  57. TRACE_FLAG_H323,
  58. "H323ActivateInterface: ignoring non-NAT interface %d",
  59. Interfacep->Index
  60. );
  61. return NO_ERROR;
  62. }
  63. Error = NO_ERROR;
  64. if (NAT_IFC_FW(InterfaceCharacteristics)) {
  65. H323InterfaceType = H323_INTERFACE_PUBLIC_FIREWALLED;
  66. } else if (NAT_IFC_BOUNDARY(InterfaceCharacteristics)) {
  67. H323InterfaceType = H323_INTERFACE_PUBLIC;
  68. } else {
  69. ASSERT(NAT_IFC_PRIVATE(InterfaceCharacteristics));
  70. H323InterfaceType = H323_INTERFACE_PRIVATE;
  71. }
  72. ACQUIRE_LOCK(Interfacep);
  73. H323ProxyActivateInterface(
  74. Interfacep->Index,
  75. H323InterfaceType,
  76. Interfacep->BindingInfo
  77. );
  78. RELEASE_LOCK(Interfacep);
  79. LeaveCriticalSection(&H323InterfaceLock);
  80. return NO_ERROR;
  81. } // H323ActivateInterface
  82. ULONG
  83. H323BindInterface(
  84. ULONG Index,
  85. PIP_ADAPTER_BINDING_INFO BindingInfo
  86. )
  87. /*++
  88. Routine Description:
  89. This routine is invoked to supply the binding for an interface.
  90. It records the binding information received, and if necessary,
  91. it activates the interface.
  92. Arguments:
  93. Index - the index of the interface to be bound
  94. BindingInfo - the binding-information for the interface
  95. Return Value:
  96. ULONG - Win32 status code.
  97. Environment:
  98. Invoked internally in the context of an IP router-manager thread.
  99. (See 'RMH323.C').
  100. --*/
  101. {
  102. ULONG Error = NO_ERROR;
  103. ULONG i;
  104. PH323_INTERFACE Interfacep;
  105. PROFILE("H323BindInterface");
  106. EnterCriticalSection(&H323InterfaceLock);
  107. //
  108. // Retrieve the interface to be bound
  109. //
  110. if (!(Interfacep = H323LookupInterface(Index, NULL))) {
  111. LeaveCriticalSection(&H323InterfaceLock);
  112. NhTrace(
  113. TRACE_FLAG_IF,
  114. "H323BindInterface: interface %d not found",
  115. Index
  116. );
  117. return ERROR_NO_SUCH_INTERFACE;
  118. }
  119. //
  120. // Make sure the interface isn't already bound
  121. //
  122. if (H323_INTERFACE_BOUND(Interfacep)) {
  123. LeaveCriticalSection(&H323InterfaceLock);
  124. NhTrace(
  125. TRACE_FLAG_IF,
  126. "H323BindInterface: interface %d is already bound",
  127. Index
  128. );
  129. return ERROR_ADDRESS_ALREADY_ASSOCIATED;
  130. }
  131. //
  132. // Reference the interface
  133. //
  134. if (!H323_REFERENCE_INTERFACE(Interfacep)) {
  135. LeaveCriticalSection(&H323InterfaceLock);
  136. NhTrace(
  137. TRACE_FLAG_IF,
  138. "H323BindInterface: interface %d cannot be referenced",
  139. Index
  140. );
  141. return ERROR_INTERFACE_DISABLED;
  142. }
  143. //
  144. // Update the interface's flags
  145. //
  146. Interfacep->Flags |= H323_INTERFACE_FLAG_BOUND;
  147. LeaveCriticalSection(&H323InterfaceLock);
  148. ACQUIRE_LOCK(Interfacep);
  149. //
  150. // Allocate space for the binding, and copy it
  151. //
  152. Interfacep->BindingInfo =
  153. reinterpret_cast<PIP_ADAPTER_BINDING_INFO>(
  154. NH_ALLOCATE(SIZEOF_IP_BINDING(BindingInfo->AddressCount))
  155. );
  156. if (!Interfacep->BindingInfo) {
  157. RELEASE_LOCK(Interfacep);
  158. H323_DEREFERENCE_INTERFACE(Interfacep);
  159. NhTrace(
  160. TRACE_FLAG_IF,
  161. "H323BindInterface: allocation failed for interface %d binding",
  162. Index
  163. );
  164. NhErrorLog(
  165. IP_H323_LOG_ALLOCATION_FAILED,
  166. 0,
  167. "%d",
  168. SIZEOF_IP_BINDING(BindingInfo->AddressCount)
  169. );
  170. return ERROR_NOT_ENOUGH_MEMORY;
  171. }
  172. CopyMemory(
  173. Interfacep->BindingInfo,
  174. BindingInfo,
  175. SIZEOF_IP_BINDING(BindingInfo->AddressCount)
  176. );
  177. RELEASE_LOCK(Interfacep);
  178. //
  179. // Activate the interface if necessary
  180. //
  181. if (H323_INTERFACE_ACTIVE(Interfacep)) {
  182. Error = H323ActivateInterface(Interfacep);
  183. }
  184. H323_DEREFERENCE_INTERFACE(Interfacep);
  185. return Error;
  186. } // H323BindInterface
  187. VOID
  188. H323CleanupInterface(
  189. PH323_INTERFACE Interfacep
  190. )
  191. /*++
  192. Routine Description:
  193. This routine is invoked when the very last reference to an interface
  194. is released, and the interface must be destroyed.
  195. Arguments:
  196. Interfacep - the interface to be destroyed
  197. Return Value:
  198. none.
  199. Environment:
  200. Invoked internally from an arbitrary context, with no references
  201. to the interface.
  202. --*/
  203. {
  204. PLIST_ENTRY Link;
  205. PROFILE("H323CleanupInterface");
  206. if (Interfacep->BindingInfo) {
  207. NH_FREE(Interfacep->BindingInfo);
  208. Interfacep->BindingInfo = NULL;
  209. }
  210. DeleteCriticalSection(&Interfacep->Lock);
  211. NH_FREE(Interfacep);
  212. } // H323CleanupInterface
  213. ULONG
  214. H323ConfigureInterface(
  215. ULONG Index,
  216. PIP_H323_INTERFACE_INFO InterfaceInfo
  217. )
  218. /*++
  219. Routine Description:
  220. This routine is called to set the configuration for an interface.
  221. Arguments:
  222. Index - the interface to be configured
  223. InterfaceInfo - the new configuration
  224. Return Value:
  225. ULONG - Win32 status code
  226. Environment:
  227. Invoked internally in the context of a IP router-manager thread.
  228. (See 'RMH323.C').
  229. --*/
  230. {
  231. ULONG Error;
  232. PH323_INTERFACE Interfacep;
  233. ULONG NewFlags;
  234. ULONG OldFlags;
  235. PROFILE("H323ConfigureInterface");
  236. //
  237. // Retrieve the interface to be configured
  238. //
  239. EnterCriticalSection(&H323InterfaceLock);
  240. if (!(Interfacep = H323LookupInterface(Index, NULL))) {
  241. LeaveCriticalSection(&H323InterfaceLock);
  242. NhTrace(
  243. TRACE_FLAG_IF,
  244. "H323ConfigureInterface: interface %d not found",
  245. Index
  246. );
  247. return ERROR_NO_SUCH_INTERFACE;
  248. }
  249. //
  250. // Reference the interface
  251. //
  252. if (!H323_REFERENCE_INTERFACE(Interfacep)) {
  253. LeaveCriticalSection(&H323InterfaceLock);
  254. NhTrace(
  255. TRACE_FLAG_IF,
  256. "H323ConfigureInterface: interface %d cannot be referenced",
  257. Index
  258. );
  259. return ERROR_INTERFACE_DISABLED;
  260. }
  261. LeaveCriticalSection(&H323InterfaceLock);
  262. Error = NO_ERROR;
  263. ACQUIRE_LOCK(Interfacep);
  264. //
  265. // Compare the interface's current and new configuration
  266. //
  267. OldFlags = Interfacep->Info.Flags;
  268. NewFlags =
  269. (InterfaceInfo
  270. ? (InterfaceInfo->Flags|H323_INTERFACE_FLAG_CONFIGURED) : 0);
  271. Interfacep->Flags &= ~OldFlags;
  272. Interfacep->Flags |= NewFlags;
  273. if (!InterfaceInfo) {
  274. ZeroMemory(&Interfacep->Info, sizeof(*InterfaceInfo));
  275. //
  276. // The interface no longer has any information;
  277. // default to being enabled.
  278. //
  279. if (OldFlags & IP_H323_INTERFACE_FLAG_DISABLED) {
  280. //
  281. // Activate the interface if necessary
  282. //
  283. if (H323_INTERFACE_ACTIVE(Interfacep)) {
  284. RELEASE_LOCK(Interfacep);
  285. Error = H323ActivateInterface(Interfacep);
  286. ACQUIRE_LOCK(Interfacep);
  287. }
  288. }
  289. } else {
  290. CopyMemory(&Interfacep->Info, InterfaceInfo, sizeof(*InterfaceInfo));
  291. //
  292. // Activate or deactivate the interface if its status changed
  293. //
  294. if ((OldFlags & IP_H323_INTERFACE_FLAG_DISABLED) &&
  295. !(NewFlags & IP_H323_INTERFACE_FLAG_DISABLED)) {
  296. //
  297. // Activate the interface
  298. //
  299. if (H323_INTERFACE_ACTIVE(Interfacep)) {
  300. RELEASE_LOCK(Interfacep);
  301. Error = H323ActivateInterface(Interfacep);
  302. ACQUIRE_LOCK(Interfacep);
  303. }
  304. } else if (!(OldFlags & IP_H323_INTERFACE_FLAG_DISABLED) &&
  305. (NewFlags & IP_H323_INTERFACE_FLAG_DISABLED)) {
  306. //
  307. // Deactivate the interface if necessary
  308. //
  309. if (H323_INTERFACE_ACTIVE(Interfacep)) {
  310. RELEASE_LOCK(Interfacep);
  311. H323DeactivateInterface(Interfacep);
  312. ACQUIRE_LOCK(Interfacep);
  313. }
  314. }
  315. }
  316. RELEASE_LOCK(Interfacep);
  317. H323_DEREFERENCE_INTERFACE(Interfacep);
  318. return Error;
  319. } // H323ConfigureInterface
  320. ULONG
  321. H323CreateInterface(
  322. ULONG Index,
  323. NET_INTERFACE_TYPE Type,
  324. PIP_H323_INTERFACE_INFO InterfaceInfo,
  325. OUT PH323_INTERFACE* InterfaceCreated
  326. )
  327. /*++
  328. Routine Description:
  329. This routine is invoked by the router-manager to add a new interface
  330. to the H.323 transparent proxy.
  331. Arguments:
  332. Index - the index of the new interface
  333. Type - the media type of the new interface
  334. InterfaceInfo - the interface's configuration
  335. Interfacep - receives the interface created
  336. Return Value:
  337. ULONG - Win32 error code
  338. Environment:
  339. Invoked internally in the context of an IP router-manager thread.
  340. (See 'RMH323.C').
  341. --*/
  342. {
  343. PLIST_ENTRY InsertionPoint;
  344. PH323_INTERFACE Interfacep;
  345. PROFILE("H323CreateInterface");
  346. EnterCriticalSection(&H323InterfaceLock);
  347. //
  348. // See if the interface already exists;
  349. // If not, this obtains the insertion point
  350. //
  351. if (H323LookupInterface(Index, &InsertionPoint)) {
  352. LeaveCriticalSection(&H323InterfaceLock);
  353. NhTrace(
  354. TRACE_FLAG_IF,
  355. "H323CreateInterface: duplicate index found for %d",
  356. Index
  357. );
  358. return ERROR_INTERFACE_ALREADY_EXISTS;
  359. }
  360. //
  361. // Allocate a new interface
  362. //
  363. Interfacep = reinterpret_cast<PH323_INTERFACE>(
  364. NH_ALLOCATE(sizeof(H323_INTERFACE))
  365. );
  366. if (!Interfacep) {
  367. LeaveCriticalSection(&H323InterfaceLock);
  368. NhTrace(
  369. TRACE_FLAG_IF, "H323CreateInterface: error allocating interface"
  370. );
  371. NhErrorLog(
  372. IP_H323_LOG_ALLOCATION_FAILED,
  373. 0,
  374. "%d",
  375. sizeof(H323_INTERFACE)
  376. );
  377. return ERROR_NOT_ENOUGH_MEMORY;
  378. }
  379. //
  380. // Initialize the new interface
  381. //
  382. ZeroMemory(Interfacep, sizeof(*Interfacep));
  383. __try {
  384. InitializeCriticalSection(&Interfacep->Lock);
  385. } __except(EXCEPTION_EXECUTE_HANDLER) {
  386. LeaveCriticalSection(&H323InterfaceLock);
  387. NH_FREE(Interfacep);
  388. return GetExceptionCode();
  389. }
  390. Interfacep->Index = Index;
  391. Interfacep->Type = Type;
  392. if (InterfaceInfo) {
  393. Interfacep->Flags = InterfaceInfo->Flags|H323_INTERFACE_FLAG_CONFIGURED;
  394. CopyMemory(&Interfacep->Info, InterfaceInfo, sizeof(*InterfaceInfo));
  395. }
  396. Interfacep->ReferenceCount = 1;
  397. InsertTailList(InsertionPoint, &Interfacep->Link);
  398. LeaveCriticalSection(&H323InterfaceLock);
  399. if (InterfaceCreated) { *InterfaceCreated = Interfacep; }
  400. return NO_ERROR;
  401. } // H323CreateInterface
  402. VOID
  403. H323DeactivateInterface(
  404. PH323_INTERFACE Interfacep
  405. )
  406. /*++
  407. Routine Description:
  408. This routine is called to deactivate an interface.
  409. It closes all sockets on the interface's bindings (if any).
  410. Arguments:
  411. Interfacep - the interface to be deactivated
  412. Return Value:
  413. none.
  414. Environment:
  415. Always invoked locally, with 'Interfacep' referenced by caller and/or
  416. 'H323InterfaceLock' held by caller.
  417. --*/
  418. {
  419. ULONG i;
  420. PLIST_ENTRY Link;
  421. PROFILE("H323DeactivateInterface");
  422. ACQUIRE_LOCK(Interfacep);
  423. // TODO: Call h323ics!DeactivateInterface
  424. H323ProxyDeactivateInterface(Interfacep->Index);
  425. RELEASE_LOCK(Interfacep);
  426. } // H323DeactivateInterface
  427. ULONG
  428. H323DeleteInterface(
  429. ULONG Index
  430. )
  431. /*++
  432. Routine Description:
  433. This routine is called to delete an interface.
  434. It drops the reference count on the interface so that the last
  435. dereferencer will delete the interface, and sets the 'deleted' flag
  436. so that further references to the interface will fail.
  437. Arguments:
  438. Index - the index of the interface to be deleted
  439. Return Value:
  440. ULONG - Win32 status code.
  441. Environment:
  442. Invoked internally in the context of an IP router-manager thread.
  443. (See 'RMH323.C').
  444. --*/
  445. {
  446. PH323_INTERFACE Interfacep;
  447. PROFILE("H323DeleteInterface");
  448. //
  449. // Retrieve the interface to be deleted
  450. //
  451. EnterCriticalSection(&H323InterfaceLock);
  452. if (!(Interfacep = H323LookupInterface(Index, NULL))) {
  453. LeaveCriticalSection(&H323InterfaceLock);
  454. NhTrace(
  455. TRACE_FLAG_IF,
  456. "H323DeleteInterface: interface %d not found",
  457. Index
  458. );
  459. return ERROR_NO_SUCH_INTERFACE;
  460. }
  461. //
  462. // Deactivate the interface
  463. //
  464. if (H323_INTERFACE_ACTIVE(Interfacep)) {
  465. H323DeactivateInterface(Interfacep);
  466. }
  467. //
  468. // Mark the interface as deleted and take it off the interface list
  469. //
  470. Interfacep->Flags |= H323_INTERFACE_FLAG_DELETED;
  471. Interfacep->Flags &= ~H323_INTERFACE_FLAG_ENABLED;
  472. RemoveEntryList(&Interfacep->Link);
  473. //
  474. // Drop the reference count; if it is non-zero,
  475. // the deletion will complete later.
  476. //
  477. if (--Interfacep->ReferenceCount) {
  478. LeaveCriticalSection(&H323InterfaceLock);
  479. NhTrace(
  480. TRACE_FLAG_IF,
  481. "H323DeleteInterface: interface %d deletion pending",
  482. Index
  483. );
  484. return NO_ERROR;
  485. }
  486. //
  487. // The reference count is zero, so perform final cleanup
  488. //
  489. H323CleanupInterface(Interfacep);
  490. LeaveCriticalSection(&H323InterfaceLock);
  491. return NO_ERROR;
  492. } // H323DeleteInterface
  493. ULONG
  494. H323DisableInterface(
  495. ULONG Index
  496. )
  497. /*++
  498. Routine Description:
  499. This routine is called to disable I/O on an interface.
  500. If the interface is active, it is deactivated.
  501. Arguments:
  502. Index - the index of the interface to be disabled.
  503. Return Value:
  504. none.
  505. Environment:
  506. Invoked internally in the context of an IP router-manager thread.
  507. (See 'RMH323.C').
  508. --*/
  509. {
  510. PH323_INTERFACE Interfacep;
  511. PROFILE("H323DisableInterface");
  512. //
  513. // Retrieve the interface to be disabled
  514. //
  515. EnterCriticalSection(&H323InterfaceLock);
  516. if (!(Interfacep = H323LookupInterface(Index, NULL))) {
  517. LeaveCriticalSection(&H323InterfaceLock);
  518. NhTrace(
  519. TRACE_FLAG_IF,
  520. "H323DisableInterface: interface %d not found",
  521. Index
  522. );
  523. return ERROR_NO_SUCH_INTERFACE;
  524. }
  525. //
  526. // Make sure the interface is not already disabled
  527. //
  528. if (!H323_INTERFACE_ENABLED(Interfacep)) {
  529. LeaveCriticalSection(&H323InterfaceLock);
  530. NhTrace(
  531. TRACE_FLAG_IF,
  532. "H323DisableInterface: interface %d already disabled",
  533. Index
  534. );
  535. return ERROR_INTERFACE_DISABLED;
  536. }
  537. //
  538. // Reference the interface
  539. //
  540. if (!H323_REFERENCE_INTERFACE(Interfacep)) {
  541. LeaveCriticalSection(&H323InterfaceLock);
  542. NhTrace(
  543. TRACE_FLAG_IF,
  544. "H323DisableInterface: interface %d cannot be referenced",
  545. Index
  546. );
  547. return ERROR_INTERFACE_DISABLED;
  548. }
  549. //
  550. // Clear the 'enabled' flag
  551. //
  552. Interfacep->Flags &= ~H323_INTERFACE_FLAG_ENABLED;
  553. //
  554. // Deactivate the interface, if necessary
  555. //
  556. if (H323_INTERFACE_BOUND(Interfacep)) {
  557. H323DeactivateInterface(Interfacep);
  558. }
  559. LeaveCriticalSection(&H323InterfaceLock);
  560. H323_DEREFERENCE_INTERFACE(Interfacep);
  561. return NO_ERROR;
  562. } // H323DisableInterface
  563. ULONG
  564. H323EnableInterface(
  565. ULONG Index
  566. )
  567. /*++
  568. Routine Description:
  569. This routine is called to enable I/O on an interface.
  570. If the interface is already bound, this enabling activates it.
  571. Arguments:
  572. Index - the index of the interfaec to be enabled
  573. Return Value:
  574. ULONG - Win32 status code.
  575. Environment:
  576. Invoked internally in the context of an IP router-manager thread.
  577. (See 'RMH323.C').
  578. --*/
  579. {
  580. ULONG Error = NO_ERROR;
  581. PH323_INTERFACE Interfacep;
  582. PROFILE("H323EnableInterface");
  583. //
  584. // Retrieve the interface to be enabled
  585. //
  586. EnterCriticalSection(&H323InterfaceLock);
  587. if (!(Interfacep = H323LookupInterface(Index, NULL))) {
  588. LeaveCriticalSection(&H323InterfaceLock);
  589. NhTrace(
  590. TRACE_FLAG_IF,
  591. "H323EnableInterface: interface %d not found",
  592. Index
  593. );
  594. return ERROR_NO_SUCH_INTERFACE;
  595. }
  596. //
  597. // Make sure the interface is not already enabled
  598. //
  599. if (H323_INTERFACE_ENABLED(Interfacep)) {
  600. LeaveCriticalSection(&H323InterfaceLock);
  601. NhTrace(
  602. TRACE_FLAG_IF,
  603. "H323EnableInterface: interface %d already enabled",
  604. Index
  605. );
  606. return ERROR_INTERFACE_ALREADY_EXISTS;
  607. }
  608. //
  609. // Reference the interface
  610. //
  611. if (!H323_REFERENCE_INTERFACE(Interfacep)) {
  612. LeaveCriticalSection(&H323InterfaceLock);
  613. NhTrace(
  614. TRACE_FLAG_IF,
  615. "H323EnableInterface: interface %d cannot be referenced",
  616. Index
  617. );
  618. return ERROR_INTERFACE_DISABLED;
  619. }
  620. //
  621. // Set the 'enabled' flag
  622. //
  623. Interfacep->Flags |= H323_INTERFACE_FLAG_ENABLED;
  624. //
  625. // Activate the interface, if necessary
  626. //
  627. if (H323_INTERFACE_ACTIVE(Interfacep)) {
  628. Error = H323ActivateInterface(Interfacep);
  629. }
  630. LeaveCriticalSection(&H323InterfaceLock);
  631. H323_DEREFERENCE_INTERFACE(Interfacep);
  632. return Error;
  633. } // H323EnableInterface
  634. ULONG
  635. H323InitializeInterfaceManagement(
  636. VOID
  637. )
  638. /*++
  639. Routine Description:
  640. This routine is called to initialize the interface-management module.
  641. Arguments:
  642. none.
  643. Return Value:
  644. ULONG - Win32 status code.
  645. Environment:
  646. Invoked internally in the context of an IP router-manager thread.
  647. (See 'RMH323.C').
  648. --*/
  649. {
  650. ULONG Error = NO_ERROR;
  651. PROFILE("H323InitializeInterfaceManagement");
  652. InitializeListHead(&H323InterfaceList);
  653. __try {
  654. InitializeCriticalSection(&H323InterfaceLock);
  655. } __except(EXCEPTION_EXECUTE_HANDLER) {
  656. NhTrace(
  657. TRACE_FLAG_IF,
  658. "H323InitializeInterfaceManagement: exception %d creating lock",
  659. Error = GetExceptionCode()
  660. );
  661. }
  662. return Error;
  663. } // H323InitializeInterfaceManagement
  664. PH323_INTERFACE
  665. H323LookupInterface(
  666. ULONG Index,
  667. OUT PLIST_ENTRY* InsertionPoint OPTIONAL
  668. )
  669. /*++
  670. Routine Description:
  671. This routine is called to retrieve an interface given its index.
  672. Arguments:
  673. Index - the index of the interface to be retrieved
  674. InsertionPoint - if the interface is not found, optionally receives
  675. the point where the interface would be inserted in the interface list
  676. Return Value:
  677. PH323_INTERFACE - the interface, if found; otherwise, NULL.
  678. Environment:
  679. Invoked internally from an arbitrary context, with 'H323InterfaceLock'
  680. held by caller.
  681. --*/
  682. {
  683. PH323_INTERFACE Interfacep;
  684. PLIST_ENTRY Link;
  685. PROFILE("H323LookupInterface");
  686. for (Link = H323InterfaceList.Flink; Link != &H323InterfaceList;
  687. Link = Link->Flink) {
  688. Interfacep = CONTAINING_RECORD(Link, H323_INTERFACE, Link);
  689. if (Index > Interfacep->Index) {
  690. continue;
  691. } else if (Index < Interfacep->Index) {
  692. break;
  693. }
  694. return Interfacep;
  695. }
  696. if (InsertionPoint) { *InsertionPoint = Link; }
  697. return NULL;
  698. } // H323LookupInterface
  699. ULONG
  700. H323QueryInterface(
  701. ULONG Index,
  702. PVOID InterfaceInfo,
  703. PULONG InterfaceInfoSize
  704. )
  705. /*++
  706. Routine Description:
  707. This routine is invoked to retrieve the configuration for an interface.
  708. Arguments:
  709. Index - the interface to be queried
  710. InterfaceInfo - receives the retrieved information
  711. InterfaceInfoSize - receives the (required) size of the information
  712. Return Value:
  713. ULONG - Win32 status code.
  714. --*/
  715. {
  716. PH323_INTERFACE Interfacep;
  717. PROFILE("H323QueryInterface");
  718. //
  719. // Check the caller's buffer size
  720. //
  721. if (!InterfaceInfoSize) { return ERROR_INVALID_PARAMETER; }
  722. //
  723. // Retrieve the interface to be configured
  724. //
  725. EnterCriticalSection(&H323InterfaceLock);
  726. if (!(Interfacep = H323LookupInterface(Index, NULL))) {
  727. LeaveCriticalSection(&H323InterfaceLock);
  728. NhTrace(
  729. TRACE_FLAG_IF,
  730. "H323QueryInterface: interface %d not found",
  731. Index
  732. );
  733. return ERROR_NO_SUCH_INTERFACE;
  734. }
  735. //
  736. // Reference the interface
  737. //
  738. if (!H323_REFERENCE_INTERFACE(Interfacep)) {
  739. LeaveCriticalSection(&H323InterfaceLock);
  740. NhTrace(
  741. TRACE_FLAG_IF,
  742. "H323QueryInterface: interface %d cannot be referenced",
  743. Index
  744. );
  745. return ERROR_INTERFACE_DISABLED;
  746. }
  747. //
  748. // See if there is any explicit config on this interface
  749. //
  750. if (!H323_INTERFACE_CONFIGURED(Interfacep)) {
  751. LeaveCriticalSection(&H323InterfaceLock);
  752. H323_DEREFERENCE_INTERFACE(Interfacep);
  753. NhTrace(
  754. TRACE_FLAG_IF,
  755. "H323QueryInterface: interface %d has no configuration",
  756. Index
  757. );
  758. *InterfaceInfoSize = 0;
  759. return NO_ERROR;
  760. }
  761. //
  762. // See if there is enough buffer space
  763. //
  764. if (*InterfaceInfoSize < sizeof(IP_H323_INTERFACE_INFO)) {
  765. LeaveCriticalSection(&H323InterfaceLock);
  766. H323_DEREFERENCE_INTERFACE(Interfacep);
  767. *InterfaceInfoSize = sizeof(IP_H323_INTERFACE_INFO);
  768. return ERROR_INSUFFICIENT_BUFFER;
  769. }
  770. //
  771. // Copy the requested data
  772. //
  773. CopyMemory(
  774. InterfaceInfo,
  775. &Interfacep->Info,
  776. sizeof(IP_H323_INTERFACE_INFO)
  777. );
  778. *InterfaceInfoSize = sizeof(IP_H323_INTERFACE_INFO);
  779. LeaveCriticalSection(&H323InterfaceLock);
  780. H323_DEREFERENCE_INTERFACE(Interfacep);
  781. return NO_ERROR;
  782. } // H323QueryInterface
  783. VOID
  784. H323ShutdownInterfaceManagement(
  785. VOID
  786. )
  787. /*++
  788. Routine Description:
  789. This routine is called to shutdown the interface-management module.
  790. Arguments:
  791. none.
  792. Return Value:
  793. none.
  794. Environment:
  795. Invoked in an arbitrary thread context, after all references
  796. to all interfaces have been released.
  797. --*/
  798. {
  799. PH323_INTERFACE Interfacep;
  800. PLIST_ENTRY Link;
  801. PROFILE("H323ShutdownInterfaceManagement");
  802. while (!IsListEmpty(&H323InterfaceList)) {
  803. Link = RemoveHeadList(&H323InterfaceList);
  804. Interfacep = CONTAINING_RECORD(Link, H323_INTERFACE, Link);
  805. if (H323_INTERFACE_ACTIVE(Interfacep)) {
  806. H323DeactivateInterface(Interfacep);
  807. }
  808. H323CleanupInterface(Interfacep);
  809. }
  810. DeleteCriticalSection(&H323InterfaceLock);
  811. } // H323ShutdownInterfaceManagement
  812. VOID
  813. H323SignalNatInterface(
  814. ULONG Index,
  815. BOOLEAN Boundary
  816. )
  817. /*++
  818. Routine Description:
  819. This routine is invoked upon reconfiguration of a NAT interface.
  820. Note that this routine may be invoked even when the H.323
  821. transparent proxy is neither installed nor running; it operates as expected,
  822. since the global information and lock are always initialized.
  823. Upon invocation, the routine activates or deactivates the interface
  824. depending on whether the NAT is not or is running on the interface,
  825. respectively.
  826. Arguments:
  827. Index - the reconfigured interface
  828. Boundary - indicates whether the interface is now a boundary interface
  829. Return Value:
  830. none.
  831. Environment:
  832. Invoked from an arbitrary context.
  833. --*/
  834. {
  835. PH323_INTERFACE Interfacep;
  836. PROFILE("H323SignalNatInterface");
  837. EnterCriticalSection(&H323GlobalInfoLock);
  838. if (!H323GlobalInfo) {
  839. LeaveCriticalSection(&H323GlobalInfoLock);
  840. return;
  841. }
  842. LeaveCriticalSection(&H323GlobalInfoLock);
  843. EnterCriticalSection(&H323InterfaceLock);
  844. if (!(Interfacep = H323LookupInterface(Index, NULL))) {
  845. LeaveCriticalSection(&H323InterfaceLock);
  846. return;
  847. }
  848. if (H323_INTERFACE_ACTIVE(Interfacep)) {
  849. H323DeactivateInterface(Interfacep);
  850. H323ActivateInterface(Interfacep);
  851. }
  852. LeaveCriticalSection(&H323InterfaceLock);
  853. } // H323SignalNatInterface
  854. ULONG
  855. H323UnbindInterface(
  856. ULONG Index
  857. )
  858. /*++
  859. Routine Description:
  860. This routine is invoked to revoke the binding on an interface.
  861. This involves deactivating the interface if it is active.
  862. Arguments:
  863. Index - the index of the interface to be unbound
  864. Return Value:
  865. none.
  866. Environment:
  867. Invoked internally in the context of an IP router-manager thread.
  868. (See 'RMH323.C').
  869. --*/
  870. {
  871. PH323_INTERFACE Interfacep;
  872. PROFILE("H323UnbindInterface");
  873. //
  874. // Retrieve the interface to be unbound
  875. //
  876. EnterCriticalSection(&H323InterfaceLock);
  877. if (!(Interfacep = H323LookupInterface(Index, NULL))) {
  878. LeaveCriticalSection(&H323InterfaceLock);
  879. NhTrace(
  880. TRACE_FLAG_IF,
  881. "H323UnbindInterface: interface %d not found",
  882. Index
  883. );
  884. return ERROR_NO_SUCH_INTERFACE;
  885. }
  886. //
  887. // Make sure the interface is not already unbound
  888. //
  889. if (!H323_INTERFACE_BOUND(Interfacep)) {
  890. LeaveCriticalSection(&H323InterfaceLock);
  891. NhTrace(
  892. TRACE_FLAG_IF,
  893. "H323UnbindInterface: interface %d already unbound",
  894. Index
  895. );
  896. return ERROR_ADDRESS_NOT_ASSOCIATED;
  897. }
  898. //
  899. // Reference the interface
  900. //
  901. if (!H323_REFERENCE_INTERFACE(Interfacep)) {
  902. LeaveCriticalSection(&H323InterfaceLock);
  903. NhTrace(
  904. TRACE_FLAG_IF,
  905. "H323UnbindInterface: interface %d cannot be referenced",
  906. Index
  907. );
  908. return ERROR_INTERFACE_DISABLED;
  909. }
  910. //
  911. // Clear the 'bound' flag
  912. //
  913. Interfacep->Flags &= ~H323_INTERFACE_FLAG_BOUND;
  914. //
  915. // Deactivate the interface, if necessary
  916. //
  917. if (H323_INTERFACE_ENABLED(Interfacep)) {
  918. H323DeactivateInterface(Interfacep);
  919. }
  920. LeaveCriticalSection(&H323InterfaceLock);
  921. //
  922. // Destroy the interface's binding
  923. //
  924. ACQUIRE_LOCK(Interfacep);
  925. NH_FREE(Interfacep->BindingInfo);
  926. Interfacep->BindingInfo = NULL;
  927. RELEASE_LOCK(Interfacep);
  928. H323_DEREFERENCE_INTERFACE(Interfacep);
  929. return NO_ERROR;
  930. } // H323UnbindInterface