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.

1745 lines
47 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. ApplicationGatewayServices.cpp : Implementation of CApplicationGatewayServices
  5. Abstract:
  6. This module contains routines for the ALG Manager module's
  7. that expose a public api via COM.
  8. Author:
  9. Jon Burstein
  10. Jean-Pierre Duplessis
  11. JPDup 10-Nov-2000
  12. Revision History:
  13. --*/
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CApplicationGatewayServices
  16. //
  17. // ApplicationGatewayServices.cpp : Implementation of CApplicationGatewayServices
  18. //
  19. #include "PreComp.h"
  20. #include "AlgController.h"
  21. #include "ApplicationGatewayServices.h"
  22. #include "PendingProxyConnection.h"
  23. #include "DataChannel.h"
  24. #include "PersistentDataChannel.h"
  25. #include "EnumAdapterInfo.h"
  26. STDMETHODIMP
  27. CApplicationGatewayServices::CreatePrimaryControlChannel(
  28. IN ALG_PROTOCOL eProtocol,
  29. IN USHORT usPortToCapture,
  30. IN ALG_CAPTURE eCaptureType,
  31. IN BOOL fCaptureInbound,
  32. IN ULONG ulListenAddress,
  33. IN USHORT usListenPort,
  34. OUT IPrimaryControlChannel** ppIControlChannel
  35. )
  36. /*++
  37. Routine Description:
  38. Arguments:
  39. eProtocol,
  40. usPortToCapture,
  41. eCaptureType,
  42. fCaptureInbound,
  43. ulListenAddress,
  44. usListenPort,
  45. ppIControlChannel
  46. Return Value:
  47. HRESULT - S_OK for success
  48. Environment:
  49. ALG module will call this method to:
  50. --*/
  51. {
  52. MYTRACE_ENTER("CApplicationGatewayServices::CreatePrimaryControlChannel")
  53. MYTRACE("eProtocol %s", eProtocol==1? "TCP" : "UDP");
  54. MYTRACE("usPortToCapture %d", ntohs(usPortToCapture));
  55. MYTRACE("eCaptureType %s", eCaptureType==eALG_SOURCE_CAPTURE ? "eALG_SOURCE_CAPTURE" : "eALG_DESTINATION_CAPTURE");
  56. MYTRACE("fCaptureInbound %d", fCaptureInbound);
  57. MYTRACE("ulListenAddress %s:%d", MYTRACE_IP(ulListenAddress), ntohs(usListenPort));
  58. if ( !ppIControlChannel )
  59. {
  60. MYTRACE_ERROR("ppIControlChannel not supplied",0);
  61. return E_INVALIDARG;
  62. }
  63. if ( eProtocol != eALG_TCP && eProtocol != eALG_UDP )
  64. {
  65. MYTRACE_ERROR("Arg - eProtocol",0);
  66. return E_INVALIDARG;
  67. }
  68. if ( eCaptureType == eALG_SOURCE_CAPTURE && fCaptureInbound )
  69. {
  70. MYTRACE_ERROR("Can not have SOURCE CAPTURE and fCaptureInBount at same time",0);
  71. return E_INVALIDARG;
  72. }
  73. HRESULT hr;
  74. //
  75. // Add new ControlChannel to List of RULES
  76. //
  77. CComObject<CPrimaryControlChannel>* pIChannel;
  78. hr = CComObject<CPrimaryControlChannel>::CreateInstance(&pIChannel);
  79. if ( SUCCEEDED(hr) )
  80. {
  81. pIChannel->AddRef();
  82. pIChannel->m_Properties.eProtocol = eProtocol;
  83. pIChannel->m_Properties.eCaptureType = eCaptureType;
  84. pIChannel->m_Properties.fCaptureInbound = fCaptureInbound;
  85. pIChannel->m_Properties.ulListeningAddress = ulListenAddress;
  86. pIChannel->m_Properties.usCapturePort = usPortToCapture;
  87. pIChannel->m_Properties.usListeningPort = usListenPort;
  88. hr = pIChannel->QueryInterface(IID_IPrimaryControlChannel, (void**)ppIControlChannel);
  89. if ( SUCCEEDED(hr) )
  90. {
  91. hr = g_pAlgController->m_ControlChannelsPrimary.Add(pIChannel);
  92. if ( FAILED(hr) )
  93. {
  94. MYTRACE_ERROR("from m_ControlChannelsPrimary.Add", hr);
  95. (*ppIControlChannel)->Release();
  96. *ppIControlChannel = NULL;
  97. }
  98. }
  99. else
  100. {
  101. MYTRACE_ERROR("from pIChannel->QueryInterface", hr);
  102. }
  103. pIChannel->Release();
  104. }
  105. else
  106. {
  107. MYTRACE_ERROR("CreateInstance(&pIChannel);", hr);
  108. }
  109. return hr;
  110. }
  111. STDMETHODIMP
  112. CApplicationGatewayServices::CreateSecondaryControlChannel(
  113. IN ALG_PROTOCOL eProtocol,
  114. IN ULONG ulPrivateAddress,
  115. IN USHORT usPrivatePort,
  116. IN ULONG ulPublicAddress,
  117. IN USHORT usPublicPort,
  118. IN ULONG ulRemoteAddress,
  119. IN USHORT usRemotePort,
  120. IN ULONG ulListenAddress,
  121. IN USHORT usListenPort,
  122. IN ALG_DIRECTION eDirection,
  123. IN BOOL fPersistent,
  124. OUT ISecondaryControlChannel** ppIControlChannel
  125. )
  126. /*++
  127. Routine Description:
  128. Arguments:
  129. eProtocol,
  130. ulPrivateAddress,
  131. usPrivatePort,
  132. ulPublicAddress,
  133. usPublicPort,
  134. ulRemoteAddress,
  135. usRemotePort,
  136. ulListenAddress,
  137. usListenPort,
  138. eDirection,
  139. fPersistent,
  140. ppIControlChannel
  141. Return Value:
  142. HRESULT - S_OK for success
  143. Environment:
  144. ALG module will call this method to:
  145. --*/
  146. {
  147. MYTRACE_ENTER("CApplicationGatewayServices::CreateSecondaryControlChannel");
  148. if ( !ppIControlChannel )
  149. {
  150. MYTRACE_ERROR("ppIControlChannel not supplied",0);
  151. return E_INVALIDARG;
  152. }
  153. ULONG ulSourceAddress=0;
  154. USHORT usSourcePort=0;
  155. ULONG ulDestinationAddress=0;
  156. USHORT usDestinationPort=0;
  157. ULONG ulNewSourceAddress=0;
  158. USHORT usNewSourcePort=0;
  159. ULONG ulNewDestinationAddress=0;
  160. USHORT usNewDestinationPort=0;
  161. ULONG nFlags=0;
  162. ULONG ulRestrictAdapterIndex=0;
  163. if ( eALG_INBOUND == eDirection )
  164. {
  165. if ( ulPublicAddress == 0 || usPublicPort == 0 )
  166. {
  167. //
  168. // Madatory arguments for INBOUND
  169. //
  170. MYTRACE_ERROR("ulPublicAddress == 0 || usPublicPort == 0", E_INVALIDARG);
  171. return E_INVALIDARG;
  172. }
  173. //
  174. // All inbound cases map to a single redirect; unlike a primary control channel, there's no need to create per-adapter redirects.
  175. //
  176. if ( ulRemoteAddress==0 && usRemotePort == 0 )
  177. {
  178. //
  179. // Scenario #1a
  180. //
  181. // Inbound connection from unknown machine
  182. //
  183. MYTRACE("SCENARIO:eALG_INBOUND #1a");
  184. nFlags = NatRedirectFlagReceiveOnly;
  185. ulSourceAddress = 0;
  186. usSourcePort = 0;
  187. ulDestinationAddress = ulPublicAddress;
  188. usDestinationPort = usPublicPort;
  189. ulNewSourceAddress = 0;
  190. usNewSourcePort = 0;
  191. ulNewDestinationAddress = ulListenAddress;
  192. usNewDestinationPort = usListenPort;
  193. ulRestrictAdapterIndex = 0;
  194. }
  195. else
  196. if ( ulRemoteAddress !=0 && usRemotePort == 0 )
  197. {
  198. //
  199. // Scenario #1b
  200. //
  201. // Inbound connection from known machine, but unknown port
  202. //
  203. MYTRACE("SCENARIO:eALG_INBOUND #1b");
  204. nFlags = NatRedirectFlagReceiveOnly|NatRedirectFlagRestrictSource;
  205. ulSourceAddress = ulRemoteAddress;
  206. usSourcePort = 0;
  207. ulDestinationAddress = ulPublicAddress;
  208. usDestinationPort = usPublicPort;
  209. ulNewSourceAddress = 0;
  210. usNewSourcePort = 0;
  211. ulNewDestinationAddress = ulListenAddress;
  212. usNewDestinationPort = usListenPort;
  213. ulRestrictAdapterIndex = 0;
  214. }
  215. else
  216. if ( ulRemoteAddress !=0 && usRemotePort != 0 )
  217. {
  218. //
  219. // Scenario #1c
  220. //
  221. // Inbound connection from known machine and port
  222. //
  223. MYTRACE("SCENARIO:eALG_INBOUND #1c");
  224. nFlags = NatRedirectFlagReceiveOnly;
  225. ulSourceAddress = ulRemoteAddress;
  226. usSourcePort = usRemotePort;
  227. ulDestinationAddress = ulPublicAddress;
  228. usDestinationPort = usPublicPort;
  229. ulNewSourceAddress = ulRemoteAddress;
  230. usNewSourcePort = usRemotePort;
  231. ulNewDestinationAddress = ulListenAddress;
  232. usNewDestinationPort = usListenPort;
  233. ulRestrictAdapterIndex = 0;
  234. }
  235. else
  236. return E_INVALIDARG;
  237. }
  238. else
  239. if ( eALG_OUTBOUND == eDirection )
  240. {
  241. //
  242. // These cases can also be handled by a single ul
  243. //
  244. if ( ulRemoteAddress !=0 && usRemotePort != 0 && ulPrivateAddress == 0 && usPrivatePort == 0 )
  245. {
  246. //
  247. // Scenario #2a
  248. //
  249. // Outbound connection to known machine/port, from any private machine
  250. //
  251. MYTRACE("SCENARIO:eALG_OUTBOUND #2a");
  252. nFlags = 0;
  253. ulSourceAddress = 0;
  254. usSourcePort = 0;
  255. ulDestinationAddress = ulRemoteAddress;
  256. usDestinationPort = usRemotePort;
  257. ulNewSourceAddress = 0;
  258. usNewSourcePort = 0;
  259. ulNewDestinationAddress = ulListenAddress;
  260. usNewDestinationPort = usListenPort;
  261. ulRestrictAdapterIndex = 0;
  262. }
  263. else
  264. if ( ulRemoteAddress !=0 && usRemotePort != 0 && ulPrivateAddress != 0 && usPrivatePort == 0 )
  265. {
  266. //
  267. // Scenario #2b
  268. //
  269. // Outbound connection to known machine/port, from a specific private machine
  270. //
  271. MYTRACE("SCENARIO:eALG_OUTBOUND #2b");
  272. nFlags = NatRedirectFlagRestrictSource;
  273. ulSourceAddress = ulPrivateAddress;
  274. usSourcePort = 0;
  275. ulDestinationAddress = ulRemoteAddress;
  276. usDestinationPort = usRemotePort;
  277. ulNewSourceAddress = 0;
  278. usNewSourcePort = 0;
  279. ulNewDestinationAddress = ulListenAddress;
  280. usNewDestinationPort = usListenPort;
  281. ulRestrictAdapterIndex = 0;
  282. }
  283. else
  284. if ( ulRemoteAddress !=0 && usRemotePort != 0 && ulPrivateAddress != 0 && usPrivatePort != 0 )
  285. {
  286. //
  287. // Scenario #2c
  288. //
  289. // Outbound connection to known machine/port, from a specific port on a specific private machine
  290. //
  291. MYTRACE("SCENARIO:eALG_OUTBOUND #2c");
  292. nFlags = 0;
  293. ulSourceAddress = ulPrivateAddress;
  294. usSourcePort = usPrivatePort;
  295. ulDestinationAddress = ulRemoteAddress;
  296. usDestinationPort = usRemotePort;
  297. ulNewSourceAddress = ulPrivateAddress;
  298. usNewSourcePort = usPrivatePort;
  299. ulNewDestinationAddress = ulListenAddress;
  300. usNewDestinationPort = usListenPort;
  301. ulRestrictAdapterIndex = 0;
  302. }
  303. else
  304. if ( ulPrivateAddress != 0 && usPrivatePort != 0 && ulRemoteAddress == 0 && usRemotePort == 0 )
  305. {
  306. //
  307. // Scenario #2d
  308. //
  309. // Outbound connection from a specific port on a specific private machine, to an unknown machine
  310. //
  311. MYTRACE("SCENARIO:eALG_OUTBOUND #2d");
  312. nFlags = NatRedirectFlagSourceRedirect;
  313. ulSourceAddress = ulPrivateAddress;
  314. usSourcePort = usPrivatePort;
  315. ulDestinationAddress = 0;
  316. usDestinationPort = 0;
  317. ulNewSourceAddress = ulPrivateAddress;
  318. usNewSourcePort = usPrivatePort;
  319. ulNewDestinationAddress = ulListenAddress;
  320. usNewDestinationPort = usListenPort;
  321. ulRestrictAdapterIndex = 0;
  322. }
  323. else
  324. if ( ulPrivateAddress != 0 && usPrivatePort != 0 && ulRemoteAddress != 0 && usRemotePort == 0 )
  325. {
  326. //
  327. // Scenario #2e
  328. //
  329. // Outbound connection from a specific port on a specific private machine, to a known machine
  330. //
  331. MYTRACE("SCENARIO:eALG_OUTBOUND #2e");
  332. nFlags = 0;
  333. ulSourceAddress = ulPrivateAddress;
  334. usSourcePort = usPrivatePort;
  335. ulDestinationAddress = ulRemoteAddress;
  336. usDestinationPort = 0;
  337. ulNewSourceAddress = ulPrivateAddress;
  338. usNewSourcePort = usPrivatePort;
  339. ulNewDestinationAddress = ulListenAddress;
  340. usNewDestinationPort = usListenPort;
  341. ulRestrictAdapterIndex = 0;
  342. }
  343. else
  344. return E_INVALIDARG;
  345. }
  346. else
  347. {
  348. //
  349. //
  350. //
  351. return E_INVALIDARG;
  352. }
  353. HRESULT hr;
  354. HANDLE_PTR HandleDynamicRedirect=NULL;
  355. if ( fPersistent )
  356. {
  357. // Dynamic
  358. hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
  359. nFlags,
  360. 0, // Adapter Index
  361. (UCHAR)eProtocol,
  362. ulDestinationAddress, // ULONG DestinationAddress
  363. usDestinationPort, // USHORT DestinationPort
  364. ulSourceAddress, // ULONG SourceAddress
  365. usSourcePort, // USHORT SourcePort
  366. ulNewDestinationAddress, // ULONG NewDestinationAddress
  367. usNewDestinationPort, // USHORT NewDestinationPort
  368. ulNewSourceAddress, // ULONG NewSourceAddress
  369. usNewSourcePort, // USHORT NewSourcePort
  370. &HandleDynamicRedirect
  371. );
  372. }
  373. else
  374. {
  375. // Normal
  376. hr = g_pAlgController->GetNat()->CreateRedirect(
  377. nFlags,
  378. (UCHAR)eProtocol,
  379. ulDestinationAddress, // ULONG DestinationAddress
  380. usDestinationPort, // USHORT DestinationPort
  381. ulSourceAddress, // ULONG SourceAddress
  382. usSourcePort, // USHORT SourcePort
  383. ulNewDestinationAddress, // ULONG NewDestinationAddress
  384. usNewDestinationPort, // USHORT NewDestinationPort
  385. ulNewSourceAddress, // ULONG NewSourceAddress
  386. usNewSourcePort, // USHORT NewSourcePort
  387. ulRestrictAdapterIndex, // ULONG RestrictAdapterIndex
  388. 0, // DWORD_PTR ThisProcessID
  389. NULL, // HANDLE_PTR CreateEvent
  390. NULL // HANDLE_PTR DeleteEvent
  391. );
  392. }
  393. if ( FAILED(hr) )
  394. {
  395. MYTRACE_ERROR("From g_pAlgController->GetNat()->CreateRedirect", hr);
  396. return hr;
  397. }
  398. //
  399. // Add new ControlChannel to List
  400. //
  401. CComObject<CSecondaryControlChannel>* pIChannel;
  402. hr = CComObject<CSecondaryControlChannel>::CreateInstance(&pIChannel);
  403. if ( SUCCEEDED(hr) )
  404. {
  405. pIChannel->AddRef();
  406. pIChannel->m_Properties.eProtocol = eProtocol;
  407. pIChannel->m_Properties.ulPrivateAddress = ulPrivateAddress;
  408. pIChannel->m_Properties.usPrivatePort = usPrivatePort;
  409. pIChannel->m_Properties.ulPublicAddress = ulPublicAddress;
  410. pIChannel->m_Properties.usPublicPort = usPublicPort;
  411. pIChannel->m_Properties.ulRemoteAddress = ulRemoteAddress;
  412. pIChannel->m_Properties.usRemotePort = usRemotePort;
  413. pIChannel->m_Properties.ulListenAddress = ulListenAddress;
  414. pIChannel->m_Properties.usListenPort = usListenPort;
  415. pIChannel->m_Properties.eDirection = eDirection;
  416. pIChannel->m_Properties.fPersistent = fPersistent;
  417. //
  418. // Cache calling parameters used to create the redirect we will need them to cancel the redirect
  419. //
  420. pIChannel->m_ulDestinationAddress = ulDestinationAddress;
  421. pIChannel->m_usDestinationPort = usDestinationPort;
  422. pIChannel->m_ulSourceAddress = ulSourceAddress;
  423. pIChannel->m_usSourcePort = usSourcePort;
  424. pIChannel->m_ulNewDestinationAddress = ulNewDestinationAddress;
  425. pIChannel->m_usNewDestinationPort = usNewDestinationPort;
  426. pIChannel->m_ulNewSourceAddress = ulNewSourceAddress;
  427. pIChannel->m_usNewSourcePort = usNewSourcePort;
  428. pIChannel->m_HandleDynamicRedirect = HandleDynamicRedirect;
  429. hr = pIChannel->QueryInterface(IID_ISecondaryControlChannel, (void**)ppIControlChannel);
  430. if ( SUCCEEDED(hr) )
  431. {
  432. hr = g_pAlgController->m_ControlChannelsSecondary.Add(pIChannel);
  433. if ( FAILED(hr) )
  434. {
  435. MYTRACE_ERROR("Adding to list of SecondaryChannel", hr);
  436. (*ppIControlChannel)->Release();
  437. *ppIControlChannel=NULL;
  438. }
  439. }
  440. else
  441. {
  442. MYTRACE_ERROR("QueryInterface(IID_ISecondaryControlChannel", hr);
  443. }
  444. pIChannel->Release();
  445. }
  446. else
  447. {
  448. MYTRACE_ERROR("From CreateInstance<CSecondaryControlChannel>", hr);
  449. }
  450. return hr;
  451. }
  452. STDMETHODIMP
  453. CApplicationGatewayServices::GetBestSourceAddressForDestinationAddress(
  454. IN ULONG ulDestinationAddress,
  455. IN BOOL fDemandDial,
  456. OUT ULONG* pulBestSrcAddress
  457. )
  458. /*++
  459. Routine Description:
  460. We create a temporary UDP socket, connect the socket to the
  461. actual client's IP address, extract the IP address to which
  462. the socket is implicitly bound by the TCP/IP driver, and
  463. discard the socket. This leaves us with the exact IP address
  464. that we need to use to contact the client.
  465. Arguments:
  466. ulDestinationAddress,
  467. fDemandDial,
  468. pulBestSrcAddress
  469. Return Value:
  470. HRESULT - S_OK for success
  471. Environment:
  472. ALG module will call this method to:
  473. --*/
  474. {
  475. MYTRACE_ENTER("CApplicationGatewayServices::GetBestSourceAddressForDestinationAddress");
  476. HRESULT hr = g_pAlgController->GetNat()->GetBestSourceAddressForDestinationAddress(
  477. ulDestinationAddress,
  478. fDemandDial,
  479. pulBestSrcAddress
  480. );
  481. MYTRACE("For Destination address of %s", MYTRACE_IP(ulDestinationAddress) );
  482. MYTRACE("the Best source address is %s", MYTRACE_IP(*pulBestSrcAddress) );
  483. return hr;
  484. }
  485. //
  486. //
  487. //
  488. //
  489. //
  490. //
  491. STDMETHODIMP
  492. CApplicationGatewayServices::PrepareProxyConnection(
  493. IN ALG_PROTOCOL eProtocol,
  494. IN ULONG ulSourceAddress,
  495. IN USHORT usSourcePort,
  496. IN ULONG ulDestinationAddress,
  497. IN USHORT usDestinationPort,
  498. IN BOOL fNoTimeout,
  499. OUT IPendingProxyConnection** ppPendingConnection
  500. )
  501. /*++
  502. Routine Description:
  503. If we have a firwewall interface, possibly install a
  504. shadow redirect for this connection. The shadow redirect
  505. is necessary to prevent this connection from also being
  506. redirected to the proxy (setting in motion an infinite loop...)
  507. Arguments:
  508. eProtocol,
  509. ulSourceAddress,
  510. usSourcePort,
  511. ulDestinationAddress,
  512. usDestinationPort,
  513. fNoTimeout,
  514. ppPendingConnection
  515. Return Value:
  516. HRESULT - S_OK for success
  517. Environment:
  518. ALG module will call this method to:
  519. --*/
  520. {
  521. MYTRACE_ENTER("CApplicationGatewayServices::PrepareProxyConnection");
  522. MYTRACE("eProtocol %s", eProtocol==1? "TCP" : "UDP");
  523. MYTRACE("Source %s:%d", MYTRACE_IP(ulSourceAddress), ntohs(usSourcePort));
  524. MYTRACE("Destination %s:%d", MYTRACE_IP(ulDestinationAddress), ntohs(usDestinationPort));
  525. MYTRACE("NoTimeout %d", fNoTimeout);
  526. ULONG ulFlags = NatRedirectFlagLoopback;
  527. if ( !ppPendingConnection )
  528. {
  529. MYTRACE_ERROR("ppPendingConnection not supplied",0);
  530. return E_INVALIDARG;
  531. }
  532. if ( fNoTimeout )
  533. {
  534. MYTRACE("NoTimeout specified");
  535. if ( eProtocol == eALG_UDP )
  536. {
  537. ulFlags |= NatRedirectFlagNoTimeout;
  538. }
  539. else
  540. {
  541. MYTRACE("Wrong use of fNoTimeout && eProtocol != eALG_UDP");
  542. return E_INVALIDARG;
  543. }
  544. }
  545. HRESULT hr = g_pAlgController->GetNat()->CreateRedirect(
  546. ulFlags,
  547. (UCHAR)eProtocol,
  548. ulDestinationAddress, // ULONG DestinationAddress,
  549. usDestinationPort, // USHORT DestinationPort,
  550. ulSourceAddress, // ULONG SourceAddress,
  551. usSourcePort, // USHORT SourcePort,
  552. ulDestinationAddress, // ULONG NewDestinationAddress
  553. usDestinationPort, // USHORT NewDestinationPort
  554. ulSourceAddress, // ULONG NewSourceAddress,
  555. usSourcePort, // USHORT NewSourcePort,
  556. 0, // ULONG RestrictAdapterIndex
  557. 0, // DWORD_PTR ThisProcessID
  558. NULL, // HANDLE_PTR CreateEvent
  559. NULL // HANDLE_PTR DeleteEvent
  560. );
  561. if ( SUCCEEDED(hr) )
  562. {
  563. CComObject<CPendingProxyConnection>* pIPendingProxyConnection;
  564. CComObject<CPendingProxyConnection>::CreateInstance(&pIPendingProxyConnection);
  565. pIPendingProxyConnection->m_eProtocol = eProtocol;
  566. pIPendingProxyConnection->m_ulDestinationAddress = ulDestinationAddress;
  567. pIPendingProxyConnection->m_usDestinationPort = usDestinationPort;
  568. pIPendingProxyConnection->m_ulSourceAddress = ulSourceAddress;
  569. pIPendingProxyConnection->m_usSourcePort = usSourcePort;
  570. pIPendingProxyConnection->m_ulNewSourceAddress = ulSourceAddress; // Since the PendingProxyConenction is also used
  571. pIPendingProxyConnection->m_usNewSourcePort = usSourcePort; // by PrepareSourceModifiedProxyConnection we use the NewSource
  572. // for the Cancel
  573. pIPendingProxyConnection->QueryInterface(ppPendingConnection);
  574. }
  575. else
  576. {
  577. MYTRACE_ERROR(">GetNat()->CreateRedirect failed", hr);
  578. }
  579. return hr;
  580. }
  581. STDMETHODIMP
  582. CApplicationGatewayServices::PrepareSourceModifiedProxyConnection(
  583. IN ALG_PROTOCOL eProtocol,
  584. IN ULONG ulSourceAddress,
  585. IN USHORT usSrcPort,
  586. IN ULONG ulDestinationAddress,
  587. IN USHORT usDestinationPort,
  588. IN ULONG ulNewSrcAddress,
  589. IN USHORT usNewSourcePort,
  590. OUT IPendingProxyConnection** ppPendingConnection
  591. )
  592. /*++
  593. Routine Description:
  594. Arguments:
  595. eProtocol,
  596. ulSourceAddress,
  597. usSrcPort,
  598. ulDestinationAddress,
  599. usDestinationPort,
  600. ulNewSrcAddress,
  601. usNewSourcePort,
  602. ppPendingConnection
  603. Return Value:
  604. HRESULT - S_OK for success
  605. Environment:
  606. ALG module will call this method to:
  607. --*/
  608. {
  609. MYTRACE_ENTER("CApplicationGatewayServices::PrepareSourceModifiedProxyConnection");
  610. MYTRACE("Source %s:%d", MYTRACE_IP(ulSourceAddress), ntohs(usSrcPort));
  611. MYTRACE("Destination %s:%d", MYTRACE_IP(ulDestinationAddress), ntohs(usDestinationPort));
  612. MYTRACE("NewSource %s:%d", MYTRACE_IP(ulNewSrcAddress), ntohs(usNewSourcePort));
  613. if ( !ppPendingConnection )
  614. {
  615. MYTRACE_ERROR("IPendingProxyConnection** not supplied",0);
  616. return E_INVALIDARG;
  617. }
  618. HRESULT hr = g_pAlgController->GetNat()->CreateRedirect(
  619. NatRedirectFlagLoopback,
  620. (UCHAR)eProtocol,
  621. ulDestinationAddress, // ULONG DestinationAddress,
  622. usDestinationPort, // USHORT DestinationPort,
  623. ulSourceAddress, // ULONG SourceAddress,
  624. usSrcPort, // USHORT SourcePort,
  625. ulDestinationAddress, // ULONG NewDestinationAddress
  626. usDestinationPort, // USHORT NewDestinationPort
  627. ulNewSrcAddress, // ULONG NewSourceAddress,
  628. usNewSourcePort, // USHORT NewSourcePort,
  629. 0, // ULONG RestrictAdapterIndex
  630. 0, // DWORD_PTR ThisProcessID
  631. NULL, // HANDLE_PTR CreateEvent
  632. NULL // HANDLE_PTR DeleteEvent
  633. );
  634. if ( SUCCEEDED(hr) )
  635. {
  636. CComObject<CPendingProxyConnection>* pIPendingProxyConnection;
  637. CComObject<CPendingProxyConnection>::CreateInstance(&pIPendingProxyConnection);
  638. pIPendingProxyConnection->m_eProtocol = eProtocol;
  639. pIPendingProxyConnection->m_ulDestinationAddress = ulDestinationAddress;
  640. pIPendingProxyConnection->m_usDestinationPort = usDestinationPort;
  641. pIPendingProxyConnection->m_ulSourceAddress = ulSourceAddress;
  642. pIPendingProxyConnection->m_usSourcePort = usSrcPort;
  643. pIPendingProxyConnection->m_ulNewSourceAddress = ulNewSrcAddress;
  644. pIPendingProxyConnection->m_usNewSourcePort = usNewSourcePort;
  645. hr = pIPendingProxyConnection->QueryInterface(ppPendingConnection);
  646. }
  647. return hr;
  648. }
  649. HRESULT
  650. GetRedirectParameters(
  651. IN ALG_DIRECTION eDirection,
  652. IN ALG_PROTOCOL eProtocol,
  653. IN ULONG ulPrivateAddress,
  654. IN USHORT usPrivatePort,
  655. IN ULONG ulPublicAddress,
  656. IN USHORT usPublicPort,
  657. IN ULONG ulRemoteAddress,
  658. IN USHORT usRemotePort,
  659. OUT ULONG& ulFlags,
  660. OUT ULONG& ulSourceAddress,
  661. OUT USHORT& usSourcePort,
  662. OUT ULONG& ulDestinationAddress,
  663. OUT USHORT& usDestinationPort,
  664. OUT ULONG& ulNewSourceAddress,
  665. OUT USHORT& usNewSourcePort,
  666. OUT ULONG& ulNewDestinationAddress,
  667. OUT USHORT& usNewDestinationPort,
  668. OUT ULONG& ulRestrictAdapterIndex
  669. )
  670. /*++
  671. Routine Description:
  672. The logic in these scenario are use by CreateDataChannel and CreatePersitenDataChannel
  673. Arguments:
  674. eProtocol,
  675. ulSourceAddress,
  676. usSrcPort,
  677. ulDestinationAddress,
  678. usDestinationPort,
  679. ulNewSrcAddress,
  680. usNewSourcePort,
  681. ppPendingConnection
  682. Return Value:
  683. HRESULT - S_OK for success
  684. Environment:
  685. ALG module will call this method to:
  686. --*/
  687. {
  688. if ( eALG_INBOUND == eDirection )
  689. {
  690. if ( ulRemoteAddress == 0 && usRemotePort == 0 )
  691. {
  692. // 1a
  693. ulFlags = NatRedirectFlagReceiveOnly;
  694. ulSourceAddress = 0;
  695. usSourcePort = 0;
  696. ulDestinationAddress = ulPublicAddress;
  697. usDestinationPort = usPublicPort;
  698. ulNewSourceAddress = 0;
  699. usNewSourcePort = 0;
  700. ulNewDestinationAddress = ulPrivateAddress;
  701. usNewDestinationPort = usPrivatePort;
  702. ulRestrictAdapterIndex = 0;
  703. }
  704. else
  705. if ( ulRemoteAddress != 0 && usRemotePort == 0 )
  706. {
  707. // 1b
  708. ulFlags = NatRedirectFlagReceiveOnly|NatRedirectFlagRestrictSource;
  709. ulSourceAddress = ulRemoteAddress;
  710. usSourcePort = 0;
  711. ulDestinationAddress = ulPublicAddress;
  712. usDestinationPort = usPublicPort;
  713. ulNewSourceAddress = 0;
  714. usNewSourcePort = 0;
  715. ulNewDestinationAddress = ulPrivateAddress;
  716. usNewDestinationPort = usPrivatePort;
  717. ulRestrictAdapterIndex = 0;
  718. }
  719. else
  720. if ( ulRemoteAddress != 0 && usRemotePort != 0 )
  721. {
  722. // 1c.
  723. ulFlags = NatRedirectFlagReceiveOnly;
  724. ulSourceAddress = ulRemoteAddress;
  725. usSourcePort = usRemotePort;
  726. ulDestinationAddress = ulPublicAddress;
  727. usDestinationPort = usPublicPort;
  728. ulNewSourceAddress = ulRemoteAddress;
  729. usNewSourcePort = usRemotePort;
  730. ulNewDestinationAddress = ulPrivateAddress;
  731. usNewDestinationPort = usPrivatePort;
  732. ulRestrictAdapterIndex = 0;
  733. }
  734. else
  735. return E_INVALIDARG;
  736. }
  737. else
  738. if ( eALG_OUTBOUND == eDirection )
  739. {
  740. if ( ulPrivateAddress == 0 && usPrivatePort == 0 )
  741. {
  742. // 2a.
  743. ulFlags = 0;
  744. ulSourceAddress = 0;
  745. usSourcePort = 0;
  746. ulDestinationAddress = ulRemoteAddress;
  747. usDestinationPort = usRemotePort;
  748. ulNewSourceAddress = ulPublicAddress;
  749. usNewSourcePort = usPublicPort;
  750. ulNewDestinationAddress = ulRemoteAddress;
  751. usNewDestinationPort = usRemotePort;
  752. ulRestrictAdapterIndex = 0;
  753. }
  754. else
  755. if ( ulPrivateAddress != 0 && usPrivatePort == 0 )
  756. {
  757. // 2b.
  758. ulFlags = NatRedirectFlagRestrictSource;
  759. ulSourceAddress = ulPrivateAddress;
  760. usSourcePort = 0;
  761. ulDestinationAddress = ulRemoteAddress;
  762. usDestinationPort = usRemotePort;
  763. ulNewSourceAddress = ulPublicAddress;
  764. usNewSourcePort = usPublicPort;
  765. ulNewDestinationAddress = ulRemoteAddress;
  766. usNewDestinationPort = usRemotePort;
  767. ulRestrictAdapterIndex = 0;
  768. }
  769. else
  770. if ( ulPrivateAddress != 0 && usPrivatePort != 0 )
  771. {
  772. // 2c.
  773. ulFlags = 0;
  774. ulSourceAddress = ulPrivateAddress;
  775. usSourcePort = usPrivatePort;
  776. ulDestinationAddress = ulRemoteAddress;
  777. usDestinationPort = usRemotePort;
  778. ulNewSourceAddress = ulPublicAddress;
  779. usNewSourcePort = usPublicPort;
  780. ulNewDestinationAddress = ulRemoteAddress;
  781. usNewDestinationPort = usRemotePort;
  782. ulRestrictAdapterIndex = 0;
  783. }
  784. else
  785. return E_INVALIDARG;
  786. }
  787. else
  788. if ( (eALG_INBOUND | eALG_OUTBOUND) == eDirection )
  789. {
  790. ulFlags = 0;
  791. ulSourceAddress = ulRemoteAddress;
  792. usSourcePort = usRemotePort;
  793. ulDestinationAddress = ulPublicAddress;
  794. usDestinationPort = usPublicPort;
  795. ulNewSourceAddress = ulRemoteAddress;
  796. usNewSourcePort = usRemotePort;
  797. ulNewDestinationAddress = ulPrivateAddress;
  798. usNewDestinationPort = usPrivatePort;
  799. ulRestrictAdapterIndex = 0;
  800. }
  801. else
  802. return E_INVALIDARG;
  803. return S_OK;
  804. }
  805. STDMETHODIMP
  806. CApplicationGatewayServices::CreateDataChannel(
  807. IN ALG_PROTOCOL eProtocol,
  808. IN ULONG ulPrivateAddress,
  809. IN USHORT usPrivatePort,
  810. IN ULONG ulPublicAddress,
  811. IN USHORT usPublicPort,
  812. IN ULONG ulRemoteAddress,
  813. IN USHORT usRemotePort,
  814. IN ALG_DIRECTION eDirection,
  815. IN ALG_NOTIFICATION eDesiredNotification,
  816. IN BOOL fNoTimeout,
  817. OUT IDataChannel** ppDataChannel
  818. )
  819. /*++
  820. Routine Description:
  821. Arguments:
  822. eProtocol,
  823. ulPrivateAddress,
  824. usPrivatePort,
  825. ulPublicAddress,
  826. usPublicPort,
  827. ulRemoteAddress,
  828. usRemotePort,
  829. eDirection,
  830. eDesiredNotification,
  831. fNoTimeout,
  832. ppDataChannel
  833. Return Value:
  834. HRESULT - S_OK for success
  835. Environment:
  836. ALG module will call this method to:
  837. --*/
  838. {
  839. MYTRACE_ENTER("CApplicationGatewayServices::CreateDataChannel");
  840. if ( !ppDataChannel )
  841. {
  842. MYTRACE_ERROR("IDataChannel** not supplied",0);
  843. return E_INVALIDARG;
  844. }
  845. MYTRACE("eProtocol %d", eProtocol);
  846. MYTRACE("ulPrivateAddress %s:%d", MYTRACE_IP(ulPrivateAddress), ntohs(usPrivatePort));
  847. MYTRACE("ulPublicAddress %s:%d", MYTRACE_IP(ulPublicAddress), ntohs(usPublicPort));
  848. MYTRACE("ulRemoteAddress %s:%d", MYTRACE_IP(ulRemoteAddress), ntohs(usRemotePort));
  849. MYTRACE("eDirection %d", eDirection);
  850. MYTRACE("eDesiredNotification %d", eDesiredNotification);
  851. MYTRACE("fNoTimeout %d", fNoTimeout);
  852. ULONG ulFlags=0;
  853. ULONG ulSourceAddress=0;
  854. USHORT usSourcePort=0;
  855. ULONG ulDestinationAddress=0;
  856. USHORT usDestinationPort=0;
  857. ULONG ulNewSourceAddress=0;
  858. USHORT usNewSourcePort=0;
  859. ULONG ulNewDestinationAddress=0;
  860. USHORT usNewDestinationPort=0;
  861. ULONG ulRestrictAdapterIndex=0;
  862. HRESULT hr = GetRedirectParameters(
  863. // IN Params
  864. eDirection,
  865. eProtocol,
  866. ulPrivateAddress,
  867. usPrivatePort,
  868. ulPublicAddress,
  869. usPublicPort,
  870. ulRemoteAddress,
  871. usRemotePort,
  872. // OUT Params
  873. ulFlags,
  874. ulSourceAddress,
  875. usSourcePort,
  876. ulDestinationAddress,
  877. usDestinationPort,
  878. ulNewSourceAddress,
  879. usNewSourcePort,
  880. ulNewDestinationAddress,
  881. usNewDestinationPort,
  882. ulRestrictAdapterIndex
  883. );
  884. if ( FAILED(hr) )
  885. {
  886. MYTRACE_ERROR("Invalid parameters pass", hr);
  887. return E_INVALIDARG;
  888. }
  889. //
  890. // Check for timeout
  891. //
  892. if ( fNoTimeout && eALG_UDP == eProtocol)
  893. ulFlags |= NatRedirectFlagNoTimeout;
  894. HANDLE_PTR hCreateEvent = NULL;
  895. HANDLE_PTR hDeleteEvent = NULL;
  896. //
  897. // We need to events Create and Delete
  898. //
  899. if ( eALG_SESSION_CREATION & eDesiredNotification )
  900. {
  901. hCreateEvent = (HANDLE_PTR)CreateEvent(NULL, FALSE, FALSE, NULL);
  902. if ( !hCreateEvent )
  903. {
  904. MYTRACE_ERROR("Could not create hCreateEvent", GetLastError());
  905. return HRESULT_FROM_WIN32(GetLastError());
  906. }
  907. }
  908. else
  909. {
  910. MYTRACE("NO eALG_SESSION_CREATION notification requested");
  911. }
  912. if ( eALG_SESSION_DELETION & eDesiredNotification )
  913. {
  914. hDeleteEvent = (HANDLE_PTR)CreateEvent(NULL, FALSE, FALSE, NULL);
  915. if ( !hDeleteEvent )
  916. {
  917. MYTRACE_ERROR("Could not create hDeleteEvent", GetLastError());
  918. if ( hCreateEvent )
  919. CloseHandle((HANDLE)hCreateEvent);
  920. return HRESULT_FROM_WIN32(GetLastError());
  921. }
  922. }
  923. else
  924. {
  925. MYTRACE("NO eALG_SESSION_DELETION notification requested");
  926. }
  927. //
  928. // Create a IDataChannel and cache arg to be able CancelRedirect
  929. //
  930. hr = g_pAlgController->GetNat()->CreateRedirect(
  931. ulFlags|NatRedirectFlagLoopback,
  932. (UCHAR)eProtocol,
  933. ulDestinationAddress,
  934. usDestinationPort,
  935. ulSourceAddress,
  936. usSourcePort,
  937. ulNewDestinationAddress,
  938. usNewDestinationPort,
  939. ulNewSourceAddress,
  940. usNewSourcePort,
  941. ulRestrictAdapterIndex,
  942. GetCurrentProcessId(),
  943. hCreateEvent,
  944. hDeleteEvent
  945. );
  946. if ( FAILED(hr) )
  947. {
  948. MYTRACE_ERROR("GetNAT()->CreateRedirect",hr);
  949. if ( hCreateEvent )
  950. CloseHandle((HANDLE)hCreateEvent);
  951. if ( hDeleteEvent )
  952. CloseHandle((HANDLE)hDeleteEvent);
  953. return hr;
  954. }
  955. CComObject<CDataChannel>* pIDataChannel;
  956. hr = CComObject<CDataChannel>::CreateInstance(&pIDataChannel);
  957. if ( SUCCEEDED(hr) )
  958. {
  959. //
  960. // Save these settings so to be able to return them to the user
  961. // if the IDataChannel->GetProperties is called
  962. //
  963. pIDataChannel->m_Properties.eProtocol = eProtocol;
  964. pIDataChannel->m_Properties.ulPrivateAddress = ulPrivateAddress;
  965. pIDataChannel->m_Properties.usPrivatePort = usPrivatePort;
  966. pIDataChannel->m_Properties.ulPublicAddress = ulPublicAddress;
  967. pIDataChannel->m_Properties.usPublicPort = usPublicPort;
  968. pIDataChannel->m_Properties.ulRemoteAddress = ulRemoteAddress;
  969. pIDataChannel->m_Properties.usRemotePort = usRemotePort;
  970. pIDataChannel->m_Properties.eDirection = eDirection;
  971. pIDataChannel->m_Properties.eDesiredNotification = eDesiredNotification;
  972. //
  973. // Cache these arguments in order to implement IDataChannel->Cancel
  974. //
  975. pIDataChannel->m_ulSourceAddress = ulSourceAddress;
  976. pIDataChannel->m_usSourcePort = usSourcePort;
  977. pIDataChannel->m_ulDestinationAddress = ulDestinationAddress;
  978. pIDataChannel->m_usDestinationPort = usDestinationPort;
  979. pIDataChannel->m_ulNewSourceAddress = ulNewSourceAddress;
  980. pIDataChannel->m_usNewSourcePort = usNewSourcePort;
  981. pIDataChannel->m_ulNewDestinationAddress = ulNewDestinationAddress;
  982. pIDataChannel->m_usNewDestinationPort = usNewDestinationPort;
  983. pIDataChannel->m_ulRestrictAdapterIndex = ulRestrictAdapterIndex;
  984. pIDataChannel->m_hCreateEvent = (HANDLE)hCreateEvent;
  985. pIDataChannel->m_hDeleteEvent = (HANDLE)hDeleteEvent;
  986. hr = pIDataChannel->QueryInterface(ppDataChannel);
  987. if ( FAILED(hr) )
  988. {
  989. MYTRACE_ERROR("QI on IDataChannel", hr);
  990. }
  991. }
  992. return hr;
  993. }
  994. STDMETHODIMP
  995. CApplicationGatewayServices::CreatePersistentDataChannel(
  996. IN ALG_PROTOCOL eProtocol,
  997. IN ULONG ulPrivateAddress,
  998. IN USHORT usPrivatePort,
  999. IN ULONG ulPublicAddress,
  1000. IN USHORT usPublicPort,
  1001. IN ULONG ulRemoteAddress,
  1002. IN USHORT usRemotePort,
  1003. IN ALG_DIRECTION eDirection,
  1004. OUT IPersistentDataChannel** ppIPersistentDataChannel
  1005. )
  1006. /*++
  1007. Routine Description:
  1008. Arguments:
  1009. eProtocol,
  1010. ulPrivateAddress,
  1011. usPrivatePort,
  1012. ulPublicAddress,
  1013. usPublicPort,
  1014. ulRemoteAddress,
  1015. usRemotePort,
  1016. eDirection,
  1017. ppIPersistentDataChannel
  1018. Return Value:
  1019. HRESULT - S_OK for success
  1020. Environment:
  1021. ALG module will call this method to:
  1022. --*/
  1023. {
  1024. MYTRACE_ENTER("CApplicationGatewayServices::CreatePersistentDataChannel");
  1025. if ( !ppIPersistentDataChannel )
  1026. {
  1027. MYTRACE_ERROR("IPersistentDataChannel** not supplied",0);
  1028. return E_INVALIDARG;
  1029. }
  1030. ULONG ulFlags=0;
  1031. ULONG ulSourceAddress=0;
  1032. USHORT usSourcePort=0;
  1033. ULONG ulDestinationAddress=0;
  1034. USHORT usDestinationPort=0;
  1035. ULONG ulNewSourceAddress=0;
  1036. USHORT usNewSourcePort=0;
  1037. ULONG ulNewDestinationAddress=0;
  1038. USHORT usNewDestinationPort=0;
  1039. ULONG ulRestrictAdapterIndex=0;
  1040. HRESULT hr = GetRedirectParameters(
  1041. // IN Params
  1042. eDirection,
  1043. eProtocol,
  1044. ulPrivateAddress,
  1045. usPrivatePort,
  1046. ulPublicAddress,
  1047. usPublicPort,
  1048. ulRemoteAddress,
  1049. usRemotePort,
  1050. // OUT Params
  1051. ulFlags,
  1052. ulSourceAddress,
  1053. usSourcePort,
  1054. ulDestinationAddress,
  1055. usDestinationPort,
  1056. ulNewSourceAddress,
  1057. usNewSourcePort,
  1058. ulNewDestinationAddress,
  1059. usNewDestinationPort,
  1060. ulRestrictAdapterIndex
  1061. );
  1062. if ( FAILED(hr) )
  1063. return hr;
  1064. //
  1065. // Create a IDataChannel and cache arg so to CancelRedirect
  1066. //
  1067. HANDLE_PTR HandleDynamicRedirect=NULL;
  1068. // Dynamic
  1069. hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
  1070. ulFlags,
  1071. 0, // Adapter Index
  1072. (UCHAR)eProtocol,
  1073. ulDestinationAddress, // ULONG DestinationAddress
  1074. usDestinationPort, // USHORT DestinationPort
  1075. ulSourceAddress, // ULONG SourceAddress
  1076. usSourcePort, // USHORT SourcePort
  1077. ulNewDestinationAddress, // ULONG NewDestinationAddress
  1078. usNewDestinationPort, // USHORT NewDestinationPort
  1079. ulNewSourceAddress, // ULONG NewSourceAddress
  1080. usNewSourcePort, // USHORT NewSourcePort
  1081. &HandleDynamicRedirect
  1082. );
  1083. if ( SUCCEEDED(hr) )
  1084. {
  1085. CComObject<CPersistentDataChannel>* pIPersistentDataChannel;
  1086. CComObject<CPersistentDataChannel>::CreateInstance(&pIPersistentDataChannel);
  1087. //
  1088. // Save these settings so to be able to return them to the user
  1089. // if the IDataChannel->GetProperties is called
  1090. //
  1091. pIPersistentDataChannel->m_Properties.eProtocol = eProtocol;
  1092. pIPersistentDataChannel->m_Properties.ulPrivateAddress = ulPrivateAddress;
  1093. pIPersistentDataChannel->m_Properties.usPrivatePort = usPrivatePort;
  1094. pIPersistentDataChannel->m_Properties.ulPublicAddress = ulPublicAddress;
  1095. pIPersistentDataChannel->m_Properties.usPublicPort = usPublicPort;
  1096. pIPersistentDataChannel->m_Properties.ulRemoteAddress = ulRemoteAddress;
  1097. pIPersistentDataChannel->m_Properties.usRemotePort = usRemotePort;
  1098. pIPersistentDataChannel->m_Properties.eDirection = eDirection;
  1099. //
  1100. // Cache these hanlde in order to implement IPersistentDataChannel->Cancel
  1101. //
  1102. pIPersistentDataChannel->m_HandleDynamicRedirect = HandleDynamicRedirect;
  1103. hr = pIPersistentDataChannel->QueryInterface(ppIPersistentDataChannel);
  1104. }
  1105. return hr;
  1106. }
  1107. STDMETHODIMP
  1108. CApplicationGatewayServices::ReservePort(
  1109. IN USHORT usPortCount, // must be 1 or more and not more then ALG_MAXIMUM_PORT_RANGE_SIZE
  1110. OUT USHORT* pusReservedPort // Received the base reserved port *pusReservedPort+usPortCount-1 are reserved for the caller
  1111. )
  1112. /*++
  1113. Routine Description:
  1114. Reserve a number of port (usPortCount) port(s)
  1115. Arguments:
  1116. usPortCount - greated then 1 and not more then ALG_MAXIMUM_PORT_RANGE_SIZE
  1117. pusReservedPort - Received the base reserved port *pusReservedPort+usPortCount-1 are reserved for the caller
  1118. Return Value:
  1119. HRESULT - S_OK for success
  1120. Environment:
  1121. ALG module will call this method to:
  1122. --*/
  1123. {
  1124. MYTRACE_ENTER("CApplicationGatewayServices::ReservePort")
  1125. if ( usPortCount < 0 || usPortCount > ALG_MAXIMUM_PORT_RANGE_SIZE )
  1126. return E_INVALIDARG;
  1127. _ASSERT(pusReservedPort);
  1128. HRESULT hr = g_pAlgController->GetNat()->ReservePort(usPortCount, pusReservedPort);
  1129. if ( FAILED(hr) )
  1130. {
  1131. MYTRACE("Reserving Ports", hr);
  1132. }
  1133. else
  1134. {
  1135. MYTRACE("%d port stating at %d", usPortCount, ntohs(*pusReservedPort) );
  1136. }
  1137. return hr;
  1138. }
  1139. //
  1140. //
  1141. //
  1142. VOID CALLBACK
  1143. CApplicationGatewayServices::TimerCallbackReleasePort(
  1144. PVOID pParameter, // thread data
  1145. BOOLEAN TimerOrWaitFired // reason
  1146. )
  1147. {
  1148. MYTRACE_ENTER("CApplicationGatewayServices::TimerCallbackReleasePort");
  1149. CTimerQueueReleasePort* pTimerQueueReleasePort = (CTimerQueueReleasePort*)pParameter;
  1150. if ( pTimerQueueReleasePort )
  1151. {
  1152. MYTRACE("Releasing port Base %d count %d", ntohs(pTimerQueueReleasePort->m_usPortBase), pTimerQueueReleasePort->m_usPortCount);
  1153. g_pAlgController->GetNat()->ReleasePort(pTimerQueueReleasePort->m_usPortBase, pTimerQueueReleasePort->m_usPortCount);
  1154. delete pTimerQueueReleasePort;
  1155. }
  1156. }
  1157. STDMETHODIMP
  1158. CApplicationGatewayServices::ReleaseReservedPort(
  1159. IN USHORT usPortBase, // Port to release
  1160. IN USHORT usPortCount // Number of port in the range starting at usPortBase
  1161. )
  1162. /*++
  1163. Routine Description:
  1164. Release the given port(s)
  1165. Arguments:
  1166. pusReservedPort - The starting base port number
  1167. usPortCount - greated then 1 and not more then ALG_MAXIMUM_PORT_RANGE_SIZE
  1168. Return Value:
  1169. HRESULT - S_OK for success
  1170. - E_FAIL could no release the port
  1171. Environment:
  1172. ALG module will call this method to:
  1173. --*/
  1174. {
  1175. MYTRACE_ENTER("CApplicationGatewayServices::ReleaseReservedPort")
  1176. MYTRACE("BasePort %d, Count %d", ntohs(usPortBase), usPortCount);
  1177. //
  1178. // By creating a CTimerQueueReleasePort it will trigger a ReleaseReservePort after 4 minutes
  1179. // we need this delay to insure that a ReserverPort does not get the same port that just go Released
  1180. // because the connnection would not work (This is a TCP/IP TIME_WAIT restriction)
  1181. //
  1182. CTimerQueueReleasePort* pTimerReleasePort = new CTimerQueueReleasePort(m_hTimerQueue, usPortBase, usPortCount);
  1183. if ( pTimerReleasePort )
  1184. return S_OK;
  1185. else
  1186. return E_FAIL;
  1187. }
  1188. STDMETHODIMP
  1189. CApplicationGatewayServices::EnumerateAdapters(
  1190. OUT IEnumAdapterInfo** ppEnumAdapterInfo
  1191. )
  1192. /*++
  1193. Routine Description:
  1194. Create a list of IEnumAdapterInfo
  1195. the AddRef will be done soe caller needs to call Release
  1196. Arguments:
  1197. ppEnumAdapterInfo - receive the enumarator interface of the IAdapterInfo
  1198. Return Value:
  1199. HRESULT - S_OK for success
  1200. Environment:
  1201. ALG module will call this method to:
  1202. --*/
  1203. {
  1204. MYTRACE_ENTER("CApplicationGatewayServices::EnumerateAdapters")
  1205. _ASSERT(ppEnumAdapterInfo==NULL);
  1206. HRESULT hr = S_OK;
  1207. CreateSTLEnumerator<ComEnumOnSTL_ForAdapters>(
  1208. (IUnknown**)ppEnumAdapterInfo,
  1209. NULL,
  1210. g_pAlgController->m_CollectionOfAdapters.m_ListOfAdapters
  1211. );
  1212. return hr;
  1213. }
  1214. STDMETHODIMP
  1215. CApplicationGatewayServices::StartAdapterNotifications(
  1216. IN IAdapterNotificationSink* pSink,
  1217. OUT DWORD* pdwCookie
  1218. )
  1219. /*++
  1220. Routine Description:
  1221. The ALG module calls this method to Register a notification sync with the ALG.exe
  1222. Arguments:
  1223. pSink - Interface to call back with future notification
  1224. pdwCookie - this cookie will be used to cancel this sink
  1225. Return Value:
  1226. HRESULT - S_OK for success
  1227. Environment:
  1228. ALG module will call this method to:
  1229. --*/
  1230. {
  1231. MYTRACE_ENTER("CApplicationGatewayServices::StartAdapterNotifications")
  1232. if ( pSink==NULL || pdwCookie==NULL )
  1233. {
  1234. MYTRACE("Invalid argument pass");
  1235. return E_INVALIDARG;
  1236. }
  1237. return g_pAlgController->m_AdapterNotificationSinks.Add(pSink, pdwCookie);
  1238. }
  1239. STDMETHODIMP
  1240. CApplicationGatewayServices::StopAdapterNotifications(
  1241. IN DWORD dwCookieToRemove
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. Cancel a previously registered sink
  1246. Arguments:
  1247. pdwCookieToRemove - Pass the cookie that was return from the StartAdapterNotifications
  1248. Return Value:
  1249. HRESULT - S_OK for success
  1250. Environment:
  1251. ALG module will call this method to:
  1252. --*/
  1253. {
  1254. MYTRACE_ENTER("CApplicationGatewayServices::StopAdapterNotifications")
  1255. return g_pAlgController->m_AdapterNotificationSinks.Remove(dwCookieToRemove);
  1256. }