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>
21 #if defined(AFS_NT40_ENV)
24 #if (_WIN32_WINNT < 0x0501)
26 #define _WIN32_WINNT 0x0501
30 #if (_WIN32_WINNT < 0x0600)
32 * WSASendMsg -- send data to a specific destination, with options, using
33 * overlapped I/O where applicable.
35 * Valid flags for dwFlags parameter:
37 * MSG_PARTIAL (a.k.a. MSG_EOR) (only for non-stream sockets)
38 * MSG_OOB (only for stream style sockets) (NYI)
40 * Caller must provide either lpOverlapped or lpCompletionRoutine
41 * or neither (both NULL).
45 (PASCAL FAR * LPFN_WSASENDMSG) (
49 __out_opt LPDWORD lpNumberOfBytesSent,
50 IN LPWSAOVERLAPPED lpOverlapped OPTIONAL,
51 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine OPTIONAL
54 #define WSAID_WSASENDMSG /* a441e712-754f-43ca-84a7-0dee44cf606d */ \
55 {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
56 #endif /* _WINNT_WIN32 */
59 #include "rx_packet.h"
60 #include "rx_globals.h"
61 #include "rx_xmit_nt.h"
67 * WSASendMsg is only supported on Vista and above
68 * Neither function is part of the public WinSock API
69 * and therefore the function pointers must be
70 * obtained via WSAIoctl()
72 static LPFN_WSARECVMSG pWSARecvMsg = NULL;
73 static LPFN_WSASENDMSG pWSASendMsg = NULL;
76 rxi_xmit_init(osi_socket s)
79 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
80 GUID WSASendMsg_GUID = WSAID_WSASENDMSG;
81 DWORD dwIn, dwOut, NumberOfBytes;
83 rc = WSAIoctl( s, SIO_GET_EXTENSION_FUNCTION_POINTER,
84 &WSARecvMsg_GUID, sizeof(WSARecvMsg_GUID),
85 &pWSARecvMsg, sizeof(pWSARecvMsg),
86 &NumberOfBytes, NULL, NULL);
88 rc = WSAIoctl( s, SIO_GET_EXTENSION_FUNCTION_POINTER,
89 &WSASendMsg_GUID, sizeof(WSASendMsg_GUID),
90 &pWSASendMsg, sizeof(pWSASendMsg),
91 &NumberOfBytes, NULL, NULL);
93 /* Turn on UDP PORT_UNREACHABLE messages */
95 rc = WSAIoctl( s, SIO_UDP_CONNRESET,
97 &dwOut, sizeof(dwOut),
98 &NumberOfBytes, NULL, NULL);
102 recvmsg(osi_socket socket, struct msghdr *msgP, int flags)
110 wsaMsg.name = (LPSOCKADDR)(msgP->msg_name);
111 wsaMsg.namelen = (INT)(msgP->msg_namelen);
113 wsaMsg.lpBuffers = (LPWSABUF) msgP->msg_iov;
114 wsaMsg.dwBufferCount = msgP->msg_iovlen;
115 wsaMsg.Control.len = 0;
116 wsaMsg.Control.buf = NULL;
117 wsaMsg.dwFlags = flags;
119 code = pWSARecvMsg(socket, &wsaMsg, &dwBytes, NULL, NULL);
121 /* success - return the number of bytes read */
124 /* error - set errno and return -1 */
125 if (code == SOCKET_ERROR)
126 code = WSAGetLastError();
127 if (code == WSAEWOULDBLOCK || code == WSAECONNRESET)
128 errno = WSAEWOULDBLOCK;
134 char rbuf[RX_MAX_PACKET_SIZE];
139 size = rx_maxJumboRecvSize;
141 recvfrom((SOCKET) socket, rbuf, size, flags,
142 (struct sockaddr *)(msgP->msg_name), &(msgP->msg_namelen));
147 for (off = i = 0; size > 0 && i < msgP->msg_iovlen; i++) {
148 if (msgP->msg_iov[i].iov_len) {
149 if (msgP->msg_iov[i].iov_len < size) {
150 n = msgP->msg_iov[i].iov_len;
154 memcpy(msgP->msg_iov[i].iov_base, &rbuf[off], n);
160 /* Accounts for any we didn't copy in to iovecs. */
163 if (code == SOCKET_ERROR)
164 code = WSAGetLastError();
165 if (code == WSAEWOULDBLOCK || code == WSAECONNRESET)
166 errno = WSAEWOULDBLOCK;
177 sendmsg(osi_socket socket, struct msghdr *msgP, int flags)
185 wsaMsg.name = (LPSOCKADDR)(msgP->msg_name);
186 wsaMsg.namelen = (INT)(msgP->msg_namelen);
188 wsaMsg.lpBuffers = (LPWSABUF) msgP->msg_iov;
189 wsaMsg.dwBufferCount = msgP->msg_iovlen;
190 wsaMsg.Control.len = 0;
191 wsaMsg.Control.buf = NULL;
194 code = pWSASendMsg(socket, &wsaMsg, flags, &dwBytes, NULL, NULL);
196 /* success - return the number of bytes read */
199 /* error - set errno and return -1 */
200 if (code == SOCKET_ERROR)
201 code = WSAGetLastError();
210 errno = WSAEWOULDBLOCK;
212 case WSAEHOSTUNREACH:
213 errno = WSAEHOSTUNREACH;
222 char buf[RX_MAX_PACKET_SIZE];
228 for (size = i = 0; i < msgP->msg_iovlen; i++)
229 size += msgP->msg_iov[i].iov_len;
231 if (msgP->msg_iovlen <= 2) {
232 sbuf = msgP->msg_iov[0].iov_base;
234 /* Pack data into array from iovecs */
236 for (off = i = 0; tmp > 0 && i < msgP->msg_iovlen; i++) {
237 if (msgP->msg_iov[i].iov_len > 0) {
238 if (tmp > msgP->msg_iov[i].iov_len)
239 n = msgP->msg_iov[i].iov_len;
242 memcpy(&sbuf[off], msgP->msg_iov[i].iov_base, n);
250 sendto((SOCKET) socket, sbuf, size, flags,
251 (struct sockaddr *)(msgP->msg_name), msgP->msg_namelen);
252 if (code == SOCKET_ERROR) {
253 code = WSAGetLastError();
262 errno = WSAEWOULDBLOCK;
264 case WSAEHOSTUNREACH:
265 errno = WSAEHOSTUNREACH;
282 #endif /* AFS_NT40_ENV */