* autoload.cc: Never load wsock32.dll. Load all wsock32 function

from ws2_32.  Rearrange symbol order accordingly.  None of the ws2_32
	functions is optional right now.
	(wsadata): Move from net.cc here.  Define NO_COPY.
	(wsock_init): Drop unused symbols ws2_32_handle and wsock32_handle.
	(load_wsock32): Remove.
	(WSACleanup): Remove.
	* fhandler_socket.cc: Drop Winsock 1 accommodations throughout.
	(fhandler_socket::readv): Accomodate new POSIX style struct msghdr.
	(fhandler_socket::writev): Ditto.
	(fhandler_socket::recvmsg): Ditto. Handle "old" applications using
	former struct msghdr correctly.
	* net.cc: Drop Winsock 1 accommodations throughout.
	(wsadata): Move definition to autoload.cc.
	(set_socket_inheritance): Remove.
	(convert_ws1_ip_optname): New static function to convert Winsock1
	IPPROTO_IP option values into Winsock2 IPPROTO_IP option values.
	(cygwin_setsockopt): Remove wrong and incomplete cleartext printing
	of optname.  For "old" applications, convert optname from Winsock1
	to Winsock2 values before using them.  Add comment to describe the
	IP_TOS weirdness on W2K and above.
	(cygwin_getsockopt): Remove wrong and incomplete cleartext printing
	of optname.  For "old" applications, convert optname from Winsock1
	to Winsock2 values before using them.
	* select.cc (start_thread_socket): Forget about winsock2_active.
	* winsup.h (wsock32_handle): Remove declaration.
	(ws2_32_handle): Ditto.
	(netapi32_handle): Ditto.
	(wsadata): Ditto.
	(winsock2_active): Remove definition.
	* include/cygwin/socket.h: Change formatting slightly.
	(socklen_t): Move definition up in file.
	(struct msghdr): Convert to POSIX style.
	(struct cmsghdr): New type.
	(CMSG_ALIGN): New macro.
	(CMSG_LEN): Ditto.
	(CMSG_SPACE): Ditto.
	(CMSG_FIRSTHDR): Ditto.
	(CMSG_NXTHDR): Ditto.
	(CMSG_DATA): Ditto.
	(SCM_RIGHTS): Ditto.
	(struct OLD_msghdr): Define old msghdr structure for Cygwin internal
	purposes.
	(MSG_TRUNC): New macro.
	(MSG_CTRUNC): Ditto.
	(IP_OPTIONS): Redefine IPPROTO_IP option values to Winsock2 values.
	Keep Winsock1 values for Cygwin internal purposes.
	* include/cygwin/version.h: Bump API minor version.
	(CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR): Define to check for
	applications using old struct msghdr.
	(CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES): Define to check for
	applications using old Winsock1 IPPROTO_IP values.
This commit is contained in:
Corinna Vinschen 2005-10-17 21:22:18 +00:00
parent 9276ec15a7
commit 8b00a766ff
8 changed files with 406 additions and 471 deletions

View File

@ -1,3 +1,58 @@
2005-10-17 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc: Never load wsock32.dll. Load all wsock32 function
from ws2_32. Rearrange symbol order accordingly. None of the ws2_32
functions is optional right now.
(wsadata): Move from net.cc here. Define NO_COPY.
(wsock_init): Drop unused symbols ws2_32_handle and wsock32_handle.
(load_wsock32): Remove.
(WSACleanup): Remove.
* fhandler_socket.cc: Drop Winsock 1 accommodations throughout.
(fhandler_socket::readv): Accomodate new POSIX style struct msghdr.
(fhandler_socket::writev): Ditto.
(fhandler_socket::recvmsg): Ditto. Handle "old" applications using
former struct msghdr correctly.
* net.cc: Drop Winsock 1 accommodations throughout.
(wsadata): Move definition to autoload.cc.
(set_socket_inheritance): Remove.
(convert_ws1_ip_optname): New static function to convert Winsock1
IPPROTO_IP option values into Winsock2 IPPROTO_IP option values.
(cygwin_setsockopt): Remove wrong and incomplete cleartext printing
of optname. For "old" applications, convert optname from Winsock1
to Winsock2 values before using them. Add comment to describe the
IP_TOS weirdness on W2K and above.
(cygwin_getsockopt): Remove wrong and incomplete cleartext printing
of optname. For "old" applications, convert optname from Winsock1
to Winsock2 values before using them.
* select.cc (start_thread_socket): Forget about winsock2_active.
* winsup.h (wsock32_handle): Remove declaration.
(ws2_32_handle): Ditto.
(netapi32_handle): Ditto.
(wsadata): Ditto.
(winsock2_active): Remove definition.
* include/cygwin/socket.h: Change formatting slightly.
(socklen_t): Move definition up in file.
(struct msghdr): Convert to POSIX style.
(struct cmsghdr): New type.
(CMSG_ALIGN): New macro.
(CMSG_LEN): Ditto.
(CMSG_SPACE): Ditto.
(CMSG_FIRSTHDR): Ditto.
(CMSG_NXTHDR): Ditto.
(CMSG_DATA): Ditto.
(SCM_RIGHTS): Ditto.
(struct OLD_msghdr): Define old msghdr structure for Cygwin internal
purposes.
(MSG_TRUNC): New macro.
(MSG_CTRUNC): Ditto.
(IP_OPTIONS): Redefine IPPROTO_IP option values to Winsock2 values.
Keep Winsock1 values for Cygwin internal purposes.
* include/cygwin/version.h: Bump API minor version.
(CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR): Define to check for
applications using old struct msghdr.
(CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES): Define to check for
applications using old Winsock1 IPPROTO_IP values.
2005-10-13 David Rothenberger <daveroth@acm.org>
Christopher Faylor <cgf@timesys.com>

View File

@ -244,6 +244,7 @@ std_dll_init ()
/* Initialization function for winsock stuff. */
bool NO_COPY wsock_started = 0;
WSADATA NO_COPY wsadata;
__attribute__ ((used, noinline, regparm(1))) static long long
wsock_init ()
{
@ -251,16 +252,6 @@ wsock_init ()
struct func_info *func = (struct func_info *) __builtin_return_address (0);
struct dll_info *dll = func->dll;
__asm__ (" \n\
.section .ws2_32_info \n\
.equ _ws2_32_handle,.ws2_32_info + 4 \n\
.global _ws2_32_handle \n\
.section .wsock32_info \n\
.equ _wsock32_handle,.wsock32_info + 4 \n\
.global _wsock32_handle \n\
.text \n\
");
while (InterlockedIncrement (&here))
{
InterlockedDecrement (&here);
@ -305,7 +296,6 @@ wsock_init ()
return ret.ll;
}
LoadDLLprime (wsock32, _wsock_init)
LoadDLLprime (ws2_32, _wsock_init)
LoadDLLfunc (AccessCheck, 32, advapi32)
@ -452,57 +442,54 @@ LoadDLLfunc (SetProcessWindowStation, 4, user32)
LoadDLLfunc (SetTimer, 16, user32)
LoadDLLfunc (SetUserObjectSecurity, 12, user32)
LoadDLLfuncEx (load_wsock32, 0, wsock32, 1) // non-existent function forces wsock32 load
LoadDLLfunc (WSAAsyncSelect, 16, wsock32)
LoadDLLfunc (WSACleanup, 0, wsock32)
LoadDLLfunc (WSAGetLastError, 0, wsock32)
LoadDLLfunc (WSASetLastError, 4, wsock32)
// LoadDLLfunc (WSAStartup, 8, wsock32)
LoadDLLfunc (__WSAFDIsSet, 8, wsock32)
LoadDLLfunc (accept, 12, wsock32)
LoadDLLfunc (bind, 12, wsock32)
LoadDLLfunc (closesocket, 4, wsock32)
LoadDLLfunc (connect, 12, wsock32)
LoadDLLfunc (gethostbyaddr, 12, wsock32)
LoadDLLfunc (gethostbyname, 4, wsock32)
LoadDLLfuncEx2 (gethostname, 8, wsock32, 1, 1)
LoadDLLfunc (getpeername, 12, wsock32)
LoadDLLfunc (getprotobyname, 4, wsock32)
LoadDLLfunc (getprotobynumber, 4, wsock32)
LoadDLLfunc (getservbyname, 8, wsock32)
LoadDLLfunc (getservbyport, 8, wsock32)
LoadDLLfunc (getsockname, 12, wsock32)
LoadDLLfunc (getsockopt, 20, wsock32)
LoadDLLfunc (inet_addr, 4, wsock32)
LoadDLLfunc (inet_network, 4, wsock32)
LoadDLLfunc (inet_ntoa, 4, wsock32)
LoadDLLfunc (ioctlsocket, 12, wsock32)
LoadDLLfunc (listen, 8, wsock32)
LoadDLLfunc (rcmd, 24, wsock32)
LoadDLLfunc (recv, 16, wsock32)
LoadDLLfunc (recvfrom, 24, wsock32)
LoadDLLfunc (rexec, 24, wsock32)
LoadDLLfunc (rresvport, 4, wsock32)
LoadDLLfunc (select, 20, wsock32)
LoadDLLfunc (send, 16, wsock32)
LoadDLLfunc (sendto, 24, wsock32)
LoadDLLfunc (setsockopt, 20, wsock32)
LoadDLLfunc (shutdown, 8, wsock32)
LoadDLLfunc (socket, 12, wsock32)
LoadDLLfuncEx (WSACloseEvent, 4, ws2_32, 1)
LoadDLLfuncEx (WSACreateEvent, 0, ws2_32, 1)
LoadDLLfuncEx (WSADuplicateSocketA, 12, ws2_32, 1)
LoadDLLfuncEx (WSAGetOverlappedResult, 20, ws2_32, 1)
LoadDLLfuncEx (WSARecv, 28, ws2_32, 1)
LoadDLLfuncEx (WSARecvFrom, 36, ws2_32, 1)
LoadDLLfuncEx (WSASend, 28, ws2_32, 1)
LoadDLLfuncEx (WSASendTo, 36, ws2_32, 1)
LoadDLLfuncEx (WSASetEvent, 4, ws2_32, 1)
LoadDLLfuncEx (WSASocketA, 24, ws2_32, 1)
LoadDLLfuncEx (WSAWaitForMultipleEvents, 20, ws2_32, 1)
LoadDLLfuncEx (WSAEventSelect, 12, ws2_32, 1)
LoadDLLfuncEx (WSAEnumNetworkEvents, 12, ws2_32, 1)
LoadDLLfunc (accept, 12, ws2_32)
LoadDLLfunc (bind, 12, ws2_32)
LoadDLLfunc (closesocket, 4, ws2_32)
LoadDLLfunc (connect, 12, ws2_32)
LoadDLLfunc (gethostbyaddr, 12, ws2_32)
LoadDLLfunc (gethostbyname, 4, ws2_32)
LoadDLLfuncEx2 (gethostname, 8, ws2_32, 1, 1)
LoadDLLfunc (getpeername, 12, ws2_32)
LoadDLLfunc (getprotobyname, 4, ws2_32)
LoadDLLfunc (getprotobynumber, 4, ws2_32)
LoadDLLfunc (getservbyname, 8, ws2_32)
LoadDLLfunc (getservbyport, 8, ws2_32)
LoadDLLfunc (getsockname, 12, ws2_32)
LoadDLLfunc (getsockopt, 20, ws2_32)
LoadDLLfunc (inet_addr, 4, ws2_32)
LoadDLLfunc (inet_network, 4, ws2_32)
LoadDLLfunc (inet_ntoa, 4, ws2_32)
LoadDLLfunc (ioctlsocket, 12, ws2_32)
LoadDLLfunc (listen, 8, ws2_32)
LoadDLLfunc (rcmd, 24, ws2_32)
LoadDLLfunc (recv, 16, ws2_32)
LoadDLLfunc (recvfrom, 24, ws2_32)
LoadDLLfunc (rexec, 24, ws2_32)
LoadDLLfunc (rresvport, 4, ws2_32)
LoadDLLfunc (select, 20, ws2_32)
LoadDLLfunc (send, 16, ws2_32)
LoadDLLfunc (sendto, 24, ws2_32)
LoadDLLfunc (setsockopt, 20, ws2_32)
LoadDLLfunc (shutdown, 8, ws2_32)
LoadDLLfunc (socket, 12, ws2_32)
LoadDLLfunc (WSAAsyncSelect, 16, ws2_32)
LoadDLLfunc (WSACloseEvent, 4, ws2_32)
LoadDLLfunc (WSACreateEvent, 0, ws2_32)
LoadDLLfunc (WSADuplicateSocketA, 12, ws2_32)
LoadDLLfunc (WSAGetLastError, 0, ws2_32)
LoadDLLfunc (WSAGetOverlappedResult, 20, ws2_32)
LoadDLLfunc (WSARecv, 28, ws2_32)
LoadDLLfunc (WSARecvFrom, 36, ws2_32)
LoadDLLfunc (WSASend, 28, ws2_32)
LoadDLLfunc (WSASendTo, 36, ws2_32)
LoadDLLfunc (WSASetEvent, 4, ws2_32)
LoadDLLfunc (WSASetLastError, 4, ws2_32)
LoadDLLfunc (WSASocketA, 24, ws2_32)
// LoadDLLfunc (WSAStartup, 8, ws2_32)
LoadDLLfunc (WSAWaitForMultipleEvents, 20, ws2_32)
LoadDLLfunc (WSAEventSelect, 12, ws2_32)
LoadDLLfunc (WSAEnumNetworkEvents, 12, ws2_32)
LoadDLLfunc (__WSAFDIsSet, 8, ws2_32)
LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1)
LoadDLLfuncEx (GetIfEntry, 4, iphlpapi, 1)

View File

@ -394,12 +394,7 @@ fhandler_socket::af_local_set_secret (char *buf)
void
fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id)
{
if (!winsock2_active)
{
fhandler_base::fixup_before_fork_exec (win_proc_id);
debug_printf ("Without Winsock 2.0");
}
else if (!WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr))
if (!WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr))
debug_printf ("WSADuplicateSocket went fine, sock %p, win_proc_id %d, prot_info_ptr %p",
get_socket (), win_proc_id, prot_info_ptr);
else
@ -410,7 +405,6 @@ fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id)
}
}
extern "C" void __stdcall load_wsock32 ();
void
fhandler_socket::fixup_after_fork (HANDLE parent)
{
@ -428,12 +422,6 @@ fhandler_socket::fixup_after_fork (HANDLE parent)
set_io_handle ((HANDLE)INVALID_SOCKET);
set_winsock_errno ();
}
else if (!new_sock && !winsock2_active)
{
load_wsock32 ();
fhandler_base::fixup_after_fork (parent);
debug_printf ("Without Winsock 2.0");
}
else
{
debug_printf ("WSASocket went fine new_sock %p, old_sock %p", new_sock, get_io_handle ());
@ -447,10 +435,6 @@ fhandler_socket::fixup_after_exec ()
debug_printf ("here");
if (!close_on_exec ())
fixup_after_fork (NULL);
#if 0
else if (!winsock2_active)
closesocket (get_socket ());
#endif
}
int
@ -477,37 +461,34 @@ fhandler_socket::dup (fhandler_base *child)
}
fhs->connect_state (connect_state ());
if (winsock2_active)
/* Since WSADuplicateSocket() fails on NT systems when the process
is currently impersonating a non-privileged account, we revert
to the original account before calling WSADuplicateSocket() and
switch back afterwards as it's also in fork().
If WSADuplicateSocket() still fails for some reason, we fall back
to DuplicateHandle(). */
WSASetLastError (0);
cygheap->user.deimpersonate ();
fhs->set_io_handle (get_io_handle ());
fhs->fixup_before_fork_exec (GetCurrentProcessId ());
cygheap->user.reimpersonate ();
if (!WSAGetLastError ())
{
/* Since WSADuplicateSocket() fails on NT systems when the process
is currently impersonating a non-privileged account, we revert
to the original account before calling WSADuplicateSocket() and
switch back afterwards as it's also in fork().
If WSADuplicateSocket() still fails for some reason, we fall back
to DuplicateHandle(). */
WSASetLastError (0);
cygheap->user.deimpersonate ();
fhs->set_io_handle (get_io_handle ());
fhs->fixup_before_fork_exec (GetCurrentProcessId ());
cygheap->user.reimpersonate ();
if (!WSAGetLastError ())
fhs->fixup_after_fork (hMainProc);
if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET)
{
fhs->fixup_after_fork (hMainProc);
if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET)
{
cygheap->fdtab.inc_need_fixup_before ();
return 0;
}
cygheap->fdtab.inc_need_fixup_before ();
return 0;
}
debug_printf ("WSADuplicateSocket failed, trying DuplicateHandle");
}
debug_printf ("WSADuplicateSocket failed, trying DuplicateHandle");
/* We don't call fhandler_base::dup here since that requires
having winsock called from fhandler_base and it creates only
inheritable sockets which is wrong for winsock2. */
if (!DuplicateHandle (hMainProc, get_io_handle (), hMainProc, &nh, 0,
!winsock2_active, DUPLICATE_SAME_ACCESS))
FALSE, DUPLICATE_SAME_ACCESS))
{
system_printf ("!DuplicateHandle(%x) failed, %E", get_io_handle ());
__seterrno ();
@ -992,8 +973,9 @@ fhandler_socket::readv (const struct iovec *const iov, const int iovcnt,
msg_namelen: 0,
msg_iov: (struct iovec *) iov, // const_cast
msg_iovlen: iovcnt,
msg_accrights: NULL,
msg_accrightslen: 0
msg_control: NULL,
msg_controllen: 0,
msg_flags: 0
};
return recvmsg (&msg, 0, tot);
@ -1007,34 +989,27 @@ fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
DWORD ret = 0;
flags &= MSG_WINMASK;
if (!winsock2_active)
ret = res = ::recvfrom (get_socket (),
(char *) ptr, len, flags,
from, fromlen);
WSABUF wsabuf = { len, (char *) ptr };
if (is_nonblocking () || closed () || async_io ())
res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret,
(DWORD *) &flags, from, fromlen, NULL, NULL);
else
{
WSABUF wsabuf = { len, (char *) ptr };
if (is_nonblocking () || closed () || async_io ())
res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret,
(DWORD *) &flags, from, fromlen, NULL, NULL);
else
HANDLE evt;
if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
{
HANDLE evt;
if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
do
{
do
{
DWORD lflags = (DWORD) flags;
res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, &lflags,
from, fromlen, NULL, NULL);
}
while (res == SOCKET_ERROR
&& WSAGetLastError () == WSAEWOULDBLOCK
&& !closed ()
&& !(res = wait (evt, flags)));
release (evt);
DWORD lflags = (DWORD) flags;
res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, &lflags,
from, fromlen, NULL, NULL);
}
while (res == SOCKET_ERROR
&& WSAGetLastError () == WSAEWOULDBLOCK
&& !closed ()
&& !(res = wait (evt, flags)));
release (evt);
}
}
@ -1056,6 +1031,13 @@ fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
int
fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
{
if (CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR)
((struct OLD_msghdr *) msg)->msg_accrightslen = 0;
else
{
msg->msg_controllen = 0;
msg->msg_flags = 0;
}
if (get_addr_family () == AF_LOCAL)
{
/* On AF_LOCAL sockets the (fixed-size) name of the shared memory
@ -1064,7 +1046,6 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
go ahead recv'ing the normal data blocks. Otherwise start
special handling for descriptor passing. */
/*TODO*/
msg->msg_accrightslen = 0;
}
struct iovec *const iov = msg->msg_iov;
@ -1075,104 +1056,56 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
int res = SOCKET_ERROR;
if (!winsock2_active)
WSABUF wsabuf[iovcnt];
unsigned long len = 0L;
const struct iovec *iovptr = iov + iovcnt;
WSABUF *wsaptr = wsabuf + iovcnt;
do
{
if (iovcnt == 1)
res = recvfrom (iov->iov_base, iov->iov_len, flags, from, fromlen);
else
{
if (tot == -1) // i.e. if not pre-calculated by the caller.
{
tot = 0;
const struct iovec *iovptr = iov + iovcnt;
do
{
iovptr -= 1;
tot += iovptr->iov_len;
}
while (iovptr != iov);
}
char *buf = (char *) alloca (tot);
if (!buf)
{
set_errno (ENOMEM);
res = SOCKET_ERROR;
}
else
{
res = recvfrom (buf, tot, flags, from, fromlen);
const struct iovec *iovptr = iov;
int nbytes = res;
while (nbytes > 0)
{
const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
memcpy (iovptr->iov_base, buf, frag);
buf += frag;
iovptr += 1;
nbytes -= frag;
}
}
}
iovptr -= 1;
wsaptr -= 1;
len += wsaptr->len = iovptr->iov_len;
wsaptr->buf = (char *) iovptr->iov_base;
}
while (wsaptr != wsabuf);
DWORD ret = 0;
if (is_nonblocking () || closed () || async_io ())
res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
(DWORD *) &flags, from, fromlen, NULL, NULL);
else
{
WSABUF wsabuf[iovcnt];
unsigned long len = 0L;
{
const struct iovec *iovptr = iov + iovcnt;
WSABUF *wsaptr = wsabuf + iovcnt;
do
{
iovptr -= 1;
wsaptr -= 1;
len += wsaptr->len = iovptr->iov_len;
wsaptr->buf = (char *) iovptr->iov_base;
}
while (wsaptr != wsabuf);
}
DWORD ret = 0;
if (is_nonblocking () || closed () || async_io ())
res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
(DWORD *) &flags, from, fromlen, NULL, NULL);
else
HANDLE evt;
if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
{
HANDLE evt;
if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
do
{
do
{
DWORD lflags = (DWORD) flags;
res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
&lflags, from, fromlen, NULL, NULL);
}
while (res == SOCKET_ERROR
&& WSAGetLastError () == WSAEWOULDBLOCK
&& !closed ()
&& !(res = wait (evt, flags)));
release (evt);
DWORD lflags = (DWORD) flags;
res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
&lflags, from, fromlen, NULL, NULL);
}
while (res == SOCKET_ERROR
&& WSAGetLastError () == WSAEWOULDBLOCK
&& !closed ()
&& !(res = wait (evt, flags)));
release (evt);
}
if (res == SOCKET_ERROR)
{
/* According to SUSv3, errno isn't set in that case and no error
condition is returned. */
if (WSAGetLastError () == WSAEMSGSIZE)
return len;
set_winsock_errno ();
}
else
res = ret;
}
if (res == SOCKET_ERROR)
{
/* According to SUSv3, errno isn't set in that case and no error
condition is returned. */
if (WSAGetLastError () == WSAEMSGSIZE)
return len;
set_winsock_errno ();
}
else
res = ret;
return res;
}
@ -1186,8 +1119,9 @@ fhandler_socket::writev (const struct iovec *const iov, const int iovcnt,
msg_namelen: 0,
msg_iov: (struct iovec *) iov, // const_cast
msg_iovlen: iovcnt,
msg_accrights: NULL,
msg_accrightslen: 0
msg_control: NULL,
msg_controllen: 0,
msg_flags: 0
};
return sendmsg (&msg, 0, tot);
@ -1205,37 +1139,30 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
int res = SOCKET_ERROR;
DWORD ret = 0;
if (!winsock2_active)
ret = res = ::sendto (get_socket (), (const char *) ptr, len,
flags & MSG_WINMASK,
(to ? (const struct sockaddr *) &sin : NULL), tolen);
WSABUF wsabuf = { len, (char *) ptr };
if (is_nonblocking () || closed () || async_io ())
res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
flags & MSG_WINMASK,
(to ? (const struct sockaddr *) &sin : NULL), tolen,
NULL, NULL);
else
{
WSABUF wsabuf = { len, (char *) ptr };
if (is_nonblocking () || closed () || async_io ())
res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
flags & MSG_WINMASK,
(to ? (const struct sockaddr *) &sin : NULL), tolen,
NULL, NULL);
else
HANDLE evt;
if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
{
HANDLE evt;
if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
do
{
do
{
res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
flags & MSG_WINMASK,
(to ? (const struct sockaddr *) &sin : NULL),
tolen, NULL, NULL);
}
while (res == SOCKET_ERROR
&& WSAGetLastError () == WSAEWOULDBLOCK
&& !(res = wait (evt, 0))
&& !closed ());
release (evt);
res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
flags & MSG_WINMASK,
(to ? (const struct sockaddr *) &sin : NULL),
tolen, NULL, NULL);
}
while (res == SOCKET_ERROR
&& WSAGetLastError () == WSAEWOULDBLOCK
&& !(res = wait (evt, 0))
&& !closed ());
release (evt);
}
}
@ -1277,103 +1204,50 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
int res = SOCKET_ERROR;
if (!winsock2_active)
WSABUF wsabuf[iovcnt];
const struct iovec *iovptr = iov + iovcnt;
WSABUF *wsaptr = wsabuf + iovcnt;
do
{
if (iovcnt == 1)
res = sendto (iov->iov_base, iov->iov_len, flags,
(struct sockaddr *) msg->msg_name,
msg->msg_namelen);
else
{
if (tot == -1) // i.e. if not pre-calculated by the caller.
{
tot = 0;
const struct iovec *iovptr = iov + iovcnt;
do
{
iovptr -= 1;
tot += iovptr->iov_len;
}
while (iovptr != iov);
}
char *const buf = (char *) alloca (tot);
if (!buf)
{
set_errno (ENOMEM);
res = SOCKET_ERROR;
}
else
{
char *bufptr = buf;
const struct iovec *iovptr = iov;
int nbytes = tot;
while (nbytes != 0)
{
const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
memcpy (bufptr, iovptr->iov_base, frag);
bufptr += frag;
iovptr += 1;
nbytes -= frag;
}
res = sendto (buf, tot, flags,
(struct sockaddr *) msg->msg_name,
msg->msg_namelen);
}
}
iovptr -= 1;
wsaptr -= 1;
wsaptr->len = iovptr->iov_len;
wsaptr->buf = (char *) iovptr->iov_base;
}
while (wsaptr != wsabuf);
DWORD ret = 0;
if (is_nonblocking () || closed () || async_io ())
res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret,
flags, (struct sockaddr *) msg->msg_name,
msg->msg_namelen, NULL, NULL);
else
{
WSABUF wsabuf[iovcnt];
{
const struct iovec *iovptr = iov + iovcnt;
WSABUF *wsaptr = wsabuf + iovcnt;
do
{
iovptr -= 1;
wsaptr -= 1;
wsaptr->len = iovptr->iov_len;
wsaptr->buf = (char *) iovptr->iov_base;
}
while (wsaptr != wsabuf);
}
DWORD ret = 0;
if (is_nonblocking () || closed () || async_io ())
res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret,
flags, (struct sockaddr *) msg->msg_name,
msg->msg_namelen, NULL, NULL);
else
HANDLE evt;
if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
{
HANDLE evt;
if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
do
{
do
{
res = WSASendTo (get_socket (), wsabuf, iovcnt,
&ret, flags,
(struct sockaddr *) msg->msg_name,
msg->msg_namelen, NULL, NULL);
}
while (res == SOCKET_ERROR
&& WSAGetLastError () == WSAEWOULDBLOCK
&& !(res = wait (evt, 0))
&& !closed ());
release (evt);
res = WSASendTo (get_socket (), wsabuf, iovcnt,
&ret, flags,
(struct sockaddr *) msg->msg_name,
msg->msg_namelen, NULL, NULL);
}
while (res == SOCKET_ERROR
&& WSAGetLastError () == WSAEWOULDBLOCK
&& !(res = wait (evt, 0))
&& !closed ());
release (evt);
}
if (res == SOCKET_ERROR)
set_winsock_errno ();
else
res = ret;
}
if (res == SOCKET_ERROR)
set_winsock_errno ();
else
res = ret;
/* Special handling for EPIPE and SIGPIPE.
EPIPE is generated if the local end has been shut down on a connection
@ -1628,8 +1502,6 @@ fhandler_socket::fcntl (int cmd, void *arg)
void
fhandler_socket::set_close_on_exec (bool val)
{
if (!winsock2_active) /* < Winsock 2.0 */
set_no_inheritance (get_handle (), val);
close_on_exec (val);
debug_printf ("set close_on_exec for %s to %d", get_name (), val);
}

View File

@ -1,6 +1,6 @@
/* cygwin/socket.h
Copyright 1999, 2000, 2001 Red Hat, Inc.
Copyright 1999, 2000, 2001, 2005 Red Hat, Inc.
This file is part of Cygwin.
@ -26,30 +26,80 @@ struct sockaddr {
#include <sys/types.h>
struct ucred {
pid_t pid;
__uid32_t uid;
__gid32_t gid;
pid_t pid;
__uid32_t uid;
__gid32_t gid;
};
struct linger {
unsigned short l_onoff; /* Linger active */
unsigned short l_linger; /* How long to linger for */
};
struct msghdr
{
void * msg_name; /* Socket name */
int msg_namelen; /* Length of name */
struct iovec * msg_iov; /* Data blocks */
int msg_iovlen; /* Number of blocks */
void * msg_accrights; /* Per protocol magic (eg BSD file descriptor passing) */
int msg_accrightslen; /* Length of rights list */
unsigned short l_onoff; /* Linger active */
unsigned short l_linger; /* How long to linger for */
};
#ifndef socklen_t
#define socklen_t int
#endif
struct msghdr
{
void * msg_name; /* Socket name */
socklen_t msg_namelen; /* Length of name */
struct iovec * msg_iov; /* Data blocks */
int msg_iovlen; /* Number of blocks */
void * msg_control; /* Ancillary data */
socklen_t msg_controllen; /* Ancillary data buffer length */
int msg_flags; /* Received flags on recvmsg */
};
struct cmsghdr
{
socklen_t cmsg_len; /* Length of cmsghdr + data */
int cmsg_level; /* Protocol */
int cmsg_type; /* Protocol type */
};
#define CMSG_ALIGN(len) \
(((len) + sizeof (size_t) - 1) & ~(sizeof (size_t) - 1))
#define CMSG_LEN(len) \
(CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
#define CMSG_SPACE(len) \
(CMSG_ALIGN (sizeof (struct cmsghdr)) + CMSG_ALIGN(len))
#define CMSG_FIRSTHDR(mhdr) \
({ \
struct msghdr *_m = (struct msghdr *) mhdr; \
(_m)->msg_controllen >= sizeof (struct cmsghdr) \
? (struct cmsghdr *) (_m)->msg_control \
: (struct cmsghdr *) NULL; \
})
#define CMSG_NXTHDR(mhdr,cmsg) \
({ \
struct msghdr *_m = (struct msghdr *) mhdr; \
struct cmsghdr *_c = (struct cmsghdr *) cmsg; \
((char *) _c + CMSG_SPACE (_c->cmsg_len) \
> (char *) _m->msg_control + _m->msg_controllen) \
? (struct cmsghdr *) NULL \
: (struct cmsghdr *) ((char *) _c + CMSG_ALIGN (_c->cmsg_len)); \
})
#define CMSG_DATA(cmsg) \
((unsigned char *) ((struct cmsghdr *)(cmsg) + 1))
/* "Socket"-level control message types: */
#define SCM_RIGHTS 0x01 /* access rights (array of int) */
#ifdef __INSIDE_CYGWIN__
/* Definition of struct msghdr up to release 1.5.18 */
struct OLD_msghdr
{
void * msg_name; /* Socket name */
int msg_namelen; /* Length of name */
struct iovec * msg_iov; /* Data blocks */
int msg_iovlen; /* Number of blocks */
void * msg_accrights; /* Per protocol magic */
/* (eg BSD descriptor passing) */
int msg_accrightslen; /* Length of rights list */
};
#endif
/* Socket types. */
#define SOCK_STREAM 1 /* stream (connection) socket */
#define SOCK_DGRAM 2 /* datagram (conn.less) socket */
@ -124,6 +174,8 @@ struct msghdr
#define MSG_DONTROUTE 0x4 /* send without using routing tables */
#define MSG_WINMASK 0x7 /* flags understood by WinSock calls */
#define MSG_NOSIGNAL 0x20 /* Don't raise SIGPIPE */
#define MSG_TRUNC 0x0100 /* Normal data truncated */
#define MSG_CTRUNC 0x0200 /* Control data truncated */
/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
#define SOL_IP 0
@ -146,17 +198,35 @@ struct msghdr
#define IP_DEFAULT_MULTICAST_LOOP 1
#define IP_MAX_MEMBERSHIPS 20
/* IP options for use with WinSock */
/* IP options for use with getsockopt/setsockopt */
#define IP_OPTIONS 1
#define IP_HDRINCL 2
#define IP_TOS 3
#define IP_TTL 4
#define IP_MULTICAST_IF 9
#define IP_MULTICAST_TTL 10
#define IP_MULTICAST_LOOP 11
#define IP_ADD_MEMBERSHIP 12
#define IP_DROP_MEMBERSHIP 13
#define IP_DONTFRAGMENT 14
#define IP_ADD_SOURCE_MEMBERSHIP 15
#define IP_DROP_SOURCE_MEMBERSHIP 16
#define IP_BLOCK_SOURCE 17
#define IP_UNBLOCK_SOURCE 18
#define IP_PKTINFO 19
#define IP_OPTIONS 1
#define IP_MULTICAST_IF 2
#define IP_MULTICAST_TTL 3
#define IP_MULTICAST_LOOP 4
#define IP_ADD_MEMBERSHIP 5
#define IP_DROP_MEMBERSHIP 6
#define IP_TTL 7
#define IP_TOS 8
#define IP_DONTFRAGMENT 9
/* Old WinSock1 values, needed internally */
#ifdef __INSIDE_CYGWIN__
#define _WS1_IP_OPTIONS 1
#define _WS1_IP_MULTICAST_IF 2
#define _WS1_IP_MULTICAST_TTL 3
#define _WS1_IP_MULTICAST_LOOP 4
#define _WS1_IP_ADD_MEMBERSHIP 5
#define _WS1_IP_DROP_MEMBERSHIP 6
#define _WS1_IP_TTL 7
#define _WS1_IP_TOS 8
#define _WS1_IP_DONTFRAGMENT 9
#endif
/* IPX options */
#define IPX_TYPE 1

View File

@ -88,6 +88,15 @@ details. */
#define CYGWIN_VERSION_CHECK_FOR_USING_BIG_TYPES \
(CYGWIN_VERSION_DLL_MAKE_COMBINED (user_data->api_major, user_data->api_minor) >= \
79)
#define CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR \
(CYGWIN_VERSION_DLL_MAKE_COMBINED (user_data->api_major, user_data->api_minor) <= \
138)
#define CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES \
(CYGWIN_VERSION_DLL_MAKE_COMBINED (user_data->api_major, user_data->api_minor) <= \
138)
/* We used to use the DLL major/minor to track
non-backward-compatible interface changes to the API. Now we
use an API major/minor number for this purpose. */
@ -266,12 +275,14 @@ details. */
137: fts_children, fts_close, fts_get_clientptr, fts_get_stream,
fts_open, fts_read, fts_set, fts_set_clientptr, ftw, nftw.
138: Export readdir_r.
139: Start using POSIX definition of struct msghdr and WinSock2
IPPROTO_IP values.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
#define CYGWIN_VERSION_API_MINOR 138
#define CYGWIN_VERSION_API_MINOR 139
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible

View File

@ -29,6 +29,8 @@ details. */
#include <assert.h>
#include "cygerrno.h"
#include "security.h"
#include "cygwin/version.h"
#include "perprocess.h"
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
@ -50,8 +52,6 @@ extern "C"
int sscanf (const char *, const char *, ...);
} /* End of "C" section */
WSADATA wsadata;
static fhandler_socket *
get (const int fd)
{
@ -68,20 +68,6 @@ get (const int fd)
return fh;
}
static SOCKET __stdcall
set_socket_inheritance (SOCKET sock)
{
SOCKET osock = sock;
if (!DuplicateHandle (hMainProc, (HANDLE) sock, hMainProc, (HANDLE *) &sock,
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
system_printf ("DuplicateHandle failed %E");
else
debug_printf ("DuplicateHandle succeeded osock %p, sock %p", osock, sock);
VerifyHandle ((HANDLE) sock);
return sock;
}
/* htonl: standards? */
extern "C" unsigned long int
htonl (unsigned long int x)
@ -555,24 +541,20 @@ cygwin_getprotobynumber (int number)
bool
fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
{
if (!winsock2_active)
soc = set_socket_inheritance (soc);
else if (wincap.has_set_handle_information ())
if (wincap.has_set_handle_information ())
{
/* NT systems apparently set sockets to inheritable by default */
SetHandleInformation ((HANDLE) soc, HANDLE_FLAG_INHERIT, 0);
debug_printf ("reset socket inheritance since winsock2_active %d",
winsock2_active);
debug_printf ("reset socket inheritance");
}
else
debug_printf ("not setting socket inheritance since winsock2_active %d",
winsock2_active);
debug_printf ("not setting socket inheritance");
fd = build_fh_dev (*dev);
if (!fd.isopen ())
return false;
fd->set_io_handle ((HANDLE) soc);
fd->set_flags (O_RDWR | O_BINARY);
fd->uninterruptible_io (winsock2_active);
fd->uninterruptible_io (true);
cygheap->fdtab.inc_need_fixup_before ();
debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name, soc);
return true;
@ -663,6 +645,27 @@ cygwin_recvfrom (int fd, void *buf, int len, int flags,
return res;
}
static int
convert_ws1_ip_optname (int optname)
{
static int ws2_optname[] =
{
0,
IP_OPTIONS,
IP_MULTICAST_IF,
IP_MULTICAST_TTL,
IP_MULTICAST_LOOP,
IP_ADD_MEMBERSHIP,
IP_DROP_MEMBERSHIP,
IP_TTL,
IP_TOS,
IP_DONTFRAGMENT
};
return (optname < 1 || optname > _WS1_IP_DONTFRAGMENT)
? optname
: ws2_optname[optname];
}
/* exported as setsockopt: standards? */
extern "C" int
cygwin_setsockopt (int fd, int level, int optname, const void *optval,
@ -670,48 +673,30 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
{
int res;
fhandler_socket *fh = get (fd);
const char *name = "error";
/* For the following debug_printf */
switch (optname)
{
case SO_DEBUG:
name = "SO_DEBUG";
break;
case SO_ACCEPTCONN:
name = "SO_ACCEPTCONN";
break;
case SO_REUSEADDR:
name = "SO_REUSEADDR";
break;
case SO_KEEPALIVE:
name = "SO_KEEPALIVE";
break;
case SO_DONTROUTE:
name = "SO_DONTROUTE";
break;
case SO_BROADCAST:
name = "SO_BROADCAST";
break;
case SO_USELOOPBACK:
name = "SO_USELOOPBACK";
break;
case SO_LINGER:
name = "SO_LINGER";
break;
case SO_OOBINLINE:
name = "SO_OOBINLINE";
break;
case SO_ERROR:
name = "SO_ERROR";
break;
}
myfault efault;
if (efault.faulted (EFAULT) || !fh)
res = -1;
else
{
/* Old applications still use the old Winsock1 IPPROTO_IP values. */
if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
optname = convert_ws1_ip_optname (optname);
/* FOR THE RECORDS:
Setting IP_TOS is disabled by default since W2K, the official
reason being that IP_TOS setting would interfere with Windows
QOS settings. As result, setsockopt returns with WinSock error
10022, WSAEINVAL, when running under W2K or later, instead of
handling this gracefully.
The workaround is described in KB article 248611. Add a new
registry DWORD value HKLM/System/CurrentControlSet/Services/...
... Tcpip/Parameters/DisableUserTOSSetting, set to 0, and reboot.
FIXME: Maybe we should simply fake that IP_TOS could be set
successfully, if DisableUserTOSSetting is not set to 0 on W2K
and above? */
res = setsockopt (fh->get_socket (), level, optname,
(const char *) optval, optlen);
@ -722,8 +707,8 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
set_winsock_errno ();
}
syscall_printf ("%d = setsockopt (%d, %d, %x (%s), %p, %d)",
res, fd, level, optname, name, optval, optlen);
syscall_printf ("%d = setsockopt (%d, %d, %x, %p, %d)",
res, fd, level, optname, optval, optlen);
return res;
}
@ -733,44 +718,6 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
{
int res;
fhandler_socket *fh = get (fd);
const char *name = "error";
/* For the following debug_printf */
switch (optname)
{
case SO_DEBUG:
name = "SO_DEBUG";
break;
case SO_ACCEPTCONN:
name = "SO_ACCEPTCONN";
break;
case SO_REUSEADDR:
name = "SO_REUSEADDR";
break;
case SO_KEEPALIVE:
name = "SO_KEEPALIVE";
break;
case SO_DONTROUTE:
name = "SO_DONTROUTE";
break;
case SO_BROADCAST:
name = "SO_BROADCAST";
break;
case SO_USELOOPBACK:
name = "SO_USELOOPBACK";
break;
case SO_LINGER:
name = "SO_LINGER";
break;
case SO_OOBINLINE:
name = "SO_OOBINLINE";
break;
case SO_ERROR:
name = "SO_ERROR";
break;
case SO_PEERCRED:
name = "SO_PEERCRED";
}
myfault efault;
if (efault.faulted (EFAULT) || !fh)
@ -782,6 +729,9 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
}
else
{
/* Old applications still use the old Winsock1 IPPROTO_IP values. */
if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
optname = convert_ws1_ip_optname (optname);
res = getsockopt (fh->get_socket (), level, optname, (char *) optval,
(int *) optlen);
@ -797,8 +747,8 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
set_winsock_errno ();
}
syscall_printf ("%d = getsockopt (%d, %d, %x (%s), %p, %p)",
res, fd, level, optname, name, optval, optlen);
syscall_printf ("%d = getsockopt (%d, %d, 0x%x, %p, %p)",
res, fd, level, optname, optval, optlen);
return res;
}

View File

@ -1410,7 +1410,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
select_printf ("getsockname error");
goto err;
}
if (winsock2_active && wincap.has_set_handle_information ())
if (wincap.has_set_handle_information ())
SetHandleInformation ((HANDLE) si->exitsock, HANDLE_FLAG_INHERIT, 0);
/* else
too bad? */

View File

@ -225,13 +225,6 @@ void events_terminate ();
void __stdcall close_all_files (bool = false);
/* Globals that handle initialization of winsock in a child process. */
extern HANDLE wsock32_handle;
extern HANDLE ws2_32_handle;
/* Globals that handle initialization of netapi in a child process. */
extern HANDLE netapi32_handle;
/* debug_on_trap support. see exceptions.cc:try_to_debug() */
extern "C" void error_start_init (const char*);
extern "C" int try_to_debug (bool waitloop = 1);
@ -352,7 +345,4 @@ extern bool cygwin_testing;
extern char almost_null[];
#define winsock2_active (wsadata.wVersion >= 512)
extern struct WSAData wsadata;
#endif /* defined __cplusplus */