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.

295 lines
9.2 KiB

  1. #include "stdafx.h"
  2. #include "sockinfo.h"
  3. SOCKET_INFO::SOCKET_INFO (void)
  4. : Socket (INVALID_SOCKET)
  5. {
  6. ZeroMemory (&LocalAddress, sizeof (SOCKADDR_IN));
  7. ZeroMemory (&RemoteAddress, sizeof (SOCKADDR_IN));
  8. ZeroMemory (&TrivialRedirectDestAddress, sizeof (SOCKADDR_IN));
  9. ZeroMemory (&TrivialRedirectSourceAddress, sizeof (SOCKADDR_IN));
  10. IsNatRedirectActive = FALSE;
  11. }
  12. void
  13. SOCKET_INFO::Init (
  14. IN SOCKET ArgSocket,
  15. IN SOCKADDR_IN * ArgLocalAddress,
  16. IN SOCKADDR_IN * ArgRemoteAddress)
  17. {
  18. assert (Socket == INVALID_SOCKET);
  19. assert (ArgSocket != INVALID_SOCKET);
  20. assert (ArgLocalAddress);
  21. assert (ArgRemoteAddress);
  22. Socket = ArgSocket;
  23. LocalAddress = *ArgLocalAddress;
  24. RemoteAddress = *ArgRemoteAddress;
  25. }
  26. int SOCKET_INFO::Init (
  27. IN SOCKET ArgSocket,
  28. IN SOCKADDR_IN * ArgRemoteAddress)
  29. {
  30. INT AddressLength;
  31. assert (Socket == INVALID_SOCKET);
  32. assert (ArgSocket != INVALID_SOCKET);
  33. AddressLength = sizeof (SOCKADDR_IN);
  34. if (getsockname (ArgSocket, (SOCKADDR *) &LocalAddress, &AddressLength)) {
  35. return WSAGetLastError();
  36. }
  37. Socket = ArgSocket;
  38. RemoteAddress = *ArgRemoteAddress;
  39. return ERROR_SUCCESS;
  40. }
  41. BOOLEAN
  42. SOCKET_INFO::IsSocketValid (void) {
  43. return Socket != INVALID_SOCKET;
  44. }
  45. void
  46. SOCKET_INFO::SetListenInfo (
  47. IN SOCKET ListenSocket,
  48. IN SOCKADDR_IN * ListenAddress)
  49. {
  50. assert (Socket == INVALID_SOCKET);
  51. assert (ListenSocket != INVALID_SOCKET);
  52. assert (ListenAddress);
  53. Socket = ListenSocket;
  54. LocalAddress = *ListenAddress;
  55. }
  56. int
  57. SOCKET_INFO::Connect(
  58. IN SOCKADDR_IN * ArgRemoteAddress)
  59. {
  60. int Status;
  61. DWORD LocalToRemoteInterfaceAddress;
  62. INT AddressSize = sizeof (SOCKADDR_IN);
  63. BOOL KeepaliveOption;
  64. assert (Socket == INVALID_SOCKET);
  65. assert (ArgRemoteAddress);
  66. Status = GetBestInterfaceAddress (
  67. ntohl (ArgRemoteAddress -> sin_addr.s_addr),
  68. &LocalToRemoteInterfaceAddress);
  69. if (ERROR_SUCCESS != Status) {
  70. DebugF (_T("Q931: Failed to get best interface for the destination %08X:%04X.\n"),
  71. SOCKADDR_IN_PRINTF (ArgRemoteAddress));
  72. return Status;
  73. }
  74. LocalAddress.sin_family = AF_INET;
  75. LocalAddress.sin_addr.s_addr = htonl (LocalToRemoteInterfaceAddress);
  76. LocalAddress.sin_port = htons (0);
  77. Socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
  78. if (Socket == INVALID_SOCKET) {
  79. Status = WSAGetLastError ();
  80. DebugF( _T("Q931: Destination %08X:%04X, failed to create socket"),
  81. SOCKADDR_IN_PRINTF (ArgRemoteAddress));
  82. DumpError (Status);
  83. return Status;
  84. }
  85. //
  86. // Set RCV and SND buffers to zero
  87. // for details look up bug# WinSE 31054, 691666 (read both 35928 and 33546).
  88. //
  89. ULONG Option = 0;
  90. setsockopt( Socket, SOL_SOCKET, SO_SNDBUF,
  91. (PCHAR)&Option, sizeof(Option) );
  92. Option = 0;
  93. setsockopt( Socket, SOL_SOCKET, SO_SNDBUF,
  94. (PCHAR)&Option, sizeof(Option) );
  95. if (SOCKET_ERROR == bind(Socket, (PSOCKADDR)&LocalAddress, AddressSize)) {
  96. Status = WSAGetLastError ();
  97. DebugLastError (_T("Q931: Failed to bind dest socket.\n"));
  98. goto cleanup;
  99. }
  100. // Set keepalive on the socket
  101. KeepaliveOption = TRUE;
  102. if (SOCKET_ERROR == setsockopt (Socket, SOL_SOCKET, SO_KEEPALIVE,
  103. (PCHAR) &KeepaliveOption, sizeof (KeepaliveOption)))
  104. {
  105. Status = WSAGetLastError ();
  106. DebugLastError (_T("Q931: Failed to set keepalive on the dest socket.\n"));
  107. goto cleanup;
  108. }
  109. if (getsockname (Socket, (struct sockaddr *)&LocalAddress, &AddressSize)) {
  110. Status = WSAGetLastError ();
  111. DebugLastError (_T("Q931: Failed to get name of TCP socket.\n"));
  112. goto cleanup;
  113. }
  114. // Create a trivial redirect. This is used to disallow interception of
  115. // Q.931 connect-attempts by more general Q.931 dynamic port redirect established
  116. // during initialization of the proxy. As a side effect it helps to puncture
  117. // the firewall for both H.245 and Q.931 if the firewall is enabled.
  118. Status = CreateTrivialNatRedirect(
  119. ArgRemoteAddress,
  120. &LocalAddress,
  121. 0
  122. );
  123. if(Status != S_OK) {
  124. goto cleanup;
  125. }
  126. RemoteAddress = *ArgRemoteAddress;
  127. // connect to the target server
  128. // -XXX- make this asynchronous some day!!!
  129. Status = connect (Socket, (SOCKADDR *) ArgRemoteAddress, sizeof (SOCKADDR_IN));
  130. if(Status) {
  131. Status = WSAGetLastError ();
  132. goto cleanup;
  133. }
  134. Status = EventMgrBindIoHandle (Socket);
  135. if (Status != S_OK) {
  136. goto cleanup;
  137. }
  138. return ERROR_SUCCESS;
  139. cleanup:
  140. Clear(TRUE);
  141. return Status;
  142. }
  143. HRESULT SOCKET_INFO::CreateTrivialNatRedirect (
  144. IN SOCKADDR_IN * ArgTrivialRedirectDestAddress,
  145. IN SOCKADDR_IN * ArgTrivialRedirectSourceAddress,
  146. IN ULONG RestrictedAdapterIndex)
  147. {
  148. HRESULT Status = S_OK;
  149. ULONG ErrorCode;
  150. ULONG RedirectFlags = NatRedirectFlagLoopback;
  151. _ASSERTE(ArgTrivialRedirectDestAddress);
  152. _ASSERTE(ArgTrivialRedirectSourceAddress);
  153. // Save redirect information. It will be needed when time comes to cancel the redirect.
  154. TrivialRedirectDestAddress.sin_addr.s_addr = ArgTrivialRedirectDestAddress->sin_addr.s_addr;
  155. TrivialRedirectDestAddress.sin_port = ArgTrivialRedirectDestAddress->sin_port;
  156. TrivialRedirectSourceAddress.sin_addr.s_addr = ArgTrivialRedirectSourceAddress->sin_addr.s_addr;
  157. TrivialRedirectSourceAddress.sin_port = ArgTrivialRedirectSourceAddress->sin_port;
  158. if(RestrictedAdapterIndex) {
  159. RedirectFlags |= NatRedirectFlagRestrictAdapter;
  160. }
  161. ErrorCode = NatCreateRedirectEx (
  162. NatHandle,
  163. RedirectFlags,
  164. IPPROTO_TCP,
  165. TrivialRedirectDestAddress.sin_addr.s_addr, // destination address
  166. TrivialRedirectDestAddress.sin_port, // destination port
  167. TrivialRedirectSourceAddress.sin_addr.s_addr, // source addresss
  168. TrivialRedirectSourceAddress.sin_port, // source port
  169. TrivialRedirectDestAddress.sin_addr.s_addr, // new destination address
  170. TrivialRedirectDestAddress.sin_port, // new destination port
  171. TrivialRedirectSourceAddress.sin_addr.s_addr, // new source address
  172. TrivialRedirectSourceAddress.sin_port, // new source port
  173. RestrictedAdapterIndex, // restricted adapter index
  174. NULL, // completion routine
  175. NULL, // completion context
  176. NULL); // notify event
  177. if( NO_ERROR != ErrorCode) {
  178. Status = GetLastErrorAsResult();
  179. DebugF (_T("H323: Failed to set up trivial redirect (%08X:%04X -> %08X:%04X) => (%08X:%04X -> %08X:%04X). Error - %d.\n"),
  180. SOCKADDR_IN_PRINTF(&TrivialRedirectSourceAddress), SOCKADDR_IN_PRINTF(&TrivialRedirectDestAddress),
  181. SOCKADDR_IN_PRINTF(&TrivialRedirectSourceAddress), SOCKADDR_IN_PRINTF(&TrivialRedirectDestAddress),
  182. ErrorCode);
  183. }
  184. else {
  185. DebugF (_T("H323: Set up trivial redirect (%08X:%04X -> %08X:%04X) => (%08X:%04X -> %08X:%04X).\n"),
  186. SOCKADDR_IN_PRINTF(&TrivialRedirectSourceAddress), SOCKADDR_IN_PRINTF(&TrivialRedirectDestAddress),
  187. SOCKADDR_IN_PRINTF(&TrivialRedirectSourceAddress), SOCKADDR_IN_PRINTF(&TrivialRedirectDestAddress));
  188. IsNatRedirectActive = TRUE;
  189. }
  190. return Status;
  191. }
  192. void SOCKET_INFO::Clear (BOOL CancelTrivialRedirect)
  193. {
  194. if (Socket != INVALID_SOCKET) {
  195. closesocket (Socket);
  196. Socket = INVALID_SOCKET;
  197. }
  198. if (CancelTrivialRedirect && IsNatRedirectActive) {
  199. DebugF (_T("H323: Cancelling trivial redirect (%08X:%04X -> %08X:%04X) => (%08X:%04X -> %08X:%04X).\n"),
  200. SOCKADDR_IN_PRINTF(&TrivialRedirectSourceAddress), SOCKADDR_IN_PRINTF(&TrivialRedirectDestAddress),
  201. SOCKADDR_IN_PRINTF(&TrivialRedirectSourceAddress), SOCKADDR_IN_PRINTF(&TrivialRedirectDestAddress));
  202. NatCancelRedirect (
  203. NatHandle,
  204. IPPROTO_TCP,
  205. TrivialRedirectDestAddress.sin_addr.s_addr, // destination address
  206. TrivialRedirectDestAddress.sin_port, // destination port
  207. TrivialRedirectSourceAddress.sin_addr.s_addr, // source addresss
  208. TrivialRedirectSourceAddress.sin_port, // source port
  209. TrivialRedirectDestAddress.sin_addr.s_addr, // new destination address
  210. TrivialRedirectDestAddress.sin_port, // new destination port
  211. TrivialRedirectSourceAddress.sin_addr.s_addr, // new source address
  212. TrivialRedirectSourceAddress.sin_port // new source port
  213. );
  214. IsNatRedirectActive = FALSE;
  215. }
  216. }
  217. SOCKET_INFO::~SOCKET_INFO (void)
  218. {
  219. Clear(TRUE);
  220. }