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.

527 lines
15 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. PrimaryControlChannel.cpp.cpp
  5. Abstract:
  6. Control channel a created to control the life time of a newly created DynamicRedirection
  7. Author:
  8. JP Duplessis (jpdup) 08-Dec-2000
  9. Revision History:
  10. --*/
  11. #include "PreComp.h"
  12. #include "PrimaryControlChannel.h"
  13. #include "AlgController.h"
  14. /////////////////////////////////////////////////////////////////////////////
  15. //
  16. // CPrimaryControlChannel
  17. //
  18. //
  19. // Cancel the control channel. Cleans up by Reversing the Redirection
  20. //
  21. STDMETHODIMP CPrimaryControlChannel::Cancel()
  22. {
  23. MYTRACE_ENTER("STDMETHODIMP CPrimaryControlChannel::Cancel()");
  24. //
  25. // No longer valid so no need to keep track of this Channel
  26. //
  27. g_pAlgController->m_ControlChannelsPrimary.Remove(this);
  28. return S_OK;
  29. }
  30. //
  31. //
  32. //
  33. STDMETHODIMP
  34. CPrimaryControlChannel::GetChannelProperties(
  35. OUT ALG_PRIMARY_CHANNEL_PROPERTIES** ppProperties
  36. )
  37. {
  38. HRESULT hr = S_OK;
  39. if (NULL != ppProperties)
  40. {
  41. *ppProperties = reinterpret_cast<ALG_PRIMARY_CHANNEL_PROPERTIES*>(
  42. CoTaskMemAlloc(sizeof(ALG_PRIMARY_CHANNEL_PROPERTIES))
  43. );
  44. if (NULL != *ppProperties)
  45. {
  46. CopyMemory(*ppProperties, &m_Properties, sizeof(ALG_PRIMARY_CHANNEL_PROPERTIES));
  47. }
  48. else
  49. {
  50. hr = E_OUTOFMEMORY;
  51. }
  52. }
  53. else
  54. {
  55. hr = E_POINTER;
  56. }
  57. return hr;
  58. }
  59. //
  60. // Small helper class to get the IP address of an adapter
  61. // and release the memory allocated on the destructor
  62. //
  63. class CAdapterAddresses
  64. {
  65. public:
  66. LRESULT m_hResultLastState;
  67. IAdapterInfo* m_pIAdapter;
  68. ULONG m_ulAddressCount;
  69. ULONG* m_arAddresses;
  70. CAdapterAddresses(
  71. ULONG nIndexOfAdapter
  72. )
  73. {
  74. MYTRACE_ENTER_NOSHOWEXIT("CAdapterAddresses:NEW");
  75. m_pIAdapter = NULL;
  76. m_ulAddressCount = 0;
  77. m_hResultLastState = g_pAlgController->m_CollectionOfAdapters.GetAdapterInfo(
  78. nIndexOfAdapter,
  79. &m_pIAdapter
  80. );
  81. if ( SUCCEEDED(m_hResultLastState) )
  82. {
  83. m_arAddresses = NULL;
  84. m_hResultLastState = m_pIAdapter->GetAdapterAddresses(
  85. &m_ulAddressCount,
  86. &m_arAddresses
  87. );
  88. if ( FAILED(m_hResultLastState) )
  89. {
  90. MYTRACE_ERROR("Could not get the address", m_hResultLastState);
  91. }
  92. }
  93. else
  94. {
  95. MYTRACE_ERROR("On GetAdapterInfo", m_hResultLastState);
  96. }
  97. }
  98. ~CAdapterAddresses()
  99. {
  100. MYTRACE_ENTER_NOSHOWEXIT("CAdapterAddresses:DELETE");
  101. if ( m_pIAdapter )
  102. {
  103. m_pIAdapter->Release();
  104. if ( m_arAddresses )
  105. CoTaskMemFree(m_arAddresses);
  106. }
  107. }
  108. bool
  109. FindAddress(
  110. ULONG ulAddressToFind
  111. )
  112. {
  113. int nAddress = (int)m_ulAddressCount;
  114. //
  115. // Is the original address on the edgebox adapter
  116. //
  117. while ( --nAddress >= 0 )
  118. {
  119. if ( m_arAddresses[nAddress] == ulAddressToFind )
  120. return true;
  121. }
  122. return false;
  123. }
  124. };
  125. //
  126. //
  127. //
  128. STDMETHODIMP
  129. CPrimaryControlChannel::GetOriginalDestinationInformation(
  130. IN ULONG ulSourceAddress,
  131. IN USHORT usSourcePort,
  132. OUT ULONG* pulOriginalDestinationAddress,
  133. OUT USHORT* pusOriginalDestinationPort,
  134. OUT IAdapterInfo** ppReceiveAdapter
  135. )
  136. {
  137. MYTRACE_ENTER("CPrimaryControlChannel::GetOriginalDestinationInformation");
  138. MYTRACE("Source %s:%d", MYTRACE_IP(ulSourceAddress), ntohs(usSourcePort));
  139. if ( !ppReceiveAdapter )
  140. {
  141. MYTRACE_ERROR("Invalid Arg no Pointer supplied for the AdapterInfo", E_INVALIDARG);
  142. return E_INVALIDARG;
  143. }
  144. ULONG nAdapterIndex;
  145. HRESULT hr = g_pAlgController->GetNat()->GetOriginalDestinationInformation(
  146. m_Properties.eProtocol,
  147. m_Properties.ulListeningAddress, // ULONG DestinationAddress,
  148. m_Properties.usListeningPort, // USHORT DestinationPort,
  149. ulSourceAddress,
  150. usSourcePort,
  151. pulOriginalDestinationAddress,
  152. pusOriginalDestinationPort,
  153. &nAdapterIndex
  154. );
  155. if ( FAILED(hr) )
  156. {
  157. MYTRACE_ERROR("Could not GetNat()->GetOriginalDestinationInformation", hr);
  158. return hr;
  159. }
  160. MYTRACE("Original destination is %s:%d", MYTRACE_IP(*pulOriginalDestinationAddress), ntohs(*pusOriginalDestinationPort));
  161. //
  162. // Get the AdapterInfo interface object and list of IP Address
  163. //
  164. CAdapterAddresses Adapter(nAdapterIndex);
  165. if ( FAILED(Adapter.m_hResultLastState) )
  166. {
  167. MYTRACE_ERROR("On GetAdapterInfo", hr);
  168. return Adapter.m_hResultLastState;
  169. }
  170. if ( Adapter.m_ulAddressCount==0 )
  171. {
  172. //
  173. // We have a problem there is no IP address on this adapter
  174. //
  175. MYTRACE_ERROR("No address on adapter %d", nAdapterIndex);
  176. return E_FAIL;
  177. }
  178. //
  179. // Return the AdapterInfo to the caller
  180. //
  181. Adapter.m_pIAdapter->AddRef(); // The destructor of CAdapterAddress does a release on this interface so we need to pump it up by one
  182. *ppReceiveAdapter = Adapter.m_pIAdapter;
  183. bool bOriginalAddressIsOnTheEdgeAdapters = Adapter.FindAddress(*pulOriginalDestinationAddress);
  184. //
  185. // if pulOriginalDestinationAddress match one of the adapter on the edge box
  186. // then lookup for a remap port
  187. //
  188. if ( bOriginalAddressIsOnTheEdgeAdapters )
  189. {
  190. //
  191. // This may be an inbound
  192. //
  193. ULONG nRemapAddress;
  194. USHORT nRemapPort;
  195. HRESULT hr = g_pAlgController->GetNat()->LookupAdapterPortMapping(
  196. nAdapterIndex,
  197. m_Properties.eProtocol,
  198. *pulOriginalDestinationAddress,
  199. *pusOriginalDestinationPort,
  200. &nRemapAddress,
  201. &nRemapPort
  202. );
  203. if ( SUCCEEDED(hr) )
  204. {
  205. //
  206. // Theres a remap address/Port
  207. //
  208. *pulOriginalDestinationAddress = nRemapAddress;
  209. *pusOriginalDestinationPort = nRemapPort;
  210. MYTRACE("Remap destination to %s:%d", MYTRACE_IP(*pulOriginalDestinationAddress), ntohs(*pusOriginalDestinationPort));
  211. }
  212. else
  213. {
  214. //
  215. // This is just a soft error meaning no mapping where found we can still continue
  216. //
  217. MYTRACE("LookupAdapterPortMapping did not find a port maping %x", hr);
  218. }
  219. }
  220. return hr;
  221. }
  222. //
  223. // Need to remove any redirect that was set for this Adapter
  224. //
  225. HRESULT
  226. CPrimaryControlChannel::CancelRedirectsForAdapter(
  227. ULONG nAdapterIndex
  228. )
  229. {
  230. return m_CollectionRedirects.RemoveForAdapter(nAdapterIndex);
  231. }
  232. //
  233. //
  234. //
  235. HRESULT
  236. CPrimaryControlChannel::SetRedirect(
  237. ALG_ADAPTER_TYPE eAdapterType,
  238. ULONG nAdapterIndex,
  239. ULONG nAdapterAddress
  240. )
  241. {
  242. MYTRACE_ENTER("CPrimaryControlChannel::SetRedirect");
  243. HANDLE_PTR hCookie;
  244. HRESULT hr=S_OK;
  245. ULONG nFlags=NatRedirectFlagPortRedirect|NatRedirectFlagRestrictAdapter;
  246. ULONG nProtocol=0;
  247. ULONG nDestinationAddress=0;
  248. USHORT nDestinationPort=0;
  249. ULONG nSourceAddress=0;
  250. USHORT nSourcePort=0;
  251. //
  252. // What type of port is supplied
  253. //
  254. if ( m_Properties.eCaptureType == eALG_DESTINATION_CAPTURE )
  255. {
  256. MYTRACE("CAPTURE TYPE is eALG_DESTINATION_CAPTURE");
  257. nDestinationPort = m_Properties.usCapturePort;
  258. }
  259. if ( m_Properties.eCaptureType == eALG_SOURCE_CAPTURE )
  260. {
  261. MYTRACE("CAPTURE TYPE is eALG_SOURCE_CAPTURE");
  262. nFlags |= NatRedirectFlagSourceRedirect;
  263. nSourcePort = m_Properties.usCapturePort;
  264. }
  265. //
  266. // ADAPTER IS FIREWALL or SHARED
  267. //
  268. if ( (eAdapterType & eALG_FIREWALLED) || (eAdapterType & eALG_BOUNDARY) )
  269. {
  270. nFlags |= NatRedirectFlagSendOnly;
  271. MYTRACE("ADAPTER TYPE is %s %s",
  272. eAdapterType & eALG_FIREWALLED ? "FIREWALLED" : "",
  273. eAdapterType & eALG_BOUNDARY ? "SHARED" : ""
  274. );
  275. MYTRACE("Destination %s:%d", MYTRACE_IP(nDestinationAddress), ntohs(nDestinationPort));
  276. MYTRACE("Source %s:%d", MYTRACE_IP(nSourceAddress), ntohs(nSourcePort));
  277. MYTRACE("NewDestination %s:%d", MYTRACE_IP(m_Properties.ulListeningAddress), ntohs(m_Properties.usListeningPort));
  278. //
  279. // INBOUND Additional Redirect needed
  280. //
  281. if ( m_Properties.fCaptureInbound == TRUE)
  282. {
  283. MYTRACE("INBOUND requested - Lookup Remap port service to see if we should allow it");
  284. //
  285. // Create an additional Redirect for inbound from the Public side to the ICS box
  286. //
  287. //
  288. // before we allow the redirection
  289. // See if a maping was set by the user ("under the SERVICE Tab of ICS")
  290. //
  291. ULONG nRemapAddress;
  292. USHORT nRemapPort;
  293. hr = g_pAlgController->GetNat()->LookupAdapterPortMapping(
  294. nAdapterIndex,
  295. m_Properties.eProtocol,
  296. nDestinationAddress,
  297. nDestinationPort,
  298. &nRemapAddress,
  299. &nRemapPort
  300. );
  301. if ( SUCCEEDED(hr) )
  302. {
  303. MYTRACE("RemapAddress is %s:%d", MYTRACE_IP(nRemapAddress), ntohs(nRemapPort));
  304. hr = CreateInboundRedirect(nAdapterIndex);
  305. }
  306. else
  307. {
  308. MYTRACE_ERROR("LookupPortMappingAdapter Failed", hr);
  309. }
  310. }
  311. }
  312. else
  313. {
  314. //
  315. // ADAPTER IS PRIVATE
  316. //
  317. if ( eAdapterType & eALG_PRIVATE )
  318. {
  319. MYTRACE("ADAPTER TYPE is PRIVATE");
  320. CAdapterAddresses PrivateAdapter(nAdapterIndex);
  321. if ( PrivateAdapter.m_ulAddressCount > 0 )
  322. {
  323. MYTRACE("Create Shadow redirect between any private computers to private adapter %s", MYTRACE_IP(PrivateAdapter.m_arAddresses[0]) );
  324. hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
  325. NatRedirectFlagReceiveOnly,
  326. nAdapterIndex,
  327. (UCHAR) m_Properties.eProtocol,
  328. PrivateAdapter.m_arAddresses[0], // ULONG DestinationAddress,
  329. nDestinationPort, // USHORT DestinationPort,
  330. 0, // ULONG SourceAddress,
  331. 0, // USHORT SourcePort,
  332. PrivateAdapter.m_arAddresses[0], // ULONG NewDestinationAddress
  333. nDestinationPort, // USHORT NewDestinationPort
  334. 0, // ULONG NewSourceAddress,
  335. 0, // USHORT NewSourcePort,
  336. &hCookie
  337. );
  338. }
  339. if ( SUCCEEDED(hr) )
  340. {
  341. hr = m_CollectionRedirects.Add(hCookie, nAdapterIndex, FALSE); // Cache the Dynamic redirect Handle
  342. }
  343. else
  344. {
  345. MYTRACE_ERROR("Failed to createDynamicRedirect PRIVATE", hr);
  346. }
  347. nFlags |= NatRedirectFlagReceiveOnly;
  348. if ( m_Properties.eCaptureType == eALG_SOURCE_CAPTURE )
  349. {
  350. nFlags |= NatRedirectFlagSourceRedirect;
  351. }
  352. }
  353. }
  354. MYTRACE("CreateDynamicRedirect for OUTBOUND");
  355. hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
  356. nFlags,
  357. nAdapterIndex,
  358. (UCHAR) m_Properties.eProtocol,
  359. nDestinationAddress, // ULONG DestinationAddress,
  360. nDestinationPort, // USHORT DestinationPort,
  361. nSourceAddress, // ULONG SourceAddress,
  362. nSourcePort, // USHORT SourcePort,
  363. m_Properties.ulListeningAddress, // ULONG NewDestinationAddress
  364. m_Properties.usListeningPort, // USHORT NewDestinationPort
  365. 0, // ULONG NewSourceAddress,
  366. 0, // USHORT NewSourcePort,
  367. &hCookie
  368. );
  369. if ( SUCCEEDED(hr) )
  370. {
  371. hr = m_CollectionRedirects.Add(hCookie, nAdapterIndex, FALSE); // Cache the Dynamic redirect Handle
  372. }
  373. else
  374. {
  375. MYTRACE_ERROR("Failed to createDynamicRedirect PRIVATE", hr);
  376. }
  377. return hr;
  378. }
  379. HRESULT
  380. CPrimaryControlChannel::CreateInboundRedirect(
  381. ULONG nAdapterIndex
  382. )
  383. {
  384. HRESULT hr;
  385. HANDLE_PTR hCookie;
  386. MYTRACE_ENTER("CPrimaryControlChannel::SetRedirect");
  387. hr = g_pAlgController->GetNat()->CreateDynamicRedirect(
  388. NatRedirectFlagPortRedirect|NatRedirectFlagReceiveOnly|NatRedirectFlagRestrictAdapter,
  389. nAdapterIndex,
  390. (UCHAR)m_Properties.eProtocol,
  391. 0, // ULONG DestinationAddress,
  392. m_Properties.usCapturePort, // USHORT DestinationPort,
  393. 0, // ULONG SourceAddress,
  394. 0, // USHORT SourcePort,
  395. m_Properties.ulListeningAddress, // ULONG NewDestinationAddress
  396. m_Properties.usListeningPort, // USHORT NewDestinationPort
  397. 0, // ULONG NewSourceAddress,
  398. 0, // USHORT NewSourcePort,
  399. &hCookie
  400. );
  401. if ( SUCCEEDED(hr) )
  402. {
  403. hr = m_CollectionRedirects.Add(hCookie, nAdapterIndex, TRUE); // Cache the Dynamic redirect Handle
  404. }
  405. else
  406. {
  407. MYTRACE_ERROR("Failed to CreateDynamicRedirect INBOUND", hr);
  408. }
  409. return hr;
  410. }