2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* NT does not have uio structs, so we roll our own sendmsg and recvmsg.
12 * The dangerous part of this code is that it assumes that iovecs 0 and 1
13 * are contiguous and that all of 0 is used before any of 1.
14 * This is true if rx_packets are being sent, so we should be ok.
17 #include <afsconfig.h>
18 #include <afs/param.h>
20 #if defined(AFS_NT40_ENV)
22 # if (_WIN32_WINNT < 0x0501)
24 # define _WIN32_WINNT 0x0501
28 # if (_WIN32_WINNT < 0x0600)
30 * WSASendMsg -- send data to a specific destination, with options, using
31 * overlapped I/O where applicable.
33 * Valid flags for dwFlags parameter:
35 * MSG_PARTIAL (a.k.a. MSG_EOR) (only for non-stream sockets)
36 * MSG_OOB (only for stream style sockets) (NYI)
38 * Caller must provide either lpOverlapped or lpCompletionRoutine
39 * or neither (both NULL).
43 (PASCAL FAR * LPFN_WSASENDMSG) (
47 __out_opt LPDWORD lpNumberOfBytesSent,
48 IN LPWSAOVERLAPPED lpOverlapped OPTIONAL,
49 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine OPTIONAL
52 # define WSAID_WSASENDMSG /* a441e712-754f-43ca-84a7-0dee44cf606d */ \
53 {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
54 #endif /* AFS_NT40_ENV */
57 #include "rx_globals.h"
58 #include "rx_packet.h"
59 #include "rx_xmit_nt.h"
64 * WSASendMsg is only supported on Vista and above
65 * Neither function is part of the public WinSock API
66 * and therefore the function pointers must be
67 * obtained via WSAIoctl()
69 static LPFN_WSARECVMSG pWSARecvMsg = NULL;
70 static LPFN_WSASENDMSG pWSASendMsg = NULL;
73 rxi_xmit_init(osi_socket s)
76 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
77 GUID WSASendMsg_GUID = WSAID_WSASENDMSG;
78 DWORD dwIn, dwOut, NumberOfBytes;
80 rc = WSAIoctl( s, SIO_GET_EXTENSION_FUNCTION_POINTER,
81 &WSARecvMsg_GUID, sizeof(WSARecvMsg_GUID),
82 &pWSARecvMsg, sizeof(pWSARecvMsg),
83 &NumberOfBytes, NULL, NULL);
85 rc = WSAIoctl( s, SIO_GET_EXTENSION_FUNCTION_POINTER,
86 &WSASendMsg_GUID, sizeof(WSASendMsg_GUID),
87 &pWSASendMsg, sizeof(pWSASendMsg),
88 &NumberOfBytes, NULL, NULL);
90 /* Turn on UDP PORT_UNREACHABLE messages */
92 rc = WSAIoctl( s, SIO_UDP_CONNRESET,
94 &dwOut, sizeof(dwOut),
95 &NumberOfBytes, NULL, NULL);
97 /* Turn on UDP CIRCULAR QUEUEING messages */
99 rc = WSAIoctl( s, SIO_ENABLE_CIRCULAR_QUEUEING,
101 &dwOut, sizeof(dwOut),
102 &NumberOfBytes, NULL, NULL);
106 recvmsg(osi_socket socket, struct msghdr *msgP, int flags)
114 wsaMsg.name = (LPSOCKADDR)(msgP->msg_name);
115 wsaMsg.namelen = (INT)(msgP->msg_namelen);
117 wsaMsg.lpBuffers = (LPWSABUF) msgP->msg_iov;
118 wsaMsg.dwBufferCount = msgP->msg_iovlen;
119 wsaMsg.Control.len = 0;
120 wsaMsg.Control.buf = NULL;
121 wsaMsg.dwFlags = flags;
123 code = pWSARecvMsg(socket, &wsaMsg, &dwBytes, NULL, NULL);
125 /* success - return the number of bytes read */
128 /* error - set errno and return -1 */
129 if (code == SOCKET_ERROR)
130 code = WSAGetLastError();
131 if (code == WSAEWOULDBLOCK || code == WSAECONNRESET)
132 errno = WSAEWOULDBLOCK;
138 char rbuf[RX_MAX_PACKET_SIZE];
143 size = rx_maxJumboRecvSize;
145 recvfrom((SOCKET) socket, rbuf, size, flags,
146 (struct sockaddr *)(msgP->msg_name), &(msgP->msg_namelen));
151 for (off = i = 0; size > 0 && i < msgP->msg_iovlen; i++) {
152 if (msgP->msg_iov[i].iov_len) {
153 if (msgP->msg_iov[i].iov_len < size) {
154 n = msgP->msg_iov[i].iov_len;
158 memcpy(msgP->msg_iov[i].iov_base, &rbuf[off], n);
164 /* Accounts for any we didn't copy in to iovecs. */
167 if (code == SOCKET_ERROR)
168 code = WSAGetLastError();
169 if (code == WSAEWOULDBLOCK || code == WSAECONNRESET)
170 errno = WSAEWOULDBLOCK;
181 sendmsg(osi_socket socket, struct msghdr *msgP, int flags)
189 wsaMsg.name = (LPSOCKADDR)(msgP->msg_name);
190 wsaMsg.namelen = (INT)(msgP->msg_namelen);
192 wsaMsg.lpBuffers = (LPWSABUF) msgP->msg_iov;
193 wsaMsg.dwBufferCount = msgP->msg_iovlen;
194 wsaMsg.Control.len = 0;
195 wsaMsg.Control.buf = NULL;
198 code = pWSASendMsg(socket, &wsaMsg, flags, &dwBytes, NULL, NULL);
200 /* success - return the number of bytes read */
203 /* error - set errno and return -1 */
204 if (code == SOCKET_ERROR)
205 code = WSAGetLastError();
214 errno = WSAEWOULDBLOCK;
216 case WSAEHOSTUNREACH:
217 errno = WSAEHOSTUNREACH;
226 char buf[RX_MAX_PACKET_SIZE];
232 for (size = i = 0; i < msgP->msg_iovlen; i++)
233 size += msgP->msg_iov[i].iov_len;
235 if (msgP->msg_iovlen <= 2) {
236 sbuf = msgP->msg_iov[0].iov_base;
238 /* Pack data into array from iovecs */
240 for (off = i = 0; tmp > 0 && i < msgP->msg_iovlen; i++) {
241 if (msgP->msg_iov[i].iov_len > 0) {
242 if (tmp > msgP->msg_iov[i].iov_len)
243 n = msgP->msg_iov[i].iov_len;
246 memcpy(&sbuf[off], msgP->msg_iov[i].iov_base, n);
254 sendto((SOCKET) socket, sbuf, size, flags,
255 (struct sockaddr *)(msgP->msg_name), msgP->msg_namelen);
256 if (code == SOCKET_ERROR) {
257 code = WSAGetLastError();
266 errno = WSAEWOULDBLOCK;
268 case WSAEHOSTUNREACH:
269 errno = WSAEHOSTUNREACH;
286 #endif /* AFS_NT40_ENV */