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.

1263 lines
32 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. rmALG.cpp
  5. Abstract:
  6. This module contains routines for the ALG Manager module's
  7. private interface to be used only by the ALG.exe manager.
  8. Author:
  9. JPDup 10-Nov-2000
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include <atlbase.h>
  14. extern CComModule _Module;
  15. #include <atlcom.h>
  16. #include "Alg.h"
  17. #include "NatPrivateAPI_Imp.h"
  18. #include <MyTrace.h>
  19. #include <Rtutils.h>
  20. extern HANDLE AlgPortReservationHandle; // see rmALG.CPP
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CNat
  23. //
  24. // Standard destructor
  25. //
  26. CNat::~CNat(void)
  27. {
  28. MYTRACE_ENTER("CNat::~CNat(void)");
  29. if ( m_hTranslatorHandle )
  30. NatShutdownTranslator(m_hTranslatorHandle);
  31. if ( m_pSidLocalService )
  32. {
  33. MYTRACE("Free m_pSidLocalService");
  34. LocalFree(m_pSidLocalService);
  35. }
  36. if ( m_pSidLocalSystem )
  37. {
  38. MYTRACE("Free m_pSidLocalSystem");
  39. LocalFree(m_pSidLocalSystem);
  40. }
  41. }
  42. bool
  43. GetSecuritySID(
  44. WELL_KNOWN_SID_TYPE WellKnownSidToCreate,
  45. PSID& pSidToReturn
  46. )
  47. /*++
  48. Routine Description:
  49. Creates a SID from a specified well know SID
  50. Arguments:
  51. WellKnownSidToCreate - Specify the well know SID to create from
  52. pSidToReturn - pointer that will be allocated and populated with the SID attributes
  53. Return Value:
  54. bool - true is the SID was successfully created
  55. - false one or more error occurred
  56. Environment:
  57. The routine will allocate the side so the caller is responsible for doing a LocalFree on the returned pSidToReturn pointer
  58. --*/
  59. {
  60. MYTRACE_ENTER("CNat::GetSecuritySID()");
  61. //
  62. // If theasked SID is not already cached then create it
  63. //
  64. if ( NULL == pSidToReturn )
  65. {
  66. DWORD dwSizeOfSid = SECURITY_MAX_SID_SIZE;
  67. // Allocate enough memory for the largest possible SID.
  68. if ( !(pSidToReturn = LocalAlloc(LMEM_FIXED, dwSizeOfSid)) )
  69. {
  70. MYTRACE_ERROR("LocalAlloc got get LocalService", GetLastError());
  71. return false;
  72. }
  73. BOOL bRet = CreateWellKnownSid(
  74. WellKnownSidToCreate,
  75. NULL,
  76. pSidToReturn,
  77. &dwSizeOfSid
  78. );
  79. if ( !bRet )
  80. {
  81. MYTRACE_ERROR("From CreateWellKnownSid(LocalService)", GetLastError());
  82. LocalFree(pSidToReturn);
  83. pSidToReturn = NULL;
  84. return false;
  85. }
  86. }
  87. return true;
  88. }
  89. bool
  90. CNat::IsTokenPartOfWellKnowSid(
  91. HANDLE pTokenToCheck,
  92. WELL_KNOWN_SID_TYPE WellKnownSidToCheckAgainst,
  93. PSID& pSidToCache
  94. )
  95. /*++
  96. Routine Description:
  97. Helper function that create/gets a well know sid and verify that the supplied token is a member of that SID
  98. Arguments:
  99. pTokenToCheck - Token that will be inspected
  100. WellKnownSidToCreate - Specify the well know SID to check against
  101. pSidToCache - pointer to a SID that you will need to LocalFree when done
  102. Return Value:
  103. bool - true if the supplied token is member of the WellKnowSID
  104. - false one or more error occurred
  105. Environment:
  106. The caller of the
  107. --*/
  108. {
  109. MYTRACE_ENTER("IsTokenPartOfWellKnowSid()");
  110. BOOL bRet;
  111. m_AutoCS_SIDAllocation.Lock();
  112. bRet = GetSecuritySID(
  113. WellKnownSidToCheckAgainst,
  114. pSidToCache
  115. );
  116. m_AutoCS_SIDAllocation.Unlock();
  117. if ( !bRet )
  118. {
  119. MYTRACE("GetSecuritySID failed");
  120. return false;
  121. }
  122. BOOL bIsMember;
  123. bRet = CheckTokenMembership(
  124. pTokenToCheck,
  125. pSidToCache,
  126. &bIsMember
  127. );
  128. if ( !bRet )
  129. {
  130. MYTRACE_ERROR("Call to CheckTokenMembership failed", GetLastError());
  131. return false;
  132. }
  133. if ( FALSE == bIsMember )
  134. {
  135. MYTRACE("Token %d is not a member of SID %d", pTokenToCheck, pSidToCache);
  136. return false;
  137. }
  138. return true;
  139. }
  140. bool
  141. CNat::IsClientAllowedToCallUs()
  142. /*++
  143. Routine Description:
  144. Verify that the current caller is part of the LocalService or LocalSystem group
  145. Arguments:
  146. none
  147. Return Value:
  148. bool - true = Part of one or the group
  149. - false = access should be denied
  150. Environment:
  151. The routine runs will allocate 2 sid and they must be freed when the CNat object is released
  152. see member variables m_pSidLocalService and m_pSidLocalSystem;
  153. --*/
  154. {
  155. MYTRACE_ENTER("CNat::IsClientAllowedToCallUs()");
  156. HRESULT hr;
  157. hr = CoImpersonateClient();
  158. if ( FAILED(hr) )
  159. {
  160. MYTRACE_ERROR("CoImpersonateClient() failed", hr);
  161. return false;
  162. }
  163. HANDLE hClientToken = NULL;
  164. bool bClientIsAllowedAccess = false;
  165. if ( OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hClientToken) )
  166. {
  167. //
  168. // Try with LocalService, this is the normal expected scenario
  169. //
  170. bClientIsAllowedAccess = IsTokenPartOfWellKnowSid(
  171. hClientToken,
  172. WinLocalServiceSid,
  173. m_pSidLocalService
  174. );
  175. if ( bClientIsAllowedAccess )
  176. {
  177. MYTRACE("Client is member of the LOCAL_SERVICE group");
  178. }
  179. else
  180. {
  181. //
  182. // For debugging purpose sometime you need to set the ALG service to LocalSystem
  183. // in this case we need to grant access also to LocalSystem account
  184. //
  185. bClientIsAllowedAccess = IsTokenPartOfWellKnowSid(
  186. hClientToken,
  187. WinLocalSystemSid,
  188. m_pSidLocalSystem
  189. );
  190. if ( bClientIsAllowedAccess )
  191. {
  192. MYTRACE("Client is member of the LOCAL_SYSTEM group");
  193. }
  194. else
  195. {
  196. MYTRACE("Client is NOT member of LOCAL_SERVICE or LOCAL_SYSTEM group");
  197. }
  198. }
  199. //
  200. // No need for this handle anymore
  201. //
  202. CloseHandle( hClientToken );
  203. }
  204. else
  205. {
  206. MYTRACE_ERROR("Could not OpenThreadToken", GetLastError());
  207. }
  208. //
  209. // Set security context back
  210. //
  211. hr = CoRevertToSelf();
  212. if ( FAILED(hr) )
  213. {
  214. MYTRACE_ERROR("from CoRevertToSelf()", hr);
  215. return false;;
  216. }
  217. return bClientIsAllowedAccess;
  218. }
  219. #define RETURN_IF_CLIENT_NOT_LOCAL_SERVICE if ( !IsClientAllowedToCallUs() ) { return E_ACCESSDENIED; };
  220. STDMETHODIMP
  221. CNat::CreateRedirect(
  222. IN ULONG Flags,
  223. IN UCHAR Protocol,
  224. IN ULONG DestinationAddress,
  225. IN USHORT DestinationPort,
  226. IN ULONG SourceAddress,
  227. IN USHORT SourcePort,
  228. IN ULONG NewDestinationAddress,
  229. IN USHORT NewDestinationPort,
  230. IN ULONG NewSourceAddress,
  231. IN USHORT NewSourcePort,
  232. IN ULONG RestrictAdapterIndex,
  233. IN DWORD_PTR dwAlgProcessId,
  234. IN HANDLE_PTR hCreateEvent,
  235. IN HANDLE_PTR hDeleteEvent
  236. )
  237. {
  238. /*++
  239. Routine Description:
  240. Creates a Redirect PORT
  241. Arguments:
  242. Flags - Specifies options for the redirect
  243. Protocol - IP protocol of the session to be redirected
  244. DestinationAddress - destination endpoint of the session to be redirected
  245. DestinationPort - "
  246. SourceAddress - source endpoint of the session to be redirected
  247. SourcePort - "
  248. NewDestinationAddress - replacement destination endpoint for the session
  249. NewDestinationPort - "
  250. NewSourceAddress - replacement source endpoint for the session
  251. NewSourcePort - "
  252. RestrictAdapterIndex - optionally specifies the adapter index that this redirect should be restricted to
  253. hCreateEvent - optionally specifies an event to be signalled when a session matches the redirect.
  254. hDeleteEvent - optionally specifies an event to be signalled when a session is delete.
  255. Return Value:
  256. HRESULT - S_OK for success or and HRESULT error
  257. Environment:
  258. The routine runs in the context of the ALG Manager and cant only be invoke by the ALG.EXE
  259. --*/
  260. MYTRACE_ENTER("CNat::CreateRedirect");
  261. RETURN_IF_CLIENT_NOT_LOCAL_SERVICE;
  262. MYTRACE("ProtocolPublic %d, ProtocolInternal %d", Protocol, ProtocolConvertToNT(Protocol));
  263. MYTRACE("Destination %s:%d", MYTRACE_IP(DestinationAddress), ntohs(DestinationPort));
  264. MYTRACE("Source %s:%d", MYTRACE_IP(SourceAddress), ntohs(SourcePort));
  265. MYTRACE("NewDestination %s:%d", MYTRACE_IP(NewDestinationAddress), ntohs(NewDestinationPort));
  266. MYTRACE("NewSource %s:%d", MYTRACE_IP(NewSourceAddress), ntohs(NewSourcePort));
  267. HANDLE hThisEventForCreate=NULL;
  268. HANDLE hThisEventForDelete=NULL;
  269. //
  270. // Duplicate the requested Event handles
  271. //
  272. if ( dwAlgProcessId )
  273. {
  274. HANDLE hAlgProcess = OpenProcess(
  275. PROCESS_DUP_HANDLE, // access flag
  276. false, // handle inheritance option
  277. (DWORD)dwAlgProcessId // process identifier
  278. );
  279. if ( !hAlgProcess )
  280. {
  281. MYTRACE_ERROR("Could not open the Process ID of ALG.exe", 0);
  282. return HRESULT_FROM_WIN32(GetLastError());
  283. }
  284. if ( hCreateEvent )
  285. {
  286. //
  287. // a create event was requested
  288. //
  289. if ( !DuplicateHandle(
  290. hAlgProcess,
  291. (HANDLE)hCreateEvent,
  292. GetCurrentProcess(),
  293. &hThisEventForCreate,
  294. 0,
  295. FALSE,
  296. DUPLICATE_SAME_ACCESS
  297. )
  298. )
  299. {
  300. MYTRACE_ERROR("DuplicateHandle on the CREATE handle", 0);
  301. CloseHandle(hAlgProcess);
  302. return HRESULT_FROM_WIN32(GetLastError());
  303. }
  304. MYTRACE("New DuplicateHandle 'CREATE'=%d base on=%d", hThisEventForCreate, hCreateEvent);
  305. }
  306. else
  307. {
  308. MYTRACE("No event for Creation requested");
  309. }
  310. if ( hDeleteEvent )
  311. {
  312. //
  313. // a delete event was requested
  314. //
  315. if ( !DuplicateHandle(
  316. hAlgProcess,
  317. (HANDLE)hDeleteEvent,
  318. GetCurrentProcess(),
  319. &hThisEventForDelete,
  320. 0,
  321. FALSE,
  322. DUPLICATE_SAME_ACCESS
  323. )
  324. )
  325. {
  326. MYTRACE_ERROR("DuplicateHandle on the DELETE handle", 0);
  327. if ( hThisEventForCreate )
  328. CloseHandle(hThisEventForCreate);
  329. CloseHandle(hAlgProcess);
  330. return HRESULT_FROM_WIN32(GetLastError());
  331. }
  332. MYTRACE("New DuplicateHandle 'DELETE'=%d base on=%d", hThisEventForDelete, hDeleteEvent);
  333. }
  334. else
  335. {
  336. MYTRACE("No event for Delete requested");
  337. }
  338. CloseHandle(hAlgProcess);
  339. }
  340. else
  341. {
  342. MYTRACE("NO EVENT Requested");
  343. }
  344. ULONG Error = NatCreateRedirectEx(
  345. GetTranslatorHandle(),
  346. Flags,
  347. ProtocolConvertToNT(Protocol),
  348. DestinationAddress,
  349. DestinationPort,
  350. SourceAddress,
  351. SourcePort,
  352. NewDestinationAddress,
  353. NewDestinationPort,
  354. NewSourceAddress,
  355. NewSourcePort,
  356. RestrictAdapterIndex,
  357. IPNATAPI_SET_EVENT_ON_COMPLETION, // Special constant to use Event vs. a callback to a CompletionRoutine
  358. (PVOID)hThisEventForDelete, //HANDLE for DELETE sessions
  359. (HANDLE)hThisEventForCreate //HANDLE NotifyEvent OPTIONAL
  360. );
  361. if ( hThisEventForCreate )
  362. CloseHandle(hThisEventForCreate);
  363. if ( hThisEventForDelete )
  364. CloseHandle(hThisEventForDelete);
  365. if ( ERROR_SUCCESS != Error )
  366. {
  367. MYTRACE_ERROR("From NatCreateRedirectEx", Error);
  368. return HRESULT_FROM_WIN32(Error);
  369. }
  370. return S_OK;
  371. }
  372. //
  373. //
  374. //
  375. STDMETHODIMP
  376. CNat::CancelRedirect(
  377. IN UCHAR Protocol,
  378. IN ULONG DestinationAddress,
  379. IN USHORT DestinationPort,
  380. IN ULONG SourceAddress,
  381. IN USHORT SourcePort,
  382. IN ULONG NewDestinationAddress,
  383. IN USHORT NewDestinationPort,
  384. IN ULONG NewSourceAddress,
  385. IN USHORT NewSourcePort
  386. )
  387. /*++
  388. Routine Description:
  389. Cancel a Redirect
  390. Arguments:
  391. Protocol - IP protocol of the session to be redirected eALG_TCP || eALG_UDP
  392. DestinationAddress - destination endpoint of the session to be redirected
  393. DestinationPort - "
  394. SourceAddress - source endpoint of the session to be redirected
  395. SourcePort - "
  396. NewDestinationAddress - replacement destination endpoint for the session
  397. NewDestinationPort - "
  398. NewSourceAddress - replacement source endpoint for the session
  399. NewSourcePort - "
  400. Return Value:
  401. HRESULT - S_OK for success or and HRESULT error
  402. Environment:
  403. The routine runs in the context of the ALG Manager and cant only be invoke by the ALG.EXE
  404. --*/
  405. {
  406. MYTRACE_ENTER("CNat::CancelRedirect");
  407. RETURN_IF_CLIENT_NOT_LOCAL_SERVICE
  408. MYTRACE("Protocol Public %d, Internal %d", Protocol, ProtocolConvertToNT(Protocol));
  409. MYTRACE("Destination %s:%d", MYTRACE_IP(DestinationAddress), ntohs(DestinationPort));
  410. MYTRACE("Source %s:%d", MYTRACE_IP(SourceAddress), ntohs(SourcePort));
  411. MYTRACE("NewDestination %s:%d", MYTRACE_IP(NewDestinationAddress), ntohs(NewDestinationPort));
  412. MYTRACE("NewSource %s:%d", MYTRACE_IP(NewSourceAddress), ntohs(NewSourcePort));
  413. ULONG Error = NatCancelRedirect(
  414. GetTranslatorHandle(),
  415. ProtocolConvertToNT(Protocol),
  416. DestinationAddress,
  417. DestinationPort,
  418. SourceAddress,
  419. SourcePort,
  420. NewDestinationAddress,
  421. NewDestinationPort,
  422. NewSourceAddress,
  423. NewSourcePort
  424. );
  425. if ( ERROR_SUCCESS != Error )
  426. {
  427. MYTRACE_ERROR("From NatCancelRedirect", Error);
  428. return HRESULT_FROM_WIN32(Error);
  429. }
  430. return S_OK;
  431. }
  432. STDMETHODIMP
  433. CNat::CreateDynamicRedirect(
  434. IN ULONG Flags,
  435. IN ULONG nAdapterIndex,
  436. IN UCHAR Protocol,
  437. IN ULONG DestinationAddress,
  438. IN USHORT DestinationPort,
  439. IN ULONG SourceAddress,
  440. IN USHORT SourcePort,
  441. IN ULONG NewDestinationAddress,
  442. IN USHORT NewDestinationPort,
  443. IN ULONG NewSourceAddress,
  444. IN USHORT NewSourcePort,
  445. OUT HANDLE_PTR* pDynamicRedirectHandle
  446. )
  447. /*++
  448. Routine Description:
  449. Cancel a dynamic Redirect, by seting up a dynamic redirection any time a adapter is created the redirection will be
  450. applied to that new adapter.
  451. Arguments:
  452. Flags - Specifies options for the redirect
  453. nAdapterIndex - Index of the IP adapter (Same as the index found using the cmd line "ROUTE PRINT")
  454. Protocol - IP protocol of the session to be redirected
  455. DestinationAddress - destination endpoint of the session to be redirected
  456. DestinationPort - "
  457. SourceAddress - source endpoint of the session to be redirected
  458. SourcePort - "
  459. NewDestinationAddress - replacement destination endpoint for the session
  460. NewDestinationPort - "
  461. NewSourceAddress - replacement source endpoint for the session
  462. NewSourcePort - "
  463. pDynamicRedirectHandle - This routine will populate this field with the handle (Cookie) for the purpose of canceling
  464. this DynamicRedirect
  465. Return Value:
  466. HRESULT - S_OK for success or and HRESULT error
  467. Environment:
  468. The routine runs in the context of the ALG Manager and cant only be invoke by the ALG.EXE
  469. and is use via the public api CreatePrimaryControlChannel (See ALG.EXE)
  470. --*/
  471. {
  472. MYTRACE_ENTER("CNat::CreateDynamicRedirect");
  473. RETURN_IF_CLIENT_NOT_LOCAL_SERVICE;
  474. ASSERT(pDynamicRedirectHandle!=NULL);
  475. #if defined(DBG) || defined(_DEBUG)
  476. MYTRACE("Flags %d", Flags);
  477. MYTRACE("Protocol Public %d Internal %d", Protocol, ProtocolConvertToNT(Protocol));
  478. if ( Flags & NatRedirectFlagNoTimeout )
  479. MYTRACE(" NatRedirectFlagNoTimeout");
  480. if ( Flags & NatRedirectFlagUnidirectional )
  481. MYTRACE(" NatRedirectFlagUnidirectional");
  482. if ( Flags & NatRedirectFlagRestrictSource )
  483. MYTRACE(" NatRedirectFlagRestrictSource");
  484. if ( Flags & NatRedirectFlagPortRedirect )
  485. MYTRACE(" NatRedirectFlagPortRedirect");
  486. if ( Flags & NatRedirectFlagReceiveOnly )
  487. MYTRACE(" NatRedirectFlagReceiveOnly");
  488. if ( Flags & NatRedirectFlagLoopback )
  489. MYTRACE(" NatRedirectFlagLoopback");
  490. if ( Flags & NatRedirectFlagSendOnly )
  491. MYTRACE(" NatRedirectFlagSendOnly");
  492. if ( Flags & NatRedirectFlagRestrictAdapter )
  493. MYTRACE(" NatRedirectFlagRestrictAdapter");
  494. if ( Flags & NatRedirectFlagSourceRedirect )
  495. MYTRACE(" NatRedirectFlagSourceRedirect");
  496. MYTRACE("AdapterIndex %d", nAdapterIndex);
  497. in_addr tmpAddr;
  498. tmpAddr.s_addr = DestinationAddress;
  499. MYTRACE("Destination %s:%d", inet_ntoa(tmpAddr), ntohs(DestinationPort));
  500. tmpAddr.s_addr = SourceAddress;
  501. MYTRACE("Source %s:%d", inet_ntoa(tmpAddr), ntohs(SourcePort));
  502. tmpAddr.s_addr = NewDestinationAddress;
  503. MYTRACE("NewDestination %s:%d", inet_ntoa(tmpAddr), ntohs(NewDestinationPort));
  504. tmpAddr.s_addr = NewSourceAddress;
  505. MYTRACE("NewSource %s:%d", inet_ntoa(tmpAddr), ntohs(NewSourcePort));
  506. #endif
  507. MYTRACE("About to call NatCreateDynamicFullRedirect");
  508. ULONG nRestrictSourceAddress = 0;
  509. if ( NatRedirectFlagRestrictSource & Flags )
  510. {
  511. MYTRACE("NatRedirectFlagRestrictSource flags is set");
  512. nRestrictSourceAddress = SourceAddress;
  513. SourceAddress = 0;
  514. }
  515. ULONG Error = NatCreateDynamicFullRedirect(
  516. Flags|NatRedirectFlagLoopback,
  517. ProtocolConvertToNT(Protocol),
  518. DestinationAddress,
  519. DestinationPort,
  520. SourceAddress,
  521. SourcePort,
  522. NewDestinationAddress,
  523. NewDestinationPort,
  524. NewSourceAddress,
  525. NewSourcePort,
  526. nRestrictSourceAddress, //ULONG RestrictSourceAddress OPTIONAL,
  527. nAdapterIndex, //ULONG RestrictAdapterIndex OPTIONAL,
  528. 0, //MinimumBacklog OPTIONAL,
  529. (PHANDLE)pDynamicRedirectHandle
  530. );
  531. if ( ERROR_SUCCESS != Error )
  532. {
  533. MYTRACE_ERROR("Failed NatCreateDynamicFullRedirect", Error);
  534. return HRESULT_FROM_WIN32(Error);
  535. }
  536. //
  537. // Cache the DynamicRedirect cookie before we hand it out to the caller
  538. // this list of cache cookie will be used to validate when a caller ask
  539. // us to Cancel a redirect
  540. //
  541. m_AutoCS_DynamicRedirect.Lock();
  542. BOOL bAddedToListOFOutstandingRedirectHandle = m_ListOfOutstandingRedirects.Add(*pDynamicRedirectHandle);
  543. m_AutoCS_DynamicRedirect.Unlock();
  544. if ( bAddedToListOFOutstandingRedirectHandle )
  545. {
  546. MYTRACE("Added %d to the list of outstanding redirects for a total of %d redirects", *pDynamicRedirectHandle, m_ListOfOutstandingRedirects.GetSize());
  547. }
  548. else
  549. {
  550. MYTRACE_ERROR("Could add to list of Outstanding Redirect handle", GetLastError());
  551. }
  552. MYTRACE("Call to NatCreateDynamicFullRedirect worked");
  553. return S_OK;;
  554. }
  555. STDMETHODIMP
  556. CNat::CancelDynamicRedirect(
  557. IN HANDLE_PTR DynamicRedirectHandle
  558. )
  559. /*++
  560. Routine Description:
  561. This routine is called to cancel the given dynamic redirect.
  562. by calling the NatApi version of this function
  563. Arguments:
  564. DynamicRedirectHandle - the handle to the dynamic redirect to be cancelled
  565. Return Value:
  566. HRESULT - S_OK for success or and HRESULT error
  567. --*/
  568. {
  569. MYTRACE_ENTER("CNat::CancelDynamicRedirect");
  570. RETURN_IF_CLIENT_NOT_LOCAL_SERVICE;
  571. //
  572. // Is the caller passing a valid DynamicRedirect handle
  573. //
  574. m_AutoCS_DynamicRedirect.Lock();
  575. MYTRACE("Remove %d from the outstanding list of redirects, the before size is %d", DynamicRedirectHandle, m_ListOfOutstandingRedirects.GetSize());
  576. BOOL bFoundAndRemoved = m_ListOfOutstandingRedirects.Remove(DynamicRedirectHandle);
  577. m_AutoCS_DynamicRedirect.Unlock();
  578. if ( bFoundAndRemoved )
  579. {
  580. MYTRACE("Removed succesfull");
  581. }
  582. else
  583. {
  584. MYTRACE_ERROR("pDynamicRedirectHandle is not valid", GetLastError());
  585. return E_INVALIDARG;
  586. }
  587. //
  588. // We are good to go release this redirect
  589. //
  590. ULONG Error = NatCancelDynamicRedirect((PHANDLE)DynamicRedirectHandle);
  591. if ( ERROR_SUCCESS != Error )
  592. {
  593. MYTRACE_ERROR("Failed NatCancelDynamicRedirect", Error);
  594. return HRESULT_FROM_WIN32(Error);
  595. }
  596. return S_OK;
  597. }
  598. STDMETHODIMP
  599. CNat::GetBestSourceAddressForDestinationAddress(
  600. IN ULONG ulDestinationAddress,
  601. IN BOOL fDemandDial,
  602. OUT ULONG* pulBestSrcAddress
  603. )
  604. /*++
  605. Routine Description:
  606. We create a temporary UDP socket, connect the socket to the
  607. actual client's IP address, extract the IP address to which
  608. the socket is implicitly bound by the TCP/IP driver, and
  609. discard the socket. This leaves us with the exact IP address
  610. that we need to use to contact the client.
  611. Arguments:
  612. ulDestinationAddress,
  613. fDemandDial,
  614. pulBestSrcAddress
  615. Return Value:
  616. HRESULT - S_OK for success
  617. Environment:
  618. ALG module will call this method to:
  619. --*/
  620. {
  621. MYTRACE_ENTER("CNat::GetBestSourceAddressForDestinationAddress");
  622. RETURN_IF_CLIENT_NOT_LOCAL_SERVICE;
  623. if ( !pulBestSrcAddress )
  624. {
  625. MYTRACE_ERROR("pulBestSrcAddress not supplied",0);
  626. return E_INVALIDARG;
  627. }
  628. SOCKADDR_IN SockAddr;
  629. SockAddr.sin_family = AF_INET;
  630. SockAddr.sin_port = 0;
  631. SockAddr.sin_addr.s_addr = ulDestinationAddress;
  632. ULONG Length = sizeof(SockAddr);
  633. SOCKET UdpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  634. if ( INVALID_SOCKET == UdpSocket
  635. || SOCKET_ERROR == connect(UdpSocket, (PSOCKADDR)&SockAddr, sizeof(SockAddr))
  636. || SOCKET_ERROR == getsockname(UdpSocket, (PSOCKADDR)&SockAddr, (int*)&Length)
  637. )
  638. {
  639. ULONG nError = WSAGetLastError();
  640. if ( nError == WSAEHOSTUNREACH )
  641. {
  642. if ( fDemandDial )
  643. nError = RasAutoDialSharedConnection();
  644. if ( ERROR_SUCCESS != nError )
  645. {
  646. MYTRACE_ERROR(" RasAutoDialSharedConnection failed [%d]", nError);
  647. if ( UdpSocket != INVALID_SOCKET )
  648. {
  649. closesocket(UdpSocket);
  650. }
  651. return HRESULT_FROM_WIN32(nError);
  652. }
  653. }
  654. else
  655. {
  656. MYTRACE_ERROR("error %d routing endpoint %d using UDP", nError);
  657. if (UdpSocket != INVALID_SOCKET)
  658. {
  659. closesocket(UdpSocket);
  660. }
  661. return HRESULT_FROM_WIN32(nError);
  662. }
  663. }
  664. *pulBestSrcAddress = SockAddr.sin_addr.s_addr;
  665. closesocket(UdpSocket);
  666. return S_OK;
  667. }
  668. STDMETHODIMP CNat::LookupAdapterPortMapping(
  669. IN ULONG ulAdapterIndex,
  670. IN UCHAR Protocol,
  671. IN ULONG ulDestinationAddress,
  672. IN USHORT usDestinationPort,
  673. OUT ULONG* pulRemapAddress,
  674. OUT USHORT* pusRemapPort
  675. )
  676. /*++
  677. Routine Description:
  678. Call NAT port maping to ge the real destination for the port
  679. This ofcourse is the use has set some maping in the SharedConnection or Firewalled adapter on the Service Tab.
  680. Arguments:
  681. ulAdapterIndex - Index of the IP adapter of the session.
  682. Protocol - eALG_PROTOCOL_UDP, eALG_PROTOCOL_TCP
  683. DestinationAddress - the edge public adapter address
  684. DestinationPort - the edge public adapter port
  685. RemapAddres - The address where that the user itended this port to go to (Private computer on the private lan)
  686. SourcePort - Should be the same as the DestinationPort for future it may be different.
  687. Return Value:
  688. HRESULT - S_OK if it worked or E_FAIL if no maping was found
  689. --*/
  690. {
  691. MYTRACE_ENTER("LookupAdapterPortMapping");
  692. RETURN_IF_CLIENT_NOT_LOCAL_SERVICE;
  693. MYTRACE("AdapterIndex %d Protocol %d DestAddress %s:%d", ulAdapterIndex, ProtocolConvertToNT(Protocol), MYTRACE_IP(ulDestinationAddress), ntohs(usDestinationPort));
  694. IP_NAT_PORT_MAPPING PortMapping;
  695. ULONG Error = NatLookupPortMappingAdapter(
  696. ulAdapterIndex,
  697. ProtocolConvertToNT(Protocol),
  698. ulDestinationAddress,
  699. usDestinationPort,
  700. &PortMapping
  701. );
  702. if ( Error )
  703. {
  704. MYTRACE_ERROR("from NatLookupPortMappingAdapter", Error);
  705. return HRESULT_FROM_WIN32(Error);
  706. }
  707. *pulRemapAddress = PortMapping.PrivateAddress;
  708. *pusRemapPort = PortMapping.PrivatePort;
  709. return S_OK;
  710. }
  711. STDMETHODIMP CNat::GetOriginalDestinationInformation(
  712. IN UCHAR Protocol,
  713. IN ULONG ulDestinationAddress,
  714. IN USHORT usDestinationPort,
  715. IN ULONG ulSourceAddress,
  716. IN USHORT usSourcePort,
  717. OUT ULONG* pulOriginalDestinationAddress,
  718. OUT USHORT* pusOriginalDestinationPort,
  719. OUT ULONG* pulAdapterIndex
  720. )
  721. /*++
  722. Routine Description:
  723. Determine the original destination endpoint of a session that is redirected to.
  724. Arguments:
  725. DestinationAddress - destination endpoint of the session to be redirected
  726. DestinationPort - "
  727. SourceAddress - source endpoint of the session to be redirected
  728. SourcePort - "
  729. NewDestinationAddress - replacement destination endpoint for the session
  730. NewDestinationPort - "
  731. NewSourceAddress - replacement source endpoint for the session
  732. NewSourcePort - "
  733. pulOriginalDestinationAddress - Returns the original address of the destination (Where the caller realy wanted to go)
  734. pusOriginalDestinationPort - Returns the original port of the destination
  735. pulAdapterIndex - Index of the IP adapter of the session.
  736. Return Value:
  737. HRESULT - S_OK if it worked or E_FAIL
  738. --*/
  739. {
  740. MYTRACE_ENTER("CNat::GetOriginalDestinationInformation");
  741. RETURN_IF_CLIENT_NOT_LOCAL_SERVICE;
  742. MYTRACE("Destination %s:%d", MYTRACE_IP(ulDestinationAddress), ntohs(usDestinationPort));
  743. MYTRACE("Address %s:%d", MYTRACE_IP(ulSourceAddress), ntohs(usSourcePort));
  744. ASSERT(pulOriginalDestinationAddress!=NULL);
  745. ASSERT(pusOriginalDestinationPort!=NULL);
  746. ASSERT(pulAdapterIndex!=NULL);
  747. IP_NAT_SESSION_MAPPING_KEY_EX Information;
  748. ULONG ulSizeOfInformation = sizeof(IP_NAT_SESSION_MAPPING_KEY_EX);
  749. ULONG Error = NatLookupAndQueryInformationSessionMapping(
  750. GetTranslatorHandle(),
  751. ProtocolConvertToNT(Protocol),
  752. ulDestinationAddress,
  753. usDestinationPort,
  754. ulSourceAddress,
  755. usSourcePort,
  756. &Information,
  757. &ulSizeOfInformation,
  758. NatKeySessionMappingExInformation
  759. );
  760. if ( ERROR_SUCCESS != Error )
  761. {
  762. MYTRACE_ERROR("Call to NatLookupAndQueryInformationMapping", Error);
  763. return HRESULT_FROM_WIN32(Error);
  764. }
  765. MYTRACE("Original Index %d Address:Port %s:%d", Information.AdapterIndex, MYTRACE_IP(Information.DestinationAddress), ntohs(Information.DestinationPort));
  766. *pulOriginalDestinationAddress = Information.DestinationAddress;
  767. *pusOriginalDestinationPort = Information.DestinationPort;
  768. *pulAdapterIndex = Information.AdapterIndex;
  769. return S_OK;
  770. }
  771. STDMETHODIMP CNat::ReservePort(
  772. IN USHORT PortCount,
  773. OUT PUSHORT pReservedPortBase
  774. )
  775. /*++
  776. Routine Description:
  777. Call the into the NAP api to reserve the required port on behave of the ALG module.
  778. Arguments:
  779. PortCount - Number of port to reserve
  780. pReservedPortBase - Starting number of the range of port reserved. example ReserePort(3, &) would save 5000,5001,5002 and return 5000 as base
  781. Return Value:
  782. HRESULT - S_OK if it worked or E_FAIL
  783. Environment:
  784. Private interface between rmALG and ALG.EXE
  785. ALG expose a more simple interface to reserve at Port
  786. in turn it call this private interface that end up calling the more complex NatApi
  787. --*/
  788. {
  789. MYTRACE_ENTER("CNat::ReservePort");
  790. RETURN_IF_CLIENT_NOT_LOCAL_SERVICE;
  791. ASSERT(pReservedPortBase!=NULL);
  792. if ( !AlgPortReservationHandle )
  793. return E_FAIL; // AlgPortReservationHandle should already have been done
  794. ULONG Error = NatAcquirePortReservation(
  795. AlgPortReservationHandle,
  796. PortCount,
  797. pReservedPortBase
  798. );
  799. if ( ERROR_SUCCESS != Error )
  800. {
  801. MYTRACE_ERROR("from NatAcquirePortReservation", Error);
  802. return HRESULT_FROM_WIN32(Error);
  803. }
  804. MYTRACE("PortBase %d count %d", *pReservedPortBase, PortCount);
  805. return S_OK;
  806. }
  807. STDMETHODIMP CNat::ReleasePort(
  808. IN USHORT ReservedPortBase,
  809. IN USHORT PortCount
  810. )
  811. /*++
  812. Routine Description:
  813. Private interface between rmALG and ALG.EXE
  814. ALG expose a more simple interface to reserve at Port
  815. in turn it call this private interface that end up calling the more complex NatApi
  816. This routine will call the Nat api to release the previously reserved ports
  817. Arguments:
  818. PortCount - Number of port to reserve
  819. pReservedPortBase - Starting number of the range of port reserved. example ReserePort(3, &) would save 5000,5001,5002 and return 5000 as base
  820. Return Value:
  821. HRESULT - S_OK if it worked or E_FAIL
  822. Environment:
  823. Private interface between rmALG and ALG.EXE
  824. ALG expose a more simple interface to reserve at Port
  825. in turn it call this private interface that end up calling the more complex NatApi
  826. --*/
  827. {
  828. MYTRACE_ENTER("CNat::ReleasePort");
  829. RETURN_IF_CLIENT_NOT_LOCAL_SERVICE;
  830. if ( !AlgPortReservationHandle )
  831. return E_FAIL; // AlgPortReservationHandle should already have been done
  832. ULONG Error = NatReleasePortReservation(
  833. AlgPortReservationHandle,
  834. ReservedPortBase,
  835. PortCount
  836. );
  837. if ( ERROR_SUCCESS != Error )
  838. {
  839. MYTRACE_ERROR("from NatReleasePortReservation", Error);
  840. return HRESULT_FROM_WIN32(Error);
  841. }
  842. MYTRACE("PortBase=%d, Count=%d", ntohs(ReservedPortBase), PortCount);
  843. return S_OK;
  844. }