diff options
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/ChangeLog | 55 | ||||
-rw-r--r-- | winsup/cygwin/autoload.cc | 111 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_socket.cc | 402 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/socket.h | 120 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/version.h | 13 | ||||
-rw-r--r-- | winsup/cygwin/net.cc | 154 | ||||
-rw-r--r-- | winsup/cygwin/select.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/winsup.h | 10 |
8 files changed, 401 insertions, 466 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ba92f6c8f..ad775bc3b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -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> diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 5f0b5ddf3..8ac707edb 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -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) diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index b5e5248ec..420eb627a 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -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,103 +1056,55 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot) int res = SOCKET_ERROR; - if (!winsock2_active) - { - 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); + WSABUF wsabuf[iovcnt]; + unsigned long len = 0L; - if (!buf) - { - set_errno (ENOMEM); - res = SOCKET_ERROR; - } - else - { - res = recvfrom (buf, tot, flags, from, fromlen); + 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); - const struct iovec *iovptr = iov; - int nbytes = res; + DWORD ret = 0; - 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; - } - } - } - } + 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; + 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; + 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) - { - 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); + WSABUF wsabuf[iovcnt]; - if (!buf) - { - set_errno (ENOMEM); - res = SOCKET_ERROR; - } - else - { - char *bufptr = buf; - const struct iovec *iovptr = iov; - int nbytes = tot; + 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); - 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; - } + DWORD ret = 0; - res = sendto (buf, tot, flags, - (struct sockaddr *) msg->msg_name, - msg->msg_namelen); - } - } - } + 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); } diff --git a/winsup/cygwin/include/cygwin/socket.h b/winsup/cygwin/include/cygwin/socket.h index f6dc11353..7597e813e 100644 --- a/winsup/cygwin/include/cygwin/socket.h +++ b/winsup/cygwin/include/cygwin/socket.h @@ -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,28 +26,78 @@ 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 */ + 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 */ - 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 */ + 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 */ }; -#ifndef socklen_t -#define socklen_t int +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. */ @@ -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 */ - -#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 +/* 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 + +/* 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 diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 7984df7f2..32dfa413c 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -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 diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 3de7304f5..91ee74a20 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -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; } diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 3e300a0d5..4c93dd32d 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -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? */ diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index d31dd9abd..0b2850119 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -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 */ |