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 */