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.

341 lines
8.7 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. Afd.cxx
  5. Abstract:
  6. Wrappers to simulate winsock API directly on top of AFD IOCTLS.
  7. Author:
  8. Mario Goertzel [MarioGo]
  9. Revision History:
  10. MarioGo 4/4/1997 Based on NT 4 DG code.
  11. --*/
  12. #include <precomp.hxx>
  13. #include <tdi.h>
  14. #include <clustdi.h>
  15. #include <afd.h>
  16. void
  17. InitializeRawAddress(
  18. IN WS_SOCKADDR *pSockAddr,
  19. OUT PVOID pRawAddress,
  20. OUT DWORD *pdwRawAddressSize
  21. )
  22. /*++
  23. Routine Description:
  24. Converts from a winsock sockaddr to a TDI format address.
  25. Arguments:
  26. pSockAddr - The address to convert from, must be either a
  27. AF_INET (IP), AF_IPX, or AF_CLUSTER family address.
  28. pRawAddress - The buffer to store the TDI format address.
  29. pdwRawAddressSize - On return, the size of the TDI format address.
  30. Return Value:
  31. None
  32. --*/
  33. {
  34. #ifdef IPX_ON
  35. ASSERT( pSockAddr->generic.sa_family == AF_INET
  36. || pSockAddr->generic.sa_family == AF_IPX
  37. || pSockAddr->generic.sa_family == AF_CLUSTER);
  38. #else
  39. ASSERT( pSockAddr->generic.sa_family == AF_INET
  40. || pSockAddr->generic.sa_family == AF_CLUSTER);
  41. #endif
  42. switch (pSockAddr->generic.sa_family) {
  43. case AF_INET:
  44. {
  45. // UDP
  46. TA_IP_ADDRESS *pra = (TA_IP_ADDRESS *)pRawAddress;
  47. pra->TAAddressCount = 1;
  48. pra->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
  49. pra->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
  50. pra->Address[0].Address[0].sin_port = pSockAddr->inetaddr.sin_port;
  51. pra->Address[0].Address[0].in_addr = pSockAddr->inetaddr.sin_addr.s_addr;
  52. memset(pra->Address[0].Address[0].sin_zero, 0, 8);
  53. *pdwRawAddressSize = sizeof(TA_IP_ADDRESS);
  54. break;
  55. }
  56. #ifdef IPX_ON
  57. case AF_IPX:
  58. {
  59. // IPX
  60. TA_IPX_ADDRESS *pra = (TA_IPX_ADDRESS *)pRawAddress;
  61. pra->TAAddressCount = 1;
  62. pra->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IPX;
  63. pra->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX;
  64. memcpy(&pra->Address[0].Address[0].NetworkAddress, pSockAddr->ipxaddr.sa_netnum, 4);
  65. memcpy(&pra->Address[0].Address[0].NodeAddress, pSockAddr->ipxaddr.sa_nodenum, 6);
  66. pra->Address[0].Address[0].Socket = pSockAddr->ipxaddr.sa_socket;
  67. *pdwRawAddressSize = sizeof(TA_IPX_ADDRESS);
  68. break;
  69. }
  70. #endif
  71. case AF_CLUSTER:
  72. {
  73. // Clusters
  74. TA_CLUSTER_ADDRESS *pra = (TA_CLUSTER_ADDRESS *)pRawAddress;
  75. pra->TAAddressCount = 1;
  76. pra->Address[0].AddressLength = TDI_ADDRESS_LENGTH_CLUSTER;
  77. pra->Address[0].AddressType = TDI_ADDRESS_TYPE_CLUSTER;
  78. pra->Address[0].Address[0].Port = pSockAddr->clusaddr.sac_port;
  79. pra->Address[0].Address[0].Node = pSockAddr->clusaddr.sac_node;
  80. pra->Address[0].Address[0].ReservedMBZ = 0;
  81. *pdwRawAddressSize = sizeof(TA_CLUSTER_ADDRESS);
  82. }
  83. }
  84. return;
  85. }
  86. int
  87. WSAAPI
  88. AFD_SendTo(
  89. SOCKET s,
  90. LPWSABUF lpBuffers,
  91. DWORD dwBufferCount,
  92. LPDWORD lpNumberOfBytesSent,
  93. DWORD dwFlags,
  94. const struct sockaddr FAR * lpTo,
  95. int iTolen,
  96. LPWSAOVERLAPPED lpOverlapped,
  97. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  98. )
  99. /*++
  100. Routine Description:
  101. Implement's a wrapper around the AFD recv IOCTL which looks like WSASendTo.
  102. RPC uses this when MSAFD is the network provider.
  103. Note:
  104. Try reading private\net\sockets\winsock2\wsp\msafd\send.c if you want
  105. more information.
  106. Arguments:
  107. WSASendTo arguments
  108. Return Value:
  109. 0 - success
  110. ERROR_IO_PENDING - IO submitted
  111. non-zero - error
  112. --*/
  113. {
  114. PIO_STATUS_BLOCK pIoStatus = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
  115. AFD_SEND_DATAGRAM_INFO sendInfo;
  116. UCHAR abRawAddress[max(sizeof(TA_IP_ADDRESS),sizeof(TA_IPX_ADDRESS))];
  117. DWORD dwRawAddressSize;
  118. int status;
  119. NTSTATUS NtStatus;
  120. ASSERT(lpCompletionRoutine == 0);
  121. ASSERT(lpOverlapped);
  122. InitializeRawAddress((WS_SOCKADDR *)lpTo, abRawAddress, &dwRawAddressSize);
  123. sendInfo.AfdFlags = AFD_OVERLAPPED;
  124. sendInfo.BufferArray = lpBuffers;
  125. sendInfo.BufferCount = dwBufferCount;
  126. sendInfo.TdiRequest.SendDatagramInformation = &sendInfo.TdiConnInfo;
  127. sendInfo.TdiConnInfo.UserDataLength = 0;
  128. sendInfo.TdiConnInfo.UserData = 0;
  129. sendInfo.TdiConnInfo.OptionsLength = 0;
  130. sendInfo.TdiConnInfo.Options = 0;
  131. sendInfo.TdiConnInfo.RemoteAddressLength = dwRawAddressSize;
  132. sendInfo.TdiConnInfo.RemoteAddress = abRawAddress;
  133. pIoStatus->Status = STATUS_PENDING;
  134. NtStatus = NtDeviceIoControlFile(
  135. (HANDLE)s,
  136. lpOverlapped->hEvent,
  137. NULL,
  138. ( PtrToUlong(lpOverlapped->hEvent) & 1 ) ? NULL : lpOverlapped,
  139. pIoStatus,
  140. IOCTL_AFD_SEND_DATAGRAM,
  141. &sendInfo,
  142. sizeof(sendInfo),
  143. NULL,
  144. 0
  145. );
  146. if (NtStatus == STATUS_PENDING)
  147. {
  148. SetLastError(WSA_IO_PENDING);
  149. *lpNumberOfBytesSent = 0;
  150. return(-1);
  151. }
  152. if (NtStatus == STATUS_HOST_DOWN)
  153. {
  154. SetLastError(WSAEHOSTDOWN);
  155. return(-1);
  156. }
  157. if (!NT_SUCCESS(NtStatus))
  158. {
  159. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  160. DPFLTR_WARNING_LEVEL,
  161. RPCTRANS "Afd send failed: 0x%x\n",
  162. NtStatus));
  163. SetLastError(RtlNtStatusToDosError(NtStatus));
  164. return(-1);
  165. }
  166. *lpNumberOfBytesSent = ULONG(pIoStatus->Information);
  167. ASSERT(*lpNumberOfBytesSent);
  168. return 0;
  169. }
  170. int
  171. WSAAPI
  172. AFD_RecvFrom(
  173. SOCKET s,
  174. LPWSABUF lpBuffers,
  175. DWORD dwBufferCount,
  176. LPDWORD lpNumberOfBytesRecvd,
  177. LPDWORD lpFlags,
  178. struct sockaddr FAR * lpFrom,
  179. LPINT lpFromlen,
  180. LPWSAOVERLAPPED lpOverlapped,
  181. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  182. )
  183. /*++
  184. Routine Description:
  185. Implement's a wrapper around the AFD recv IOCTL which looks like WSARecvFrom.
  186. RPC uses this when MSAFD is the network provider.
  187. Notes:
  188. Try reading private\net\sockets\winsock2\wsp\msafd\recv.c if you want
  189. more information.
  190. Arguments:
  191. WSARecvFrom arguments
  192. Return Value:
  193. 0 - success
  194. ERROR_IO_PENDING - IO submitted
  195. non-zero - error
  196. --*/
  197. {
  198. PIO_STATUS_BLOCK pIoStatus = (PIO_STATUS_BLOCK )&lpOverlapped->Internal;
  199. AFD_RECV_DATAGRAM_INFO recvInfo;
  200. int status;
  201. NTSTATUS NtStatus;
  202. ASSERT(lpCompletionRoutine == 0);
  203. ASSERT(lpOverlapped);
  204. recvInfo.TdiFlags = TDI_RECEIVE_NORMAL;
  205. recvInfo.AfdFlags = AFD_OVERLAPPED;
  206. recvInfo.BufferArray = lpBuffers;
  207. recvInfo.BufferCount = dwBufferCount;
  208. recvInfo.Address = lpFrom;
  209. recvInfo.AddressLength = (PULONG)lpFromlen;
  210. pIoStatus->Status = STATUS_PENDING;
  211. NtStatus = NtDeviceIoControlFile((HANDLE)s,
  212. lpOverlapped->hEvent,
  213. 0,
  214. ( PtrToUlong(lpOverlapped->hEvent) & 1 ) ? NULL : lpOverlapped,
  215. pIoStatus,
  216. IOCTL_AFD_RECEIVE_DATAGRAM,
  217. &recvInfo,
  218. sizeof(recvInfo),
  219. NULL,
  220. 0);
  221. if (NtStatus == STATUS_PENDING)
  222. {
  223. SetLastError(ERROR_IO_PENDING);
  224. return(ERROR_IO_PENDING);
  225. }
  226. if (!NT_SUCCESS(NtStatus))
  227. {
  228. switch (NtStatus)
  229. {
  230. case STATUS_PORT_UNREACHABLE: status = WSAECONNRESET; break;
  231. case STATUS_HOST_UNREACHABLE: status = WSAEHOSTUNREACH; break;
  232. case STATUS_NETWORK_UNREACHABLE: status = WSAENETUNREACH; break;
  233. case STATUS_BUFFER_OVERFLOW:
  234. case STATUS_RECEIVE_PARTIAL:
  235. {
  236. *lpNumberOfBytesRecvd = -1 * ULONG(pIoStatus->Information);
  237. status = WSAEMSGSIZE;
  238. break;
  239. }
  240. default:
  241. {
  242. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  243. DPFLTR_WARNING_LEVEL,
  244. RPCTRANS "Afd recv failed: 0x%x\n",
  245. NtStatus));
  246. status = RPC_S_OUT_OF_RESOURCES;
  247. break;
  248. }
  249. }
  250. SetLastError( status );
  251. }
  252. else
  253. {
  254. *lpNumberOfBytesRecvd = ULONG(pIoStatus->Information);
  255. status = NO_ERROR;
  256. }
  257. return(status);
  258. }