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 # include <winsock2.h>
23 # if (_WIN32_WINNT < 0x0501)
25 # define _WIN32_WINNT 0x0501
29 # if (_WIN32_WINNT < 0x0600)
31 * WSASendMsg -- send data to a specific destination, with options, using
32 * overlapped I/O where applicable.
34 * Valid flags for dwFlags parameter:
36 * MSG_PARTIAL (a.k.a. MSG_EOR) (only for non-stream sockets)
37 * MSG_OOB (only for stream style sockets) (NYI)
39 * Caller must provide either lpOverlapped or lpCompletionRoutine
40 * or neither (both NULL).
44 (PASCAL FAR * LPFN_WSASENDMSG) (
48 __out_opt LPDWORD lpNumberOfBytesSent,
49 IN LPWSAOVERLAPPED lpOverlapped OPTIONAL,
50 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine OPTIONAL
53 # define WSAID_WSASENDMSG /* a441e712-754f-43ca-84a7-0dee44cf606d */ \
54 {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
55 #endif /* AFS_NT40_ENV */
58 #include "rx_globals.h"
59 #include "rx_packet.h"
60 #include "rx_xmit_nt.h"
66 * WSASendMsg is only supported on Vista and above
67 * Neither function is part of the public WinSock API
68 * and therefore the function pointers must be
69 * obtained via WSAIoctl()
71 static LPFN_WSARECVMSG pWSARecvMsg = NULL;
72 static LPFN_WSASENDMSG pWSASendMsg = NULL;
75 rxi_xmit_init(osi_socket s)
78 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
79 GUID WSASendMsg_GUID = WSAID_WSASENDMSG;
80 DWORD dwIn, dwOut, NumberOfBytes;
82 rc = WSAIoctl( s, SIO_GET_EXTENSION_FUNCTION_POINTER,
83 &WSARecvMsg_GUID, sizeof(WSARecvMsg_GUID),
84 &pWSARecvMsg, sizeof(pWSARecvMsg),
85 &NumberOfBytes, NULL, NULL);
87 rc = WSAIoctl( s, SIO_GET_EXTENSION_FUNCTION_POINTER,
88 &WSASendMsg_GUID, sizeof(WSASendMsg_GUID),
89 &pWSASendMsg, sizeof(pWSASendMsg),
90 &NumberOfBytes, NULL, NULL);
92 /* Turn on UDP PORT_UNREACHABLE messages */
94 rc = WSAIoctl( s, SIO_UDP_CONNRESET,
96 &dwOut, sizeof(dwOut),
97 &NumberOfBytes, NULL, NULL);
99 /* Turn on UDP CIRCULAR QUEUEING messages */
101 rc = WSAIoctl( s, SIO_ENABLE_CIRCULAR_QUEUEING,
103 &dwOut, sizeof(dwOut),
104 &NumberOfBytes, NULL, NULL);
108 recvmsg(osi_socket socket, struct msghdr *msgP, int flags)
116 wsaMsg.name = (LPSOCKADDR)(msgP->msg_name);
117 wsaMsg.namelen = (INT)(msgP->msg_namelen);
119 wsaMsg.lpBuffers = (LPWSABUF) msgP->msg_iov;
120 wsaMsg.dwBufferCount = msgP->msg_iovlen;
121 wsaMsg.Control.len = 0;
122 wsaMsg.Control.buf = NULL;
123 wsaMsg.dwFlags = flags;
125 code = pWSARecvMsg(socket, &wsaMsg, &dwBytes, NULL, NULL);
127 /* success - return the number of bytes read */
130 /* error - set errno and return -1 */
131 if (code == SOCKET_ERROR)
132 code = WSAGetLastError();
133 if (code == WSAEWOULDBLOCK || code == WSAECONNRESET)
134 errno = WSAEWOULDBLOCK;
140 char rbuf[RX_MAX_PACKET_SIZE];
145 size = rx_maxJumboRecvSize;
147 recvfrom((SOCKET) socket, rbuf, size, flags,
148 (struct sockaddr *)(msgP->msg_name), &(msgP->msg_namelen));
153 for (off = i = 0; size > 0 && i < msgP->msg_iovlen; i++) {
154 if (msgP->msg_iov[i].iov_len) {
155 if (msgP->msg_iov[i].iov_len < size) {
156 n = msgP->msg_iov[i].iov_len;
160 memcpy(msgP->msg_iov[i].iov_base, &rbuf[off], n);
166 /* Accounts for any we didn't copy in to iovecs. */
169 if (code == SOCKET_ERROR)
170 code = WSAGetLastError();
171 if (code == WSAEWOULDBLOCK || code == WSAECONNRESET)
172 errno = WSAEWOULDBLOCK;
183 sendmsg(osi_socket socket, struct msghdr *msgP, int flags)
191 wsaMsg.name = (LPSOCKADDR)(msgP->msg_name);
192 wsaMsg.namelen = (INT)(msgP->msg_namelen);
194 wsaMsg.lpBuffers = (LPWSABUF) msgP->msg_iov;
195 wsaMsg.dwBufferCount = msgP->msg_iovlen;
196 wsaMsg.Control.len = 0;
197 wsaMsg.Control.buf = NULL;
200 code = pWSASendMsg(socket, &wsaMsg, flags, &dwBytes, NULL, NULL);
202 /* success - return the number of bytes read */
205 /* error - set errno and return -1 */
206 if (code == SOCKET_ERROR)
207 code = WSAGetLastError();
216 errno = WSAEWOULDBLOCK;
218 case WSAEHOSTUNREACH:
219 errno = WSAEHOSTUNREACH;
228 char buf[RX_MAX_PACKET_SIZE];
234 for (size = i = 0; i < msgP->msg_iovlen; i++)
235 size += msgP->msg_iov[i].iov_len;
237 if (msgP->msg_iovlen <= 2) {
238 sbuf = msgP->msg_iov[0].iov_base;
240 /* Pack data into array from iovecs */
242 for (off = i = 0; tmp > 0 && i < msgP->msg_iovlen; i++) {
243 if (msgP->msg_iov[i].iov_len > 0) {
244 if (tmp > msgP->msg_iov[i].iov_len)
245 n = msgP->msg_iov[i].iov_len;
248 memcpy(&sbuf[off], msgP->msg_iov[i].iov_base, n);
256 sendto((SOCKET) socket, sbuf, size, flags,
257 (struct sockaddr *)(msgP->msg_name), msgP->msg_namelen);
258 if (code == SOCKET_ERROR) {
259 code = WSAGetLastError();
268 errno = WSAEWOULDBLOCK;
270 case WSAEHOSTUNREACH:
271 errno = WSAEHOSTUNREACH;
288 #endif /* AFS_NT40_ENV */