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.

601 lines
13 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // MyALG.cpp : Implementation of CMyALG
  4. //
  5. // Main interface called by ALG.exe it wil call Initialise and stop when the ALG.exe is unloading
  6. // or this ALG Module is disable/removed
  7. //
  8. #include "PreComp.h"
  9. #include "MyALG.h"
  10. #include "MyAdapterNotify.h"
  11. #include <winsock.h>
  12. #pragma comment(lib, "wsock32.lib")
  13. /////////////////////////////////////////////////////////////////////////////
  14. //
  15. // CMyALG
  16. //
  17. #define PORTNUM 1313
  18. #define HOSTNAME "localhost" // Server name string
  19. #define MAX_PENDING_CONNECTS 4 // Maximum length of the queue of pending connections
  20. IApplicationGatewayServices* g_pIAlgServices=NULL; // Cache main interface of ALG
  21. IAdapterNotificationSink* g_pIAdapterNotificationSink=NULL;
  22. IPrimaryControlChannel* g_pIControlChannel=NULL;
  23. USHORT g_usPort= 0; // Test Reserve some ports
  24. DWORD g_dwAdapterSinkCookie=0;
  25. DWORD g_dwThreadID_Listen;
  26. SOCKET g_ClientSock = INVALID_SOCKET; // Socket for communicating
  27. //
  28. // Forward declaration
  29. //
  30. DWORD WINAPI ThreadListenRedirect(LPVOID lpThreadParameter);
  31. //
  32. //
  33. // Main entry point for ALG Modules
  34. //
  35. //
  36. STDMETHODIMP
  37. CMyALG::Initialize(
  38. IApplicationGatewayServices* pIAlgServices
  39. )
  40. {
  41. MYTRACE_ENTER("CMyALG::Initialize");
  42. USES_CONVERSION;
  43. HRESULT hr;
  44. ULONG nAddress;
  45. //
  46. // Keep the service alive (this is optional since the ALG Manager is loading us it will always be around)
  47. //
  48. g_pIAlgServices = pIAlgServices;
  49. g_pIAlgServices->AddRef();
  50. #if 1
  51. //
  52. // Requesting Notification of adapter ADD/REMOVE/MODIFY
  53. // when an adapter gets Added Removed or is modified this ALG will receive a notification
  54. //
  55. {
  56. MYTRACE_ENTER("###TEST### - STARTADAPTERNOTIFICATIONS");
  57. CComObject<CMyAdapterNotify>* pIAdapterNotify;
  58. CComObject<CMyAdapterNotify>::CreateInstance(&pIAdapterNotify);
  59. hr = pIAdapterNotify->QueryInterface(IID_IAdapterNotificationSink, (void**)&g_pIAdapterNotificationSink);
  60. if ( FAILED(hr) )
  61. MYTRACE_ERROR("No QI on IID_IAdapterNotificationSink", hr);
  62. hr = g_pIAlgServices->StartAdapterNotifications(g_pIAdapterNotificationSink, &g_dwAdapterSinkCookie);
  63. }
  64. #endif
  65. #if 1
  66. //
  67. // Reserver some ports, these port will be garantied to be free and available for this ALG
  68. //
  69. {
  70. MYTRACE_ENTER("###TEST### - RESERVE PORT");
  71. hr = g_pIAlgServices->ReservePort(4, &g_usPort);
  72. if ( SUCCEEDED(hr) )
  73. MYTRACE("ALG_TEST->ReservePorts (%d) to (%d)", ntohs(g_usPort), ntohs(g_usPort)+3);
  74. else
  75. {
  76. MYTRACE_ERROR("Could no reserver port", hr);
  77. return E_FAIL;
  78. }
  79. }
  80. #endif
  81. #if 1
  82. //
  83. // Redirect traffic of a well unknown port here we invented port 5000 as a port of interest
  84. //
  85. {
  86. MYTRACE_ENTER("###TEST### - CREATE PRIMARY CONTROL CHANNEL");
  87. hr = g_pIAlgServices->CreatePrimaryControlChannel(
  88. eALG_TCP,
  89. htons(5000),
  90. eALG_DESTINATION_CAPTURE,
  91. true,
  92. inet_addr("127.0.0.1"),
  93. htons(PORTNUM),
  94. &g_pIControlChannel
  95. );
  96. if ( FAILED(hr) )
  97. {
  98. MYTRACE_ERROR("FAILED the CreatePrimaryControlChannel", hr);
  99. }
  100. }
  101. #endif
  102. #if 1
  103. //
  104. // SECONDARY CHANNEL
  105. //
  106. {
  107. MYTRACE_ENTER("###TEST### - CREATE SECONDARY CHANNAL");
  108. ISecondaryControlChannel* mySecondaryDataChannel=NULL;
  109. hr = g_pIAlgServices->CreateSecondaryControlChannel(
  110. eALG_UDP,
  111. inet_addr("192.168.0.2"),
  112. htons(99),
  113. inet_addr("157.157.157.2"),
  114. htons(5001),
  115. inet_addr("205.157.157.1"),
  116. htons(5002),
  117. inet_addr("127.0.0.1"),
  118. htons(666),
  119. eALG_INBOUND,
  120. false,
  121. &mySecondaryDataChannel
  122. );
  123. if ( FAILED(hr) )
  124. {
  125. MYTRACE_ERROR("Could not create SecondaryDataChannel", hr);
  126. }
  127. else
  128. {
  129. hr = mySecondaryDataChannel->Cancel();
  130. if ( FAILED(hr) )
  131. {
  132. MYTRACE_ERROR("Failed to cancel", hr);
  133. }
  134. mySecondaryDataChannel->Release();
  135. }
  136. }
  137. #endif
  138. //
  139. // Listen on another thread for redirected packet
  140. //
  141. HANDLE hThread = CreateThread(
  142. NULL, // SecurityDesc
  143. 0, // initial stack size
  144. ThreadListenRedirect, // thread function
  145. NULL, // thread argument
  146. 0, // creation option
  147. &g_dwThreadID_Listen // thread identifier
  148. );
  149. if ( !hThread )
  150. MYTRACE_ERROR("Could not start listenning thread", 0);
  151. #if 1
  152. //
  153. // TEST GetBestSourceAddressForDestinationAddress
  154. // should return the best IP Address to use
  155. //
  156. {
  157. MYTRACE_ENTER("###TEST### - GET BEST SOURCE ADDRESS FOR DESTINATION ADDRESS");
  158. ULONG nAddressDest = inet_addr("157.157.157.2");
  159. hr = g_pIAlgServices->GetBestSourceAddressForDestinationAddress(
  160. nAddressDest, // IP Address of destination
  161. false, // if Dialup is involved
  162. &nAddress // the Address to use
  163. );
  164. if ( FAILED(hr) )
  165. {
  166. MYTRACE_ERROR("FAILED the CreatePrimaryControlChannel", hr);
  167. }
  168. MYTRACE( "Best address is %s", MYTRACE_IP(nAddress) );
  169. }
  170. #endif
  171. #if 1
  172. //
  173. // D A T A C H A N N E L
  174. //
  175. {
  176. MYTRACE_ENTER("###TEST### - CREATE DATA CHANNEL");
  177. IDataChannel* myDataChannel=NULL;
  178. hr = g_pIAlgServices->CreateDataChannel(
  179. eALG_TCP,
  180. nAddress,
  181. g_usPort,
  182. inet_addr("157.157.157.2"),
  183. htons(5001),
  184. inet_addr("157.157.157.1"),
  185. htons(5001),
  186. eALG_INBOUND,
  187. eALG_NONE,
  188. false,
  189. &myDataChannel
  190. );
  191. if ( FAILED(hr) )
  192. {
  193. MYTRACE_ERROR("Could not create DataChannel", hr);
  194. }
  195. else
  196. {
  197. hr = myDataChannel->Cancel();
  198. if ( FAILED(hr) )
  199. {
  200. MYTRACE_ERROR("Failed to cancel", hr);
  201. }
  202. myDataChannel->Release();
  203. }
  204. }
  205. #endif
  206. //
  207. //
  208. // TEST - PrepareProxyConnection
  209. //
  210. //
  211. #if 1
  212. {
  213. MYTRACE_ENTER("###TEST### - PREPARE PROXY CONNECTION");
  214. IPendingProxyConnection* myPendingProxyConnection=NULL;
  215. hr = g_pIAlgServices->PrepareProxyConnection(
  216. eALG_TCP, // Protocal
  217. nAddress, // Source Address
  218. g_usPort, // Source Port
  219. inet_addr("172.31.77.13"), // Public Destination Address
  220. htons(21), // Public Destination port
  221. FALSE,
  222. &myPendingProxyConnection
  223. );
  224. if ( FAILED(hr) )
  225. {
  226. MYTRACE_ERROR("Could not create shadow redirect", hr);
  227. }
  228. else
  229. {
  230. hr = myPendingProxyConnection->Cancel();
  231. if ( FAILED(hr) )
  232. {
  233. MYTRACE_ERROR("Failed to cancel", hr);
  234. }
  235. myPendingProxyConnection->Release();
  236. }
  237. }
  238. #endif
  239. #if 1
  240. //
  241. //
  242. // TEST - PrepareSourceModifiedProxyConnection
  243. //
  244. //
  245. {
  246. MYTRACE_ENTER("###TEST### - PREPARE SOURCE MODIFIED PROXY CONNECTION");
  247. IPendingProxyConnection* myPendingProxyConnection2=NULL;
  248. hr = g_pIAlgServices->PrepareSourceModifiedProxyConnection(
  249. eALG_TCP,
  250. nAddress,
  251. htons(1212),
  252. inet_addr("172.31.77.13"),
  253. htons(21),
  254. inet_addr("172.31.77.14"),
  255. htons(22),
  256. &myPendingProxyConnection2
  257. );
  258. if ( FAILED(hr) )
  259. {
  260. MYTRACE_ERROR("Could not create shadow redirect", hr);
  261. }
  262. else
  263. {
  264. hr = myPendingProxyConnection2->Cancel();
  265. if ( FAILED(hr) )
  266. {
  267. MYTRACE_ERROR("Failed to cancel", hr);
  268. }
  269. myPendingProxyConnection2->Release();
  270. }
  271. }
  272. #endif
  273. return S_OK;
  274. }
  275. //
  276. //
  277. //
  278. STDMETHODIMP
  279. CMyALG::Stop()
  280. {
  281. MYTRACE_ENTER("CMyALG::Stop(void)");
  282. closesocket(g_ClientSock);
  283. g_ClientSock = INVALID_SOCKET;
  284. if ( g_dwAdapterSinkCookie )
  285. {
  286. HRESULT hr = g_pIAlgServices->StopAdapterNotifications(g_dwAdapterSinkCookie);
  287. g_pIAdapterNotificationSink->Release();
  288. }
  289. if ( g_pIControlChannel )
  290. {
  291. g_pIControlChannel->Cancel();
  292. }
  293. MYTRACE("ReleaseReservedPort %d", g_usPort);
  294. g_pIAlgServices->ReleaseReservedPort(g_usPort, 4);
  295. MYTRACE("About To Release");
  296. // g_pIAlgServices->Release();
  297. MYTRACE("Return");
  298. return S_OK;
  299. }
  300. //
  301. //
  302. //
  303. HRESULT
  304. WaitForData()
  305. {
  306. MYTRACE_ENTER("WaitForData()");
  307. //
  308. // Prepare winsock
  309. //
  310. int index = 0; // Integer index
  311. SOCKET WinSocket = INVALID_SOCKET; // Window socket
  312. // between the server and client
  313. SOCKADDR_IN local_sin; // Local socket address
  314. WSADATA WSAData; // Contains details of the Winsock implementation
  315. // Initialize Winsock.
  316. if ( WSAStartup (MAKEWORD(1,1), &WSAData) != 0 )
  317. {
  318. MYTRACE_ERROR("WSAStartup failed.", WSAGetLastError ());
  319. }
  320. // Create a TCP/IP socket, WinSocket.
  321. if ((WinSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
  322. {
  323. MYTRACE_ERROR("Allocating socket failed", WSAGetLastError());
  324. return E_FAIL;
  325. }
  326. // Fill out the local socket's address information.
  327. local_sin.sin_family = AF_INET;
  328. local_sin.sin_port = htons(PORTNUM); //g_usPort;
  329. local_sin.sin_addr.s_addr = inet_addr("127.0.0.1");
  330. // Associate the local address with WinSocket.
  331. if ( bind(WinSocket, (struct sockaddr *) &local_sin, sizeof (local_sin)) == SOCKET_ERROR )
  332. {
  333. MYTRACE_ERROR("Binding socket failed.", WSAGetLastError ());
  334. closesocket (WinSocket);
  335. return E_FAIL;
  336. }
  337. // Establish a socket to listen for incoming connections.
  338. if ( listen(WinSocket, MAX_PENDING_CONNECTS) == SOCKET_ERROR )
  339. {
  340. MYTRACE_ERROR("Listening to the client failed.", WSAGetLastError ());
  341. closesocket (WinSocket);
  342. return E_FAIL;
  343. }
  344. // Accept an incoming connection attempt on WinSocket.
  345. SOCKADDR_IN accept_sin; // Receives the address of the
  346. // connecting entity
  347. int accept_sin_len; // Length of accept_sin
  348. accept_sin_len = sizeof (accept_sin);
  349. MYTRACE("*** Accept is waiting for a connection");
  350. g_ClientSock = accept(
  351. WinSocket,
  352. (struct sockaddr *) &accept_sin,
  353. (int *) &accept_sin_len
  354. );
  355. // Stop listening for connections from clients.
  356. closesocket (WinSocket);
  357. {
  358. MYTRACE ("Getting original address");
  359. //
  360. ULONG ulOriginalDestinationAddress;
  361. USHORT usOriginalDestinationPort;
  362. IAdapterInfo* pAdapterInfo;
  363. HRESULT hr = g_pIControlChannel->GetOriginalDestinationInformation(
  364. accept_sin.sin_addr.S_un.S_addr,
  365. accept_sin.sin_port,
  366. &ulOriginalDestinationAddress,
  367. &usOriginalDestinationPort,
  368. &pAdapterInfo
  369. );
  370. if ( FAILED(hr) )
  371. {
  372. MYTRACE_ERROR("GetOriginalDestinationInformation did not work", hr);
  373. }
  374. else
  375. {
  376. MYTRACE("Original Address %s:%d", MYTRACE_IP(ulOriginalDestinationAddress), ntohs(usOriginalDestinationPort));
  377. ULONG nIndex;
  378. pAdapterInfo->GetAdapterIndex(&nIndex);
  379. ALG_ADAPTER_TYPE eType;
  380. pAdapterInfo->GetAdapterType(&eType);
  381. MYTRACE("AdapterIndex %d", nIndex);
  382. MYTRACE("AdapterType %d", eType);
  383. }
  384. }
  385. if ( g_ClientSock == INVALID_SOCKET)
  386. {
  387. MYTRACE_ERROR("Accepting connection with client failed. Error: %d", WSAGetLastError ());
  388. return E_FAIL;
  389. }
  390. MYTRACE("**** AFTER Listen on port %d", g_usPort);
  391. TCHAR cData;
  392. int iReturn;
  393. for (;;)
  394. {
  395. // Receive data from the client.
  396. iReturn = recv(
  397. g_ClientSock,
  398. (char*)&cData,
  399. sizeof(cData),
  400. 0);
  401. // Check if there is any data received. If there is, display it.
  402. if (iReturn == SOCKET_ERROR)
  403. {
  404. MYTRACE("Received failed. Error: %d", WSAGetLastError ());
  405. return E_FAIL;
  406. }
  407. else if (iReturn == 0)
  408. {
  409. MYTRACE("Finished receiving data");
  410. break;
  411. }
  412. else
  413. {
  414. MYTRACE("%c", cData);
  415. }
  416. }
  417. closesocket(g_ClientSock);
  418. //
  419. // Enumerate The Adapters
  420. //
  421. IEnumAdapterInfo* pAdapters = NULL;
  422. HRESULT hr = g_pIAlgServices->EnumerateAdapters(&pAdapters);
  423. if ( FAILED(hr) )
  424. {
  425. MYTRACE_ERROR("Call EnumerateAdapters did not worked", hr);
  426. }
  427. else
  428. pAdapters->Release();
  429. return S_OK;
  430. }
  431. //
  432. //
  433. //
  434. DWORD WINAPI
  435. ThreadListenRedirect(LPVOID lpThreadParameter)
  436. {
  437. MYTRACE_ENTER("ThreadListenRedirect()");
  438. while ( WaitForData() == S_OK );
  439. return 0;
  440. }