Fix the handling of out-of-band (OOB) data in a socket.

* fhandler.h (class fhandler_socket_inet): Add variable bool oobinline.
* fhandler_socket_inet.cc (fhandler_socket_inet::fhandler_socket_inet):
  Initialize variable oobinline.
(fhandler_socket_inet::recv_internal): Make the handling of OOB data
  as consistent with POSIX as possible. Add simulation of inline mode
  for OOB data as a workaround for broken winsock behavior.
(fhandler_socket_inet::setsockopt): Ditto.
(fhandler_socket_inet::getsockopt): Ditto.
(fhandler_socket_wsock::ioctl): Fix return value of SIOCATMARK command.
  The return value of SIOCATMARK of winsock is almost opposite to
  expectation.
* fhandler_socket_local.cc (fhandler_socket_local::recv_internal):
  Remove the handling of OOB data from AF_LOCAL domain socket. Operation
  related to OOB data will result in an error like Linux does.
(fhandler_socket_local::sendto): Ditto.
(fhandler_socket_local::sendmsg): Ditto.

This fixes the issue reported in following post.
https://cygwin.com/ml/cygwin/2018-06/msg00143.html
This commit is contained in:
Takashi Yano
2018-06-21 23:11:49 +09:00
committed by Corinna Vinschen
parent 3baadb9912
commit 9c84bfd479
3 changed files with 120 additions and 9 deletions

View File

@@ -1065,7 +1065,7 @@ fhandler_socket_local::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
{
ssize_t res = 0;
DWORD ret = 0, wret;
int evt_mask = FD_READ | ((wsamsg->dwFlags & MSG_OOB) ? FD_OOB : 0);
int evt_mask = FD_READ;
LPWSABUF &wsabuf = wsamsg->lpBuffers;
ULONG &wsacnt = wsamsg->dwBufferCount;
static NO_COPY LPFN_WSARECVMSG WSARecvMsg;
@@ -1080,7 +1080,15 @@ fhandler_socket_local::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
DWORD wait_flags = wsamsg->dwFlags;
bool waitall = !!(wait_flags & MSG_WAITALL);
wsamsg->dwFlags &= (MSG_OOB | MSG_PEEK | MSG_DONTROUTE);
/* Out-of-band data not supported by AF_LOCAL */
if (wsamsg->dwFlags & MSG_OOB)
{
set_errno (EOPNOTSUPP);
return SOCKET_ERROR;
}
wsamsg->dwFlags &= (MSG_PEEK | MSG_DONTROUTE);
if (use_recvmsg)
{
if (!WSARecvMsg
@@ -1104,7 +1112,7 @@ fhandler_socket_local::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
set_winsock_errno ();
return SOCKET_ERROR;
}
if (is_nonblocking () || (wsamsg->dwFlags & (MSG_OOB | MSG_PEEK)))
if (is_nonblocking () || (wsamsg->dwFlags & MSG_PEEK))
waitall = false;
}
@@ -1114,6 +1122,7 @@ fhandler_socket_local::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
while (!(res = wait_for_events (evt_mask | FD_CLOSE, wait_flags))
|| saw_shutdown_read ())
{
DWORD dwFlags = wsamsg->dwFlags;
if (use_recvmsg)
res = WSARecvMsg (get_socket (), wsamsg, &wret, NULL, NULL);
/* This is working around a really weird problem in WinSock.
@@ -1135,11 +1144,11 @@ fhandler_socket_local::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
namelen is a valid pointer while name is NULL. Both parameters are
ignored for TCP sockets, so this only occurs when using UDP socket. */
else if (!wsamsg->name || get_socket_type () == SOCK_STREAM)
res = WSARecv (get_socket (), wsabuf, wsacnt, &wret, &wsamsg->dwFlags,
res = WSARecv (get_socket (), wsabuf, wsacnt, &wret, &dwFlags,
NULL, NULL);
else
res = WSARecvFrom (get_socket (), wsabuf, wsacnt, &wret,
&wsamsg->dwFlags, wsamsg->name, &wsamsg->namelen,
&dwFlags, wsamsg->name, &wsamsg->namelen,
NULL, NULL);
if (!res)
{
@@ -1236,6 +1245,13 @@ fhandler_socket_local::sendto (const void *in_ptr, size_t len, int flags,
char *ptr = (char *) in_ptr;
struct sockaddr_storage sst;
/* Out-of-band data not supported by AF_LOCAL */
if (flags & MSG_OOB)
{
set_errno (EOPNOTSUPP);
return SOCKET_ERROR;
}
if (to && get_inet_addr_local (to, tolen, &sst, &tolen) == SOCKET_ERROR)
return SOCKET_ERROR;
@@ -1274,6 +1290,13 @@ fhandler_socket_local::sendmsg (const struct msghdr *msg, int flags)
struct sockaddr_storage sst;
int len = 0;
/* Out-of-band data not supported by AF_LOCAL */
if (flags & MSG_OOB)
{
set_errno (EOPNOTSUPP);
return SOCKET_ERROR;
}
if (msg->msg_name
&& get_inet_addr_local ((struct sockaddr *) msg->msg_name,
msg->msg_namelen, &sst, &len) == SOCKET_ERROR)