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.

415 lines
11 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2001 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: nathelp.c
  6. * Content: usage for nat helper DLL
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 02/22/2001 aarono Original
  12. * 04/16/2001 vanceo Use one of the split DirectPlayNATHelp interfaces only.
  13. *
  14. * Notes:
  15. *
  16. ***************************************************************************/
  17. #define INITGUID
  18. #define INCL_WINSOCK_API_TYPEDEFS 1 // includes winsock 2 fn proto's, for getprocaddress
  19. #define FD_SETSIZE 1
  20. #include <winsock2.h>
  21. #include <initguid.h>
  22. #include "dpsp.h"
  23. #include "mmsystem.h"
  24. #include "dphelp.h"
  25. #if USE_NATHELP
  26. #include "dpnathlp.h"
  27. extern HRESULT GetNATHelpDLLFromRegistry(LPGUID lpguidSP, LPBYTE lpszNATHelpDLL, DWORD cbszNATHelpDLL);
  28. HMODULE g_hNatHelp = NULL; // module handle for dpnhxxx.dll
  29. DPNHHANDLE g_hNatHelpUDP = 0;
  30. IDirectPlayNATHelp *g_pINatHelp=NULL; // interface pointer for IDirectPlayNATHelp object
  31. DPNHCAPS g_NatHelpCaps;
  32. BOOL natGetCapsUpdate(VOID)
  33. {
  34. HRESULT hr;
  35. //
  36. // Get Nat Capabilities - may block for a second.
  37. //
  38. memset(&g_NatHelpCaps,0,sizeof(DPNHCAPS));
  39. g_NatHelpCaps.dwSize=sizeof(DPNHCAPS);
  40. hr=IDirectPlayNATHelp_GetCaps(g_pINatHelp, &g_NatHelpCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
  41. if(FAILED(hr))
  42. {
  43. DPF(0,"NatHelp failed to GetCaps, hr=%x\n",hr);
  44. return FALSE;
  45. }
  46. if (hr == DPNHSUCCESS_ADDRESSESCHANGED)
  47. {
  48. DPF(1,"NAT Help reports addresses changed.");
  49. }
  50. return TRUE;
  51. }
  52. /*=============================================================================
  53. natInit - Initialize nat helper i/f
  54. Description:
  55. Parameters:
  56. pgd - Service Provider's global data blob for this instance
  57. Return Values:
  58. -----------------------------------------------------------------------------*/
  59. BOOL natInit(VOID)
  60. {
  61. HRESULT hr;
  62. char szNATHelpPath[256];
  63. PFN_DIRECTPLAYNATHELPCREATE pfnNatHelpCreate = NULL;
  64. char *apszNATHelps[3];
  65. HMODULE ahNatHelps[3];
  66. IDirectPlayNATHelp *apINatHelps[3];
  67. DPNHCAPS adpnhcNatHelpCaps[3];
  68. DWORD dwNumNatHelps = 0;
  69. DWORD dwCurrentNatHelp;
  70. memset(ahNatHelps, 0, sizeof(ahNatHelps));
  71. memset(apINatHelps, 0, sizeof(apINatHelps));
  72. //
  73. // See if there's a registry setting.
  74. //
  75. hr = GetNATHelpDLLFromRegistry((LPGUID) (&DPSPGUID_TCPIP), szNATHelpPath, 256);
  76. if (hr == S_OK)
  77. {
  78. DPF(1, "Got NAT Help DLL \"%s\" from registry.\n", szNATHelpPath);
  79. apszNATHelps[dwNumNatHelps++] = szNATHelpPath;
  80. }
  81. else
  82. {
  83. DPF(4, "Couldn't get NAT Help DLL from registry, hr=%x.\n", hr);
  84. }
  85. //
  86. // Add the default entries if the registry didn't already specify them.
  87. //
  88. if (_strnicmp(szNATHelpPath + strlen(szNATHelpPath) - strlen("dpnhupnp.dll"), "dpnhupnp.dll", strlen("dpnhupnp.dll")) != 0)
  89. {
  90. apszNATHelps[dwNumNatHelps++] = "dpnhupnp.dll";
  91. }
  92. if (_strnicmp(szNATHelpPath + strlen(szNATHelpPath) - strlen("dpnhpast.dll"), "dpnhpast.dll", strlen("dpnhpast.dll")) != 0)
  93. {
  94. apszNATHelps[dwNumNatHelps++] = "dpnhpast.dll";
  95. }
  96. //
  97. // Loop through the registry specified and default NAT Helpers and attempt
  98. // to load them.
  99. //
  100. for(dwCurrentNatHelp = 0; dwCurrentNatHelp < dwNumNatHelps; dwCurrentNatHelp++)
  101. {
  102. g_hNatHelp = LoadLibrary(apszNATHelps[dwCurrentNatHelp]);
  103. if (g_hNatHelp != NULL)
  104. {
  105. pfnNatHelpCreate = (PFN_DIRECTPLAYNATHELPCREATE) GetProcAddress(g_hNatHelp,
  106. "DirectPlayNATHelpCreate");
  107. if (pfnNatHelpCreate != NULL)
  108. {
  109. hr = pfnNatHelpCreate(&IID_IDirectPlayNATHelp, (void **) (&g_pINatHelp));
  110. if (hr == DP_OK)
  111. {
  112. //
  113. // Initialize the NAT Helper interface.
  114. //
  115. hr = IDirectPlayNATHelp_Initialize(g_pINatHelp, 0);
  116. if (hr == DP_OK)
  117. {
  118. //
  119. // Get the capabilities. If it succeeds, remember the information and move on.
  120. //
  121. if (natGetCapsUpdate())
  122. {
  123. DPF(3, "Successfully retrieved caps for NAT Help \"%s\", flags = 0x%x.",
  124. apszNATHelps[dwCurrentNatHelp], g_NatHelpCaps.dwFlags);
  125. ahNatHelps[dwCurrentNatHelp] = g_hNatHelp;
  126. g_hNatHelp = NULL;
  127. apINatHelps[dwCurrentNatHelp] = g_pINatHelp;
  128. g_pINatHelp = NULL;
  129. memcpy(&adpnhcNatHelpCaps[dwCurrentNatHelp], &g_NatHelpCaps, sizeof(DPNHCAPS));
  130. continue;
  131. }
  132. else
  133. {
  134. DPF(0, "Couldn't get NAT Help \"%s\" caps, hr=%x!", apszNATHelps[dwCurrentNatHelp], hr);
  135. }
  136. IDirectPlayNATHelp_Close(g_pINatHelp, 0);
  137. }
  138. else
  139. {
  140. DPF(0, "NAT Help \"%s\" failed to initialize, hr=%x!", apszNATHelps[dwCurrentNatHelp], hr);
  141. }
  142. IDirectPlayNATHelp_Release(g_pINatHelp);
  143. g_pINatHelp = NULL;
  144. }
  145. else
  146. {
  147. DPF(0, "Couldn't create NAT Help \"%s\" interface, hr = %x!", apszNATHelps[dwCurrentNatHelp], hr);
  148. }
  149. }
  150. else
  151. {
  152. DPF(0, "Couldn't get NAT Help DLL \"%s\" entry point!", apszNATHelps[dwCurrentNatHelp]);
  153. }
  154. FreeLibrary(g_hNatHelp);
  155. g_hNatHelp = NULL;
  156. }
  157. else
  158. {
  159. DPF(0, "Couldn't load NAT Help DLL \"%s\"!", apszNATHelps[dwCurrentNatHelp]);
  160. }
  161. }
  162. //
  163. // Now go through and pick the first helper that detected a NAT.
  164. //
  165. for(dwCurrentNatHelp = 0; dwCurrentNatHelp < dwNumNatHelps; dwCurrentNatHelp++)
  166. {
  167. if ((apINatHelps[dwCurrentNatHelp] != NULL) &&
  168. (adpnhcNatHelpCaps[dwCurrentNatHelp].dwFlags & DPNHCAPSFLAG_GATEWAYPRESENT))
  169. {
  170. DPF(2, "Gateway detected by NAT Help \"%s\", flags = 0x%x.",
  171. apszNATHelps[dwCurrentNatHelp], adpnhcNatHelpCaps[dwCurrentNatHelp].dwFlags);
  172. g_hNatHelp = ahNatHelps[dwCurrentNatHelp];
  173. ahNatHelps[dwCurrentNatHelp] = NULL;
  174. g_pINatHelp = apINatHelps[dwCurrentNatHelp];
  175. apINatHelps[dwCurrentNatHelp] = NULL;
  176. memcpy(&g_NatHelpCaps, &adpnhcNatHelpCaps[dwCurrentNatHelp], sizeof(DPNHCAPS));
  177. break;
  178. }
  179. }
  180. //
  181. // If we didn't get a helper that way, pick the first one that detected a firewall.
  182. //
  183. if (g_pINatHelp != NULL)
  184. {
  185. for(dwCurrentNatHelp = 0; dwCurrentNatHelp < dwNumNatHelps; dwCurrentNatHelp++)
  186. {
  187. if ((apINatHelps[dwCurrentNatHelp] != NULL) &&
  188. (adpnhcNatHelpCaps[dwCurrentNatHelp].dwFlags & DPNHCAPSFLAG_LOCALFIREWALLPRESENT))
  189. {
  190. DPF(2, "Firewall detected by NAT Help \"%s\", flags = 0x%x.",
  191. apszNATHelps[dwCurrentNatHelp], adpnhcNatHelpCaps[dwCurrentNatHelp].dwFlags);
  192. g_hNatHelp = ahNatHelps[dwCurrentNatHelp];
  193. ahNatHelps[dwCurrentNatHelp] = NULL;
  194. g_pINatHelp = apINatHelps[dwCurrentNatHelp];
  195. apINatHelps[dwCurrentNatHelp] = NULL;
  196. memcpy(&g_NatHelpCaps, &adpnhcNatHelpCaps[dwCurrentNatHelp], sizeof(DPNHCAPS));
  197. break;
  198. }
  199. }
  200. }
  201. //
  202. // Now go through and release all the other NAT helpers, or pick the first one that
  203. // successfully loaded if we didn't pick one already.
  204. //
  205. for(dwCurrentNatHelp = 0; dwCurrentNatHelp < dwNumNatHelps; dwCurrentNatHelp++)
  206. {
  207. if (apINatHelps[dwCurrentNatHelp] != NULL)
  208. {
  209. if (g_pINatHelp == NULL)
  210. {
  211. DPF(2, "Using first loaded NAT Help \"%s\", flags = 0x%x.",
  212. apszNATHelps[dwCurrentNatHelp], adpnhcNatHelpCaps[dwCurrentNatHelp].dwFlags);
  213. g_hNatHelp = ahNatHelps[dwCurrentNatHelp];
  214. ahNatHelps[dwCurrentNatHelp] = NULL;
  215. g_pINatHelp = apINatHelps[dwCurrentNatHelp];
  216. apINatHelps[dwCurrentNatHelp] = NULL;
  217. memcpy(&g_NatHelpCaps, &adpnhcNatHelpCaps[dwCurrentNatHelp], sizeof(DPNHCAPS));
  218. }
  219. else
  220. {
  221. IDirectPlayNATHelp_Close(apINatHelps[dwCurrentNatHelp], 0);
  222. IDirectPlayNATHelp_Release(apINatHelps[dwCurrentNatHelp]);
  223. apINatHelps[dwCurrentNatHelp] = NULL;
  224. FreeLibrary(ahNatHelps[dwCurrentNatHelp]);
  225. ahNatHelps[dwCurrentNatHelp] = NULL;
  226. }
  227. }
  228. }
  229. if (g_pINatHelp == NULL)
  230. {
  231. DPF(1, "No NAT Help loaded.");
  232. g_NatHelpCaps.dwRecommendedGetCapsInterval = INFINITE;
  233. return FALSE;
  234. }
  235. #ifdef DEBUG
  236. if (! (g_NatHelpCaps.dwFlags & DPNHCAPSFLAG_PUBLICADDRESSAVAILABLE))
  237. {
  238. DPF(1, "NAT Help loaded, no NAT/firewall detected, or it doesn't currently have a public address (flags = 0x%x).",
  239. g_NatHelpCaps.dwFlags);
  240. }
  241. #endif // DEBUG
  242. return TRUE;
  243. }
  244. /*=============================================================================
  245. natFini - Shut down NATHELP support
  246. Description:
  247. Parameters:
  248. pgd - Service Provider's global data blob for this instance
  249. Return Values:
  250. None.
  251. -----------------------------------------------------------------------------*/
  252. VOID natFini(VOID)
  253. {
  254. // natDeregisterPorts(pgd); - vance says we don't need to do this.
  255. if(g_pINatHelp)
  256. {
  257. IDirectPlayNATHelp_Close(g_pINatHelp, 0);
  258. g_hNatHelpUDP = 0;
  259. IDirectPlayNATHelp_Release(g_pINatHelp);
  260. g_pINatHelp=NULL;
  261. }
  262. if(g_hNatHelp)
  263. {
  264. FreeLibrary(g_hNatHelp);
  265. g_hNatHelp=NULL;
  266. }
  267. }
  268. /*=============================================================================
  269. natRegisterUDPPort - Get a port mapping.
  270. Description:
  271. Map the shared port
  272. Parameters:
  273. pgd - Service Provider's global data blob for this instance
  274. Return Values:
  275. None.
  276. -----------------------------------------------------------------------------*/
  277. HRESULT natRegisterUDPPort(WORD port)
  278. {
  279. SOCKADDR_IN sockaddr_in, sockaddr_inpublic;
  280. DWORD dwFlags, dwSize;
  281. DPNHHANDLE hPortMapping;
  282. HRESULT hr;
  283. if (!g_hNatHelpUDP)
  284. {
  285. memset(&sockaddr_in , 0 ,sizeof(sockaddr_in));
  286. sockaddr_in.sin_family = AF_INET;
  287. sockaddr_in.sin_addr.S_un.S_addr= INADDR_ANY;
  288. sockaddr_in.sin_port = port; // port is already in network byte order
  289. dwFlags = DPNHREGISTERPORTS_SHAREDPORTS|DPNHREGISTERPORTS_FIXEDPORTS;
  290. hr = IDirectPlayNATHelp_RegisterPorts(g_pINatHelp, (SOCKADDR *)&sockaddr_in, sizeof(sockaddr_in), 1, 15*60000, &hPortMapping, dwFlags);
  291. if (hr != DPNH_OK)
  292. {
  293. DPF(0,"NATHelp_RegisterPorts failed, hr=%x",hr);
  294. hr = DPERR_GENERIC;
  295. }
  296. else
  297. {
  298. dwSize=sizeof(sockaddr_inpublic);
  299. hr = IDirectPlayNATHelp_GetRegisteredAddresses(g_pINatHelp, hPortMapping, (SOCKADDR *)&sockaddr_inpublic, &dwSize, NULL, NULL, 0);
  300. switch (hr)
  301. {
  302. case DPNH_OK:
  303. {
  304. DEBUGPRINTADDR(2, "NATHelp successfully mapped port to ", (SOCKADDR *)&sockaddr_inpublic);
  305. g_hNatHelpUDP = hPortMapping;
  306. //hr = DP_OK;
  307. break;
  308. }
  309. case DPNHERR_PORTUNAVAILABLE:
  310. {
  311. DPF(0, "NATHelp reported port %u is unavailable!",
  312. MAKEWORD(HIBYTE(port), LOBYTE(port)));
  313. hr = IDirectPlayNATHelp_DeregisterPorts(g_pINatHelp, hPortMapping, 0);
  314. if (hr != DP_OK)
  315. {
  316. DPF(0,"NATHelp_DeregisterPorts PAST returned 0x%lx\n",hr);
  317. }
  318. hr = DPNHERR_PORTUNAVAILABLE;
  319. break;
  320. }
  321. default:
  322. {
  323. DPF(1, "NATHelp couldn't map port %u, (err = 0x%lx).",
  324. MAKEWORD(HIBYTE(port), LOBYTE(port)),
  325. hr);
  326. g_hNatHelpUDP = hPortMapping;
  327. hr = DPERR_GENERIC;
  328. break;
  329. }
  330. }
  331. }
  332. }
  333. else
  334. {
  335. DPF(1, "Already registered port with NAT Help, not registering %u.",
  336. MAKEWORD(HIBYTE(port), LOBYTE(port)));
  337. hr = DP_OK;
  338. }
  339. return hr;
  340. }
  341. #endif