Leaked source code of windows server 2003
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.

1498 lines
34 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. AlgIF.c
  5. Abstract:
  6. This module contains code for the ALG transparent proxy's interface
  7. management.
  8. Author:
  9. Qiang Wang (qiangw) 10-April-2000
  10. Revision History:
  11. Savasg 22-Aug-2001 Added RRAS Support
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include <ipnatapi.h>
  16. #include <atlbase.h>
  17. #include <MyTrace.h>
  18. extern HRESULT
  19. GetAlgControllerInterface(
  20. IAlgController** ppAlgController
  21. );
  22. //
  23. // GLOBAL DATA DEFINITIONS
  24. //
  25. LIST_ENTRY AlgInterfaceList;
  26. CRITICAL_SECTION AlgInterfaceLock;
  27. ULONG AlgFirewallIfCount;
  28. ULONG
  29. AlgBindInterface(
  30. ULONG Index,
  31. PIP_ADAPTER_BINDING_INFO BindingInfo
  32. )
  33. /*++
  34. Routine Description:
  35. This routine is invoked to supply the binding for an interface.
  36. It records the binding information received, and if necessary,
  37. it activates the interface.
  38. Arguments:
  39. Index - the index of the interface to be bound
  40. BindingInfo - the binding-information for the interface
  41. Return Value:
  42. ULONG - Win32 status code.
  43. Notes:
  44. Invoked internally in the context of an IP router-manager thread.
  45. (See 'RMALG.C').
  46. --*/
  47. {
  48. ULONG i;
  49. ULONG Error = NO_ERROR;
  50. PALG_INTERFACE Interfacep;
  51. PROFILE("AlgBindInterface");
  52. EnterCriticalSection(&AlgInterfaceLock);
  53. //
  54. // Retrieve the interface to be bound
  55. //
  56. Interfacep = AlgLookupInterface(Index, NULL);
  57. if (Interfacep == NULL)
  58. {
  59. LeaveCriticalSection(&AlgInterfaceLock);
  60. NhTrace(
  61. TRACE_FLAG_IF,
  62. "AlgBindInterface: interface %d not found",
  63. Index
  64. );
  65. return ERROR_NO_SUCH_INTERFACE;
  66. }
  67. //
  68. // Make sure the interface isn't already bound
  69. //
  70. if (ALG_INTERFACE_BOUND(Interfacep))
  71. {
  72. LeaveCriticalSection(&AlgInterfaceLock);
  73. NhTrace(
  74. TRACE_FLAG_IF,
  75. "AlgBindInterface: interface %d is already bound",
  76. Index
  77. );
  78. return ERROR_ADDRESS_ALREADY_ASSOCIATED;
  79. }
  80. //
  81. // Reference the interface
  82. //
  83. if (!ALG_REFERENCE_INTERFACE(Interfacep))
  84. {
  85. LeaveCriticalSection(&AlgInterfaceLock);
  86. NhTrace(
  87. TRACE_FLAG_IF,
  88. "AlgBindInterface: interface %d cannot be referenced",
  89. Index
  90. );
  91. return ERROR_INTERFACE_DISABLED;
  92. }
  93. //
  94. // Update the interface's flags
  95. //
  96. Interfacep->Flags |= ALG_INTERFACE_FLAG_BOUND;
  97. LeaveCriticalSection(&AlgInterfaceLock);
  98. ACQUIRE_LOCK(Interfacep);
  99. //
  100. // Allocate space for the binding
  101. //
  102. if (!BindingInfo->AddressCount)
  103. {
  104. Interfacep->BindingCount = 0;
  105. Interfacep->BindingArray = NULL;
  106. } else
  107. {
  108. Interfacep->BindingArray =
  109. reinterpret_cast<PALG_BINDING>(
  110. NH_ALLOCATE(BindingInfo->AddressCount * sizeof(ALG_BINDING))
  111. );
  112. if (!Interfacep->BindingArray)
  113. {
  114. RELEASE_LOCK(Interfacep);
  115. ALG_DEREFERENCE_INTERFACE(Interfacep);
  116. NhTrace(
  117. TRACE_FLAG_IF,
  118. "AlgBindInterface: allocation failed for interface %d binding",
  119. Index
  120. );
  121. NhErrorLog(
  122. IP_ALG_LOG_ALLOCATION_FAILED,
  123. 0,
  124. "%d",
  125. BindingInfo->AddressCount * sizeof(ALG_BINDING)
  126. );
  127. return ERROR_NOT_ENOUGH_MEMORY;
  128. }
  129. ZeroMemory(
  130. Interfacep->BindingArray,
  131. BindingInfo->AddressCount * sizeof(ALG_BINDING)
  132. );
  133. Interfacep->BindingCount = BindingInfo->AddressCount;
  134. }
  135. //
  136. // Copy the binding
  137. //
  138. for (i = 0; i < BindingInfo->AddressCount; i++)
  139. {
  140. Interfacep->BindingArray[i].Address = BindingInfo->Address[i].Address;
  141. Interfacep->BindingArray[i].Mask = BindingInfo->Address[i].Mask;
  142. Interfacep->BindingArray[i].ListeningSocket = INVALID_SOCKET;
  143. }
  144. //
  145. // Figure out our IP Adapter Index, if we have a valid binding
  146. //
  147. if (Interfacep->BindingCount)
  148. {
  149. Interfacep->AdapterIndex =
  150. NhMapAddressToAdapter(BindingInfo->Address[0].Address);
  151. }
  152. if (ALG_INTERFACE_ACTIVE( Interfacep ))
  153. {
  154. Error = AlgActivateInterface( Interfacep );
  155. }
  156. RELEASE_LOCK(Interfacep);
  157. ALG_DEREFERENCE_INTERFACE(Interfacep);
  158. return Error;
  159. } // AlgBindInterface
  160. VOID
  161. AlgCleanupInterface(
  162. PALG_INTERFACE Interfacep
  163. )
  164. /*++
  165. Routine Description:
  166. This routine is invoked when the very last reference to an interface
  167. is released, and the interface must be destroyed.
  168. Arguments:
  169. Interfacep - the interface to be destroyed
  170. Return Value:
  171. none.
  172. Notes:
  173. Invoked internally from an arbitrary context, with no references
  174. to the interface.
  175. --*/
  176. {
  177. PROFILE("AlgCleanupInterface");
  178. if (Interfacep->BindingArray)
  179. {
  180. NH_FREE(Interfacep->BindingArray);
  181. Interfacep->BindingArray = NULL;
  182. }
  183. DeleteCriticalSection(&Interfacep->Lock);
  184. NH_FREE(Interfacep);
  185. } // AlgCleanupInterface
  186. ULONG
  187. AlgConfigureInterface(
  188. ULONG Index,
  189. PIP_ALG_INTERFACE_INFO InterfaceInfo
  190. )
  191. /*++
  192. Routine Description:
  193. This routine is called to set the configuration for an interface.
  194. Since we're tracking the interfaces as is, not for any other purpose,
  195. we're not enabling/disabling and/or activating them like the other modules
  196. do.
  197. Arguments:
  198. Index - the interface to be configured
  199. InterfaceInfo - the new configuration
  200. Return Value:
  201. ULONG - Win32 status code
  202. Notes:
  203. Invoked internally in the context of a IP router-manager thread.
  204. (See 'RMALG.C').
  205. --*/
  206. {
  207. ULONG Error;
  208. PALG_INTERFACE Interfacep;
  209. ULONG NewFlags;
  210. ULONG OldFlags;
  211. PROFILE("AlgConfigureInterface");
  212. //
  213. // Retrieve the interface to be configured
  214. //
  215. EnterCriticalSection(&AlgInterfaceLock);
  216. Interfacep = AlgLookupInterface(Index, NULL);
  217. if (Interfacep == NULL)
  218. {
  219. LeaveCriticalSection(&AlgInterfaceLock);
  220. NhTrace(
  221. TRACE_FLAG_IF,
  222. "AlgConfigureInterface: interface %d not found",
  223. Index
  224. );
  225. return ERROR_NO_SUCH_INTERFACE;
  226. }
  227. //
  228. // Reference the interface
  229. //
  230. if (!ALG_REFERENCE_INTERFACE(Interfacep))
  231. {
  232. LeaveCriticalSection(&AlgInterfaceLock);
  233. NhTrace(
  234. TRACE_FLAG_IF,
  235. "AlgConfigureInterface: interface %d cannot be referenced",
  236. Index
  237. );
  238. return ERROR_INTERFACE_DISABLED;
  239. }
  240. LeaveCriticalSection(&AlgInterfaceLock);
  241. Error = NO_ERROR;
  242. ACQUIRE_LOCK(Interfacep);
  243. //
  244. // Compare the interface's current and new configuration
  245. //
  246. OldFlags = Interfacep->Info.Flags;
  247. NewFlags = (InterfaceInfo ?
  248. (InterfaceInfo->Flags|ALG_INTERFACE_FLAG_CONFIGURED) :
  249. 0);
  250. Interfacep->Flags &= ~OldFlags;
  251. Interfacep->Flags |= NewFlags;
  252. if (!InterfaceInfo)
  253. {
  254. ZeroMemory(&Interfacep->Info, sizeof(*InterfaceInfo));
  255. //
  256. // The interface no longer has any information;
  257. // default to being enabled...
  258. //
  259. if ( OldFlags & IP_ALG_INTERFACE_FLAG_DISABLED )
  260. {
  261. //
  262. // Activate the interface if necessary.
  263. //
  264. if ( ALG_INTERFACE_ACTIVE( Interfacep ) )
  265. {
  266. RELEASE_LOCK( Interfacep );
  267. Error = AlgActivateInterface( Interfacep );
  268. ACQUIRE_LOCK( Interfacep );
  269. }
  270. }
  271. }
  272. else
  273. {
  274. CopyMemory(&Interfacep->Info, InterfaceInfo, sizeof(*InterfaceInfo));
  275. //
  276. // Activate or deactivate the interface if its status changed
  277. //
  278. if (( OldFlags & IP_ALG_INTERFACE_FLAG_DISABLED) &&
  279. !(NewFlags & IP_ALG_INTERFACE_FLAG_DISABLED)
  280. )
  281. {
  282. //
  283. // Activate the interface
  284. //
  285. if (ALG_INTERFACE_ACTIVE(Interfacep))
  286. {
  287. RELEASE_LOCK(Interfacep);
  288. Error = AlgActivateInterface(Interfacep);
  289. ACQUIRE_LOCK(Interfacep);
  290. }
  291. }
  292. else if (!(OldFlags & IP_ALG_INTERFACE_FLAG_DISABLED) &&
  293. (NewFlags & IP_ALG_INTERFACE_FLAG_DISABLED)
  294. )
  295. {
  296. //
  297. // Deactivate the interface if necessary
  298. //
  299. if (ALG_INTERFACE_ACTIVE(Interfacep))
  300. {
  301. AlgDeactivateInterface(Interfacep);
  302. }
  303. }
  304. }
  305. RELEASE_LOCK(Interfacep);
  306. ALG_DEREFERENCE_INTERFACE(Interfacep);
  307. return Error;
  308. } // AlgConfigureInterface
  309. ULONG
  310. AlgCreateInterface(
  311. ULONG Index,
  312. NET_INTERFACE_TYPE Type,
  313. PIP_ALG_INTERFACE_INFO InterfaceInfo,
  314. OUT PALG_INTERFACE* InterfaceCreated
  315. )
  316. /*++
  317. Routine Description:
  318. This routine is invoked by the router-manager to add a new interface
  319. to the ALG transparent proxy.
  320. Arguments:
  321. Index - the index of the new interface
  322. Type - the media type of the new interface
  323. InterfaceInfo - the interface's configuration
  324. Interfacep - receives the interface created
  325. Return Value:
  326. ULONG - Win32 error code
  327. Notes:
  328. Invoked internally in the context of an IP router-manager thread.
  329. (See 'RMALG.C').
  330. --*/
  331. {
  332. PLIST_ENTRY InsertionPoint;
  333. PALG_INTERFACE Interfacep;
  334. PROFILE("AlgCreateInterface");
  335. EnterCriticalSection(&AlgInterfaceLock);
  336. //
  337. // See if the interface already exists;
  338. // If not, this obtains the insertion point
  339. //
  340. if (AlgLookupInterface(Index, &InsertionPoint))
  341. {
  342. LeaveCriticalSection(&AlgInterfaceLock);
  343. NhTrace(
  344. TRACE_FLAG_IF,
  345. "AlgCreateInterface: duplicate index found for %d",
  346. Index
  347. );
  348. return ERROR_INTERFACE_ALREADY_EXISTS;
  349. }
  350. //
  351. // Allocate a new interface
  352. //
  353. Interfacep =
  354. reinterpret_cast<PALG_INTERFACE>(NH_ALLOCATE(sizeof(ALG_INTERFACE)));
  355. if (!Interfacep)
  356. {
  357. LeaveCriticalSection(&AlgInterfaceLock);
  358. NhTrace(
  359. TRACE_FLAG_IF, "AlgCreateInterface: error allocating interface"
  360. );
  361. NhErrorLog(
  362. IP_ALG_LOG_ALLOCATION_FAILED,
  363. 0,
  364. "%d",
  365. sizeof(ALG_INTERFACE)
  366. );
  367. return ERROR_NOT_ENOUGH_MEMORY;
  368. }
  369. //
  370. // Initialize the new interface
  371. //
  372. ZeroMemory(Interfacep, sizeof(*Interfacep));
  373. __try {
  374. InitializeCriticalSection(&Interfacep->Lock);
  375. } __except(EXCEPTION_EXECUTE_HANDLER)
  376. {
  377. LeaveCriticalSection(&AlgInterfaceLock);
  378. NH_FREE(Interfacep);
  379. return GetExceptionCode();
  380. }
  381. Interfacep->Index = Index;
  382. Interfacep->Type = Type;
  383. if (InterfaceInfo)
  384. {
  385. Interfacep->Flags = InterfaceInfo->Flags|ALG_INTERFACE_FLAG_CONFIGURED;
  386. CopyMemory(&Interfacep->Info, InterfaceInfo, sizeof(*InterfaceInfo));
  387. }
  388. Interfacep->ReferenceCount = 1;
  389. InitializeListHead(&Interfacep->ConnectionList);
  390. InitializeListHead(&Interfacep->EndpointList);
  391. InsertTailList(InsertionPoint, &Interfacep->Link);
  392. LeaveCriticalSection(&AlgInterfaceLock);
  393. if (InterfaceCreated)
  394. {
  395. *InterfaceCreated = Interfacep;
  396. }
  397. return NO_ERROR;
  398. } // AlgCreateInterface
  399. ULONG
  400. AlgDeleteInterface(
  401. ULONG Index
  402. )
  403. /*++
  404. Routine Description:
  405. This routine is called to delete an interface.
  406. It drops the reference count on the interface so that the last
  407. dereferencer will delete the interface, and sets the 'deleted' flag
  408. so that further references to the interface will fail.
  409. Arguments:
  410. Index - the index of the interface to be deleted
  411. Return Value:
  412. ULONG - Win32 status code.
  413. Notes:
  414. Invoked internally in the context of an IP router-manager thread.
  415. (See 'RMALG.C').
  416. --*/
  417. {
  418. PALG_INTERFACE Interfacep;
  419. PROFILE("AlgDeleteInterface");
  420. //
  421. // Retrieve the interface to be deleted
  422. //
  423. EnterCriticalSection(&AlgInterfaceLock);
  424. Interfacep = AlgLookupInterface(Index, NULL);
  425. if (Interfacep == NULL)
  426. {
  427. LeaveCriticalSection(&AlgInterfaceLock);
  428. NhTrace(
  429. TRACE_FLAG_IF,
  430. "AlgDeleteInterface: interface %d not found",
  431. Index
  432. );
  433. return ERROR_NO_SUCH_INTERFACE;
  434. }
  435. //
  436. // Mark the interface as deleted and take it off the interface list
  437. //
  438. Interfacep->Flags |= ALG_INTERFACE_FLAG_DELETED;
  439. Interfacep->Flags &= ~ALG_INTERFACE_FLAG_ENABLED;
  440. RemoveEntryList(&Interfacep->Link);
  441. //
  442. // Deactivate the Interface
  443. //
  444. AlgDeactivateInterface( Interfacep );
  445. //
  446. // Drop the reference count; if it is non-zero,
  447. // the deletion will complete later.
  448. //
  449. if (--Interfacep->ReferenceCount)
  450. {
  451. LeaveCriticalSection(&AlgInterfaceLock);
  452. NhTrace(
  453. TRACE_FLAG_IF,
  454. "AlgDeleteInterface: interface %d deletion pending",
  455. Index
  456. );
  457. return NO_ERROR;
  458. }
  459. //
  460. // The reference count is zero, so perform final cleanup
  461. //
  462. AlgCleanupInterface(Interfacep);
  463. LeaveCriticalSection(&AlgInterfaceLock);
  464. return NO_ERROR;
  465. } // AlgDeleteInterface
  466. ULONG
  467. AlgDisableInterface(
  468. ULONG Index
  469. )
  470. /*++
  471. Routine Description:
  472. This routine is called to disable I/O on an interface.
  473. If the interface is active, it is deactivated.
  474. Arguments:
  475. Index - the index of the interface to be disabled.
  476. Return Value:
  477. none.
  478. Notes:
  479. Invoked internally in the context of an IP router-manager thread.
  480. (See 'RMALG.C').
  481. --*/
  482. {
  483. PALG_INTERFACE Interfacep;
  484. PROFILE("AlgDisableInterface");
  485. //
  486. // Retrieve the interface to be disabled
  487. //
  488. EnterCriticalSection(&AlgInterfaceLock);
  489. Interfacep = AlgLookupInterface(Index, NULL);
  490. if (Interfacep == NULL)
  491. {
  492. LeaveCriticalSection(&AlgInterfaceLock);
  493. NhTrace(
  494. TRACE_FLAG_IF,
  495. "AlgDisableInterface: interface %d not found",
  496. Index
  497. );
  498. return ERROR_NO_SUCH_INTERFACE;
  499. }
  500. //
  501. // Make sure the interface is not already disabled
  502. //
  503. if (!ALG_INTERFACE_ENABLED(Interfacep))
  504. {
  505. LeaveCriticalSection(&AlgInterfaceLock);
  506. NhTrace(
  507. TRACE_FLAG_IF,
  508. "AlgDisableInterface: interface %d already disabled",
  509. Index
  510. );
  511. return ERROR_INTERFACE_DISABLED;
  512. }
  513. //
  514. // Reference the interface
  515. //
  516. if (!ALG_REFERENCE_INTERFACE(Interfacep))
  517. {
  518. LeaveCriticalSection(&AlgInterfaceLock);
  519. NhTrace(
  520. TRACE_FLAG_IF,
  521. "AlgDisableInterface: interface %d cannot be referenced",
  522. Index
  523. );
  524. return ERROR_INTERFACE_DISABLED;
  525. }
  526. //
  527. // Clear the 'enabled' flag
  528. //
  529. Interfacep->Flags &= ~ALG_INTERFACE_FLAG_ENABLED;
  530. //
  531. // Deactivate the Interface, if necessary
  532. //
  533. if ( ALG_INTERFACE_BOUND(Interfacep) )
  534. {
  535. AlgDeactivateInterface( Interfacep );
  536. }
  537. LeaveCriticalSection(&AlgInterfaceLock);
  538. ALG_DEREFERENCE_INTERFACE(Interfacep);
  539. return NO_ERROR;
  540. } // AlgDisableInterface
  541. ULONG
  542. AlgEnableInterface(
  543. ULONG Index
  544. )
  545. /*++
  546. Routine Description:
  547. This routine is called to enable I/O on an interface.
  548. If the interface is already bound, this enabling activates it.
  549. Arguments:
  550. Index - the index of the interfaec to be enabled
  551. Return Value:
  552. ULONG - Win32 status code.
  553. Notes:
  554. Invoked internally in the context of an IP router-manager thread.
  555. (See 'RMALG.C').
  556. --*/
  557. {
  558. ULONG Error = NO_ERROR;
  559. PALG_INTERFACE Interfacep;
  560. PROFILE("AlgEnableInterface");
  561. //
  562. // Retrieve the interface to be enabled
  563. //
  564. EnterCriticalSection(&AlgInterfaceLock);
  565. Interfacep = AlgLookupInterface(Index, NULL);
  566. if (Interfacep == NULL)
  567. {
  568. LeaveCriticalSection(&AlgInterfaceLock);
  569. NhTrace(
  570. TRACE_FLAG_IF,
  571. "AlgEnableInterface: interface %d not found",
  572. Index
  573. );
  574. return ERROR_NO_SUCH_INTERFACE;
  575. }
  576. //
  577. // Make sure the interface is not already enabled
  578. //
  579. if (ALG_INTERFACE_ENABLED(Interfacep))
  580. {
  581. LeaveCriticalSection(&AlgInterfaceLock);
  582. NhTrace(
  583. TRACE_FLAG_IF,
  584. "AlgEnableInterface: interface %d already enabled",
  585. Index
  586. );
  587. return ERROR_INTERFACE_ALREADY_EXISTS;
  588. }
  589. //
  590. // Reference the interface
  591. //
  592. if (!ALG_REFERENCE_INTERFACE(Interfacep))
  593. {
  594. LeaveCriticalSection(&AlgInterfaceLock);
  595. NhTrace(
  596. TRACE_FLAG_IF,
  597. "AlgEnableInterface: interface %d cannot be referenced",
  598. Index
  599. );
  600. return ERROR_INTERFACE_DISABLED;
  601. }
  602. //
  603. // Set the 'enabled' flag
  604. //
  605. Interfacep->Flags |= ALG_INTERFACE_FLAG_ENABLED;
  606. //
  607. // Activate the interface, if necessary
  608. //
  609. if ( ALG_INTERFACE_ACTIVE( Interfacep ) )
  610. {
  611. Error = AlgActivateInterface( Interfacep );
  612. }
  613. LeaveCriticalSection(&AlgInterfaceLock);
  614. ALG_DEREFERENCE_INTERFACE(Interfacep);
  615. return Error;
  616. } // AlgEnableInterface
  617. ULONG
  618. AlgInitializeInterfaceManagement(
  619. VOID
  620. )
  621. /*++
  622. Routine Description:
  623. This routine is called to initialize the interface-management module.
  624. Arguments:
  625. none.
  626. Return Value:
  627. ULONG - Win32 status code.
  628. Notes:
  629. Invoked internally in the context of an IP router-manager thread.
  630. (See 'RMALG.C').
  631. --*/
  632. {
  633. ULONG Error = NO_ERROR;
  634. PROFILE("AlgInitializeInterfaceManagement");
  635. InitializeListHead(&AlgInterfaceList);
  636. __try {
  637. InitializeCriticalSection(&AlgInterfaceLock);
  638. } __except(EXCEPTION_EXECUTE_HANDLER)
  639. {
  640. NhTrace(
  641. TRACE_FLAG_IF,
  642. "AlgInitializeInterfaceManagement: exception %d creating lock",
  643. Error = GetExceptionCode()
  644. );
  645. }
  646. AlgFirewallIfCount = 0;
  647. return Error;
  648. } // AlgInitializeInterfaceManagement
  649. PALG_INTERFACE
  650. AlgLookupInterface(
  651. ULONG Index,
  652. OUT PLIST_ENTRY* InsertionPoint OPTIONAL
  653. )
  654. /*++
  655. Routine Description:
  656. This routine is called to retrieve an interface given its index.
  657. Arguments:
  658. Index - the index of the interface to be retrieved
  659. InsertionPoint - if the interface is not found, optionally receives
  660. the point where the interface would be inserted in the interface list
  661. Return Value:
  662. PALG_INTERFACE - the interface, if found; otherwise, NULL.
  663. Notes:
  664. Invoked internally from an arbitrary context, with 'AlgInterfaceLock'
  665. held by caller.
  666. --*/
  667. {
  668. PALG_INTERFACE Interfacep;
  669. PLIST_ENTRY Link;
  670. PROFILE("AlgLookupInterface");
  671. for (Link = AlgInterfaceList.Flink; Link != &AlgInterfaceList;
  672. Link = Link->Flink)
  673. {
  674. Interfacep = CONTAINING_RECORD(Link, ALG_INTERFACE, Link);
  675. if (Index > Interfacep->Index)
  676. {
  677. continue;
  678. } else if (Index < Interfacep->Index)
  679. {
  680. break;
  681. }
  682. return Interfacep;
  683. }
  684. if (InsertionPoint)
  685. {
  686. *InsertionPoint = Link;
  687. }
  688. return NULL;
  689. } // AlgLookupInterface
  690. ULONG
  691. AlgQueryInterface(
  692. ULONG Index,
  693. PVOID InterfaceInfo,
  694. PULONG InterfaceInfoSize
  695. )
  696. /*++
  697. Routine Description:
  698. This routine is invoked to retrieve the configuration for an interface.
  699. Arguments:
  700. Index - the interface to be queried
  701. InterfaceInfo - receives the retrieved information
  702. InterfaceInfoSize - receives the (required) size of the information
  703. Return Value:
  704. ULONG - Win32 status code.
  705. --*/
  706. {
  707. PALG_INTERFACE Interfacep;
  708. PROFILE("AlgQueryInterface");
  709. //
  710. // Check the caller's buffer size
  711. //
  712. if (!InterfaceInfoSize)
  713. {
  714. return ERROR_INVALID_PARAMETER;
  715. }
  716. //
  717. // Retrieve the interface to be configured
  718. //
  719. EnterCriticalSection(&AlgInterfaceLock);
  720. Interfacep = AlgLookupInterface(Index, NULL);
  721. if (Interfacep == NULL)
  722. {
  723. LeaveCriticalSection(&AlgInterfaceLock);
  724. NhTrace(
  725. TRACE_FLAG_IF,
  726. "AlgQueryInterface: interface %d not found",
  727. Index
  728. );
  729. return ERROR_NO_SUCH_INTERFACE;
  730. }
  731. //
  732. // Reference the interface
  733. //
  734. if (!ALG_REFERENCE_INTERFACE(Interfacep))
  735. {
  736. LeaveCriticalSection(&AlgInterfaceLock);
  737. NhTrace(
  738. TRACE_FLAG_IF,
  739. "AlgQueryInterface: interface %d cannot be referenced",
  740. Index
  741. );
  742. return ERROR_INTERFACE_DISABLED;
  743. }
  744. //
  745. // See if there is any explicit config on this interface
  746. //
  747. if (!ALG_INTERFACE_CONFIGURED(Interfacep))
  748. {
  749. LeaveCriticalSection(&AlgInterfaceLock);
  750. ALG_DEREFERENCE_INTERFACE(Interfacep);
  751. NhTrace(
  752. TRACE_FLAG_IF,
  753. "AlgQueryInterface: interface %d has no configuration",
  754. Index
  755. );
  756. *InterfaceInfoSize = 0;
  757. return NO_ERROR;
  758. }
  759. //
  760. // See if there is enough buffer space
  761. //
  762. if (*InterfaceInfoSize < sizeof(IP_ALG_INTERFACE_INFO))
  763. {
  764. LeaveCriticalSection(&AlgInterfaceLock);
  765. ALG_DEREFERENCE_INTERFACE(Interfacep);
  766. *InterfaceInfoSize = sizeof(IP_ALG_INTERFACE_INFO);
  767. return ERROR_INSUFFICIENT_BUFFER;
  768. }
  769. //
  770. // Copy the requested data
  771. //
  772. CopyMemory(
  773. InterfaceInfo,
  774. &Interfacep->Info,
  775. sizeof(IP_ALG_INTERFACE_INFO)
  776. );
  777. *InterfaceInfoSize = sizeof(IP_ALG_INTERFACE_INFO);
  778. LeaveCriticalSection(&AlgInterfaceLock);
  779. ALG_DEREFERENCE_INTERFACE(Interfacep);
  780. return NO_ERROR;
  781. } // AlgQueryInterface
  782. VOID
  783. AlgShutdownInterfaceManagement(
  784. VOID
  785. )
  786. /*++
  787. Routine Description:
  788. This routine is called to shutdown the interface-management module.
  789. Arguments:
  790. none.
  791. Return Value:
  792. none.
  793. Notes:
  794. Invoked in an arbitrary thread context, after all references
  795. to all interfaces have been released.
  796. --*/
  797. {
  798. PALG_INTERFACE Interfacep;
  799. PLIST_ENTRY Link;
  800. PROFILE("AlgShutdownInterfaceManagement");
  801. while (!IsListEmpty(&AlgInterfaceList))
  802. {
  803. Link = RemoveHeadList(&AlgInterfaceList);
  804. Interfacep = CONTAINING_RECORD(Link, ALG_INTERFACE, Link);
  805. if ( ALG_INTERFACE_ACTIVE( Interfacep ) )
  806. {
  807. AlgDeactivateInterface( Interfacep );
  808. }
  809. AlgCleanupInterface(Interfacep);
  810. }
  811. DeleteCriticalSection(&AlgInterfaceLock);
  812. } // AlgShutdownInterfaceManagement
  813. ULONG
  814. AlgUnbindInterface(
  815. ULONG Index
  816. )
  817. /*++
  818. Routine Description:
  819. This routine is invoked to revoke the binding on an interface.
  820. This involves deactivating the interface if it is active.
  821. Arguments:
  822. Index - the index of the interface to be unbound
  823. Return Value:
  824. none.
  825. Notes:
  826. Invoked internally in the context of an IP router-manager thread.
  827. (See 'RMALG.C').
  828. --*/
  829. {
  830. PALG_INTERFACE Interfacep;
  831. PROFILE("AlgUnbindInterface");
  832. //
  833. // Retrieve the interface to be unbound
  834. //
  835. EnterCriticalSection(&AlgInterfaceLock);
  836. Interfacep = AlgLookupInterface(Index, NULL);
  837. if (Interfacep == NULL)
  838. {
  839. LeaveCriticalSection(&AlgInterfaceLock);
  840. NhTrace(
  841. TRACE_FLAG_IF,
  842. "AlgUnbindInterface: interface %d not found",
  843. Index
  844. );
  845. return ERROR_NO_SUCH_INTERFACE;
  846. }
  847. //
  848. // Make sure the interface is not already unbound
  849. //
  850. if (!ALG_INTERFACE_BOUND(Interfacep))
  851. {
  852. LeaveCriticalSection(&AlgInterfaceLock);
  853. NhTrace(
  854. TRACE_FLAG_IF,
  855. "AlgUnbindInterface: interface %d already unbound",
  856. Index
  857. );
  858. return ERROR_ADDRESS_NOT_ASSOCIATED;
  859. }
  860. //
  861. // Reference the interface
  862. //
  863. if (!ALG_REFERENCE_INTERFACE(Interfacep))
  864. {
  865. LeaveCriticalSection(&AlgInterfaceLock);
  866. NhTrace(
  867. TRACE_FLAG_IF,
  868. "AlgUnbindInterface: interface %d cannot be referenced",
  869. Index
  870. );
  871. return ERROR_INTERFACE_DISABLED;
  872. }
  873. //
  874. // Clear the 'bound' and 'mapped' flag
  875. //
  876. Interfacep->Flags &=
  877. ~(ALG_INTERFACE_FLAG_BOUND | ALG_INTERFACE_FLAG_MAPPED);
  878. //
  879. // Deactivate the interface, if necessary
  880. //
  881. if ( ALG_INTERFACE_ENABLED( Interfacep ) )
  882. {
  883. AlgDeactivateInterface( Interfacep );
  884. }
  885. LeaveCriticalSection(&AlgInterfaceLock);
  886. //
  887. // Destroy the interface's binding
  888. //
  889. ACQUIRE_LOCK(Interfacep);
  890. NH_FREE(Interfacep->BindingArray);
  891. Interfacep->BindingArray = NULL;
  892. Interfacep->BindingCount = 0;
  893. RELEASE_LOCK(Interfacep);
  894. ALG_DEREFERENCE_INTERFACE(Interfacep);
  895. return NO_ERROR;
  896. } // AlgUnbindInterface
  897. VOID
  898. AlgSignalNatInterface(
  899. ULONG Index,
  900. BOOLEAN Boundary
  901. )
  902. /*++
  903. Routine Description:
  904. This routine is invoked upon reconfiguration of a NAT interface.
  905. Note that this routine may be invoked even when the ALG transparent
  906. proxy is neither installed nor running; it operates as expected,
  907. since the global information and lock are always initialized.
  908. Upon invocation, the routine activates or deactivates the interface
  909. depending on whether the NAT is not or is running on the interface,
  910. respectively.
  911. Arguments:
  912. Index - the reconfigured interface
  913. Boundary - indicates whether the interface is now a boundary interface
  914. Return Value:
  915. none.
  916. Notes:
  917. Invoked from an arbitrary context.
  918. --*/
  919. {
  920. MYTRACE_ENTER("AlgSignalNatInterface");
  921. PROFILE("AlgSignalNatInterface");
  922. MYTRACE("Index (%d): Boolean(%d-%s)",
  923. Index,
  924. Boundary,
  925. Boundary?"TRUE":"FALSE");
  926. PALG_INTERFACE Interfacep;
  927. EnterCriticalSection(&AlgGlobalInfoLock);
  928. if (!AlgGlobalInfo)
  929. {
  930. LeaveCriticalSection(&AlgGlobalInfoLock);
  931. return;
  932. }
  933. LeaveCriticalSection(&AlgGlobalInfoLock);
  934. EnterCriticalSection(&AlgInterfaceLock);
  935. Interfacep = AlgLookupInterface(Index, NULL);
  936. if (Interfacep == NULL)
  937. {
  938. LeaveCriticalSection(&AlgInterfaceLock);
  939. return;
  940. }
  941. AlgDeactivateInterface(Interfacep);
  942. if (ALG_INTERFACE_ACTIVE(Interfacep))
  943. {
  944. AlgActivateInterface(Interfacep);
  945. }
  946. LeaveCriticalSection(&AlgInterfaceLock);
  947. } // AlgSignalNatInterface
  948. ULONG
  949. AlgActivateInterface(
  950. PALG_INTERFACE Interfacep
  951. )
  952. /*++
  953. Routine Description:
  954. This routine is called to activate an interface, when the interface
  955. becomes both enabled and bound.
  956. Activation involves
  957. (a) creating sockets for each binding of the interface
  958. (b) initiating connection-acceptance on each created socket
  959. (c) initiating session-redirection for the ALG port, if necessary.
  960. Arguments:
  961. Interfacep - the interface to be activated
  962. Return Value:
  963. ULONG - Win32 status code indicating success or failure.
  964. Notes:
  965. Always invoked locally, with 'Interfacep' referenced by caller and/or
  966. 'AlgInterfaceLock' held by caller.
  967. --*/
  968. {
  969. PROFILE("AlgActivateInterface");
  970. ULONG Error = NO_ERROR;
  971. HRESULT hr;
  972. ULONG Index = Interfacep->Index;
  973. //
  974. // If the NAT has no idea what this is, do not Activate the interface.
  975. // Nat will signal us through AlgSignalNatInterface
  976. // when it detects an interface, causing us to activate this interface
  977. //
  978. ULONG nInterfaceCharacteristics =
  979. NatGetInterfaceCharacteristics( Index );
  980. if (0 == nInterfaceCharacteristics )
  981. {
  982. return NO_ERROR; // Should succeed
  983. }
  984. COMINIT_BEGIN;
  985. if ( SUCCEEDED(hr) )
  986. {
  987. //
  988. // Notify ALG.EXE of the Addition of a new interface
  989. //
  990. IAlgController* pIAlgController = NULL;
  991. hr = GetAlgControllerInterface( &pIAlgController );
  992. if ( SUCCEEDED(hr) )
  993. {
  994. short nTypeOfAdapter = 0;
  995. if ( NAT_IFC_BOUNDARY( nInterfaceCharacteristics ))
  996. nTypeOfAdapter |= eALG_BOUNDARY;
  997. if ( NAT_IFC_FW( nInterfaceCharacteristics ))
  998. nTypeOfAdapter |= eALG_FIREWALLED;
  999. if ( NAT_IFC_PRIVATE( nInterfaceCharacteristics ))
  1000. nTypeOfAdapter |= eALG_PRIVATE;
  1001. hr = pIAlgController->Adapter_Add( Index,
  1002. (short)nTypeOfAdapter );
  1003. if ( FAILED(hr) )
  1004. {
  1005. NhTrace(
  1006. TRACE_FLAG_INIT,
  1007. "AlgRmAddInterface: Error (0x%08x) returned from pIalgController->Adapter_Add()",
  1008. hr
  1009. );
  1010. }
  1011. else
  1012. {
  1013. //
  1014. // Build a simple array of address(DWORD) to send over RPC
  1015. //
  1016. DWORD* apdwAddress = new DWORD[ Interfacep->BindingCount ];
  1017. if(NULL != apdwAddress)
  1018. {
  1019. for ( ULONG nAddress=0;
  1020. nAddress < Interfacep->BindingCount;
  1021. nAddress++ )
  1022. {
  1023. apdwAddress[nAddress] = Interfacep->BindingArray[nAddress].Address;
  1024. }
  1025. ULONG nRealAdapterIndex = NhMapAddressToAdapter(apdwAddress[0]);
  1026. hr = pIAlgController->Adapter_Bind(Index,
  1027. nRealAdapterIndex,
  1028. Interfacep->BindingCount,
  1029. apdwAddress );
  1030. if ( FAILED(hr) )
  1031. {
  1032. NhTrace(
  1033. TRACE_FLAG_INIT,
  1034. "AlgRmBinInterface: Error (0x%08x) returned from pIalgController->Adapter_Bind()",
  1035. hr
  1036. );
  1037. }
  1038. delete [] apdwAddress;
  1039. }
  1040. }
  1041. pIAlgController->Release();
  1042. }
  1043. }
  1044. COMINIT_END;
  1045. Error = WIN32_FROM_HRESULT(hr);
  1046. return Error;
  1047. }
  1048. VOID
  1049. AlgDeactivateInterface(
  1050. PALG_INTERFACE Interfacep
  1051. )
  1052. /*++
  1053. Routine Description:
  1054. This routine is called to deactivate an interface.
  1055. It closes all sockets on the interface's bindings (if any).
  1056. Arguments:
  1057. Interfacep - the interface to be deactivated
  1058. Return Value:
  1059. none.
  1060. Notes:
  1061. Always invoked locally, with 'Interfacep' referenced by caller and/or
  1062. 'AlgInterfaceLock' held by caller.
  1063. --*/
  1064. {
  1065. //
  1066. // Also notify the ALG.exe manager
  1067. //
  1068. HRESULT hr;
  1069. COMINIT_BEGIN;
  1070. if ( SUCCEEDED(hr) )
  1071. {
  1072. IAlgController* pIAlgController=NULL;
  1073. HRESULT hr = GetAlgControllerInterface(&pIAlgController);
  1074. if ( SUCCEEDED(hr) )
  1075. {
  1076. hr = pIAlgController->Adapter_Remove( Interfacep->Index );
  1077. if ( FAILED(hr) )
  1078. {
  1079. NhTrace(
  1080. TRACE_FLAG_INIT,
  1081. "AlgRmAddInterface: Error (0x%08x) returned from pIalgController->Adapter_Remove()",
  1082. hr
  1083. );
  1084. }
  1085. pIAlgController->Release();
  1086. }
  1087. }
  1088. COMINIT_END;
  1089. }