/* fhandler_socket_inet.cc. See fhandler.h for a description of the fhandler classes. This file is part of Cygwin. This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #define __INSIDE_CYGWIN_NET__ #define USE_SYS_TYPES_FD_SET #include "winsup.h" /* 2014-04-24: Current Mingw headers define sockaddr_in6 using u_long (8 byte) because a redefinition for LP64 systems is missing. This leads to a wrong definition and size of sockaddr_in6 when building with winsock headers. This definition is also required to use the right u_long type in subsequent function calls. */ #undef u_long #define u_long __ms_u_long #include #include #include #include #include #include #include #include #include #include #include #include "cygerrno.h" #include "path.h" #include "fhandler.h" #include "dtable.h" #include "cygheap.h" #include "shared_info.h" #include "wininfo.h" #include "tls_pbuf.h" #define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT) #define EVENT_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE) #define LOCK_EVENTS \ if (wsock_mtx && \ WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED) \ { #define UNLOCK_EVENTS \ ReleaseMutex (wsock_mtx); \ } /* Maximum number of concurrently opened sockets from all Cygwin processes per session. Note that shared sockets (through dup/fork/exec) are counted as one socket. */ #define NUM_SOCKS 2048U #define LOCK_EVENTS \ if (wsock_mtx && \ WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED) \ { #define UNLOCK_EVENTS \ ReleaseMutex (wsock_mtx); \ } static wsa_event wsa_events[NUM_SOCKS] __attribute__((section (".cygwin_dll_common"), shared)); static LONG socket_serial_number __attribute__((section (".cygwin_dll_common"), shared)); static HANDLE wsa_slot_mtx; static PWCHAR sock_shared_name (PWCHAR buf, LONG num) { __small_swprintf (buf, L"socket.%d", num); return buf; } static wsa_event * search_wsa_event_slot (LONG new_serial_number) { WCHAR name[32], searchname[32]; UNICODE_STRING uname; OBJECT_ATTRIBUTES attr; NTSTATUS status; if (!wsa_slot_mtx) { RtlInitUnicodeString (&uname, sock_shared_name (name, 0)); InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF, get_session_parent_dir (), everyone_sd (CYG_MUTANT_ACCESS)); status = NtCreateMutant (&wsa_slot_mtx, CYG_MUTANT_ACCESS, &attr, FALSE); if (!NT_SUCCESS (status)) api_fatal ("Couldn't create/open shared socket mutex %S, %y", &uname, status); } switch (WaitForSingleObject (wsa_slot_mtx, INFINITE)) { case WAIT_OBJECT_0: case WAIT_ABANDONED: break; default: api_fatal ("WFSO failed for shared socket mutex, %E"); break; } unsigned int slot = new_serial_number % NUM_SOCKS; while (wsa_events[slot].serial_number) { HANDLE searchmtx; RtlInitUnicodeString (&uname, sock_shared_name (searchname, wsa_events[slot].serial_number)); InitializeObjectAttributes (&attr, &uname, 0, get_session_parent_dir (), NULL); status = NtOpenMutant (&searchmtx, READ_CONTROL, &attr); if (!NT_SUCCESS (status)) break; /* Mutex still exists, attached socket is active, try next slot. */ NtClose (searchmtx); slot = (slot + 1) % NUM_SOCKS; if (slot == (new_serial_number % NUM_SOCKS)) { /* Did the whole array once. Too bad. */ debug_printf ("No free socket slot"); ReleaseMutex (wsa_slot_mtx); return NULL; } } memset (&wsa_events[slot], 0, sizeof (wsa_event)); wsa_events[slot].serial_number = new_serial_number; ReleaseMutex (wsa_slot_mtx); return wsa_events + slot; } /* cygwin internal: map sockaddr into internet domain address */ static int get_inet_addr_inet (const struct sockaddr *in, int inlen, struct sockaddr_storage *out, int *outlen) { switch (in->sa_family) { case AF_INET: memcpy (out, in, inlen); *outlen = inlen; /* If the peer address given in connect or sendto is the ANY address, Winsock fails with WSAEADDRNOTAVAIL, while Linux converts that into a connection/send attempt to LOOPBACK. We're doing the same here. */ if (((struct sockaddr_in *) out)->sin_addr.s_addr == htonl (INADDR_ANY)) ((struct sockaddr_in *) out)->sin_addr.s_addr = htonl (INADDR_LOOPBACK); return 0; case AF_INET6: memcpy (out, in, inlen); *outlen = inlen; /* See comment in AF_INET case. */ if (IN6_IS_ADDR_UNSPECIFIED (&((struct sockaddr_in6 *) out)->sin6_addr)) ((struct sockaddr_in6 *) out)->sin6_addr = in6addr_loopback; return 0; default: set_errno (EAFNOSUPPORT); return SOCKET_ERROR; } } /* There's no DLL which exports the symbol WSARecvMsg. One has to call WSAIoctl as below to fetch the function pointer. Why on earth did the MS developers decide not to export a normal symbol for these extension functions? */ inline int get_ext_funcptr (SOCKET sock, void *funcptr) { DWORD bret; const GUID guid = WSAID_WSARECVMSG; return WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, (void *) &guid, sizeof (GUID), funcptr, sizeof (void *), &bret, NULL, NULL); } fhandler_socket_wsock::fhandler_socket_wsock () : fhandler_socket (), wsock_events (NULL), wsock_mtx (NULL), wsock_evt (NULL), status (), prot_info_ptr (NULL) { need_fork_fixup (true); } fhandler_socket_wsock::~fhandler_socket_wsock () { if (prot_info_ptr) cfree (prot_info_ptr); } bool fhandler_socket_wsock::init_events () { LONG new_serial_number; WCHAR name[32]; UNICODE_STRING uname; OBJECT_ATTRIBUTES attr; NTSTATUS status; do { new_serial_number = InterlockedIncrement (&socket_serial_number); if (!new_serial_number) /* 0 is reserved for global mutex */ InterlockedIncrement (&socket_serial_number); set_ino (new_serial_number); RtlInitUnicodeString (&uname, sock_shared_name (name, new_serial_number)); InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF, get_session_parent_dir (), everyone_sd (CYG_MUTANT_ACCESS)); status = NtCreateMutant (&wsock_mtx, CYG_MUTANT_ACCESS, &attr, FALSE); if (!NT_SUCCESS (status)) { debug_printf ("NtCreateMutant(%S), %y", &uname, status); set_errno (ENOBUFS); return false; } if (status == STATUS_OBJECT_NAME_EXISTS) NtClose (wsock_mtx); } while (status == STATUS_OBJECT_NAME_EXISTS); if ((wsock_evt = CreateEvent (&sec_all, TRUE, FALSE, NULL)) == WSA_INVALID_EVENT) { debug_printf ("CreateEvent, %E"); set_errno (ENOBUFS); NtClose (wsock_mtx); return false; } if (WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK) == SOCKET_ERROR) { debug_printf ("WSAEventSelect, %E"); set_winsock_errno (); NtClose (wsock_evt); NtClose (wsock_mtx); return false; } if (!(wsock_events = search_wsa_event_slot (new_serial_number))) { set_errno (ENOBUFS); NtClose (wsock_evt); NtClose (wsock_mtx); return false; } if (get_socket_type () == SOCK_DGRAM) wsock_events->events = FD_WRITE; return true; } int fhandler_socket_wsock::evaluate_events (const long event_mask, long &events, const bool erase) { int ret = 0; long events_now = 0; WSANETWORKEVENTS evts = { 0 }; if (!(WSAEnumNetworkEvents (get_socket (), wsock_evt, &evts))) { if (evts.lNetworkEvents) { LOCK_EVENTS; wsock_events->events |= evts.lNetworkEvents; events_now = (wsock_events->events & event_mask); if (evts.lNetworkEvents & FD_CONNECT) { wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT]; /* Setting the connect_state and calling the AF_LOCAL handshake here allows to handle this stuff from a single point. This is independent of FD_CONNECT being requested. Consider a server calling connect(2) and then immediately poll(2) with only polling for POLLIN (example: postfix), or select(2) just asking for descriptors ready to read. Something weird occurs in Winsock: If you fork off and call recv/send on the duplicated, already connected socket, another FD_CONNECT event is generated in the child process. This would trigger a call to af_local_connect which obviously fail. Avoid this by calling set_connect_state only if connect_state is connect_pending. */ if (connect_state () == connect_pending) { if (wsock_events->connect_errorcode) connect_state (connect_failed); else if (af_local_connect ()) { wsock_events->connect_errorcode = WSAGetLastError (); connect_state (connect_failed); } else connect_state (connected); } } UNLOCK_EVENTS; if ((evts.lNetworkEvents & FD_OOB) && wsock_events->owner) kill (wsock_events->owner, SIGURG); } } LOCK_EVENTS; if ((events = events_now) != 0 || (events = (wsock_events->events & event_mask)) != 0) { if (events & FD_CONNECT) { int wsa_err = wsock_events->connect_errorcode; if (wsa_err) { /* CV 2014-04-23: This is really weird. If you call connect asynchronously on a socket and then select, an error like "Connection refused" is set in the event and in the SO_ERROR socket option. If you call connect, then dup, then select, the error is set in the event, but not in the SO_ERROR socket option, despite the dup'ed socket handle referring to the same socket. We're trying to workaround this problem here by taking the connect errorcode from the event and write it back into the SO_ERROR socket option. CV 2014-06-16: Call WSASetLastError *after* setsockopt since, apparently, setsockopt sets the last WSA error code to 0 on success. */ ::setsockopt (get_socket (), SOL_SOCKET, SO_ERROR, (const char *) &wsa_err, sizeof wsa_err); WSASetLastError (wsa_err); ret = SOCKET_ERROR; } /* Since FD_CONNECT is only given once, we have to keep FD_CONNECT for connection failed sockets to have consistent behaviour in programs calling poll/select multiple times. Example test to non-listening port: curl -v 127.0.0.1:47 */ if (connect_state () != connect_failed) wsock_events->events &= ~FD_CONNECT; wsock_events->events |= FD_WRITE; wsock_events->connect_errorcode = 0; } if (events & FD_CLOSE) { if (evts.iErrorCode[FD_CLOSE_BIT]) { WSASetLastError (evts.iErrorCode[FD_CLOSE_BIT]); ret = SOCKET_ERROR; } /* This test makes accept/connect behave as on Linux when accept/ connect is called on a socket for which shutdown has been called. The second half of this code is in the shutdown method. Note that we only do this when called from accept/connect, not from select. In this case erase == false, just as with read (MSG_PEEK). */ if (erase) { if ((event_mask & FD_ACCEPT) && saw_shutdown_read ()) { WSASetLastError (WSAEINVAL); ret = SOCKET_ERROR; } if (event_mask & FD_CONNECT) { WSASetLastError (WSAECONNRESET); ret = SOCKET_ERROR; } } } if (erase) wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE)); } UNLOCK_EVENTS; return ret; } int fhandler_socket_wsock::wait_for_events (const long event_mask, const DWORD flags) { if (async_io ()) return 0; int ret; long events = 0; DWORD wfmo_timeout = 50; DWORD timeout; WSAEVENT ev[3] = { wsock_evt, NULL, NULL }; wait_signal_arrived here (ev[1]); DWORD ev_cnt = 2; if ((ev[2] = pthread::get_cancel_event ()) != NULL) ++ev_cnt; if (is_nonblocking () || (flags & MSG_DONTWAIT)) timeout = 0; else if (event_mask & FD_READ) timeout = rcvtimeo (); else if (event_mask & FD_WRITE) timeout = sndtimeo (); else timeout = INFINITE; while (!(ret = evaluate_events (event_mask, events, !(flags & MSG_PEEK))) && !events) { if (timeout == 0) { WSASetLastError (WSAEWOULDBLOCK); return SOCKET_ERROR; } if (timeout < wfmo_timeout) wfmo_timeout = timeout; switch (WSAWaitForMultipleEvents (ev_cnt, ev, FALSE, wfmo_timeout, FALSE)) { case WSA_WAIT_TIMEOUT: case WSA_WAIT_EVENT_0: if (timeout != INFINITE) timeout -= wfmo_timeout; break; case WSA_WAIT_EVENT_0 + 1: if (_my_tls.call_signal_handler ()) break; WSASetLastError (WSAEINTR); return SOCKET_ERROR; case WSA_WAIT_EVENT_0 + 2: pthread::static_cancel_self (); break; default: /* wsock_evt can be NULL. We're generating the same errno values as for sockets on which shutdown has been called. */ if (WSAGetLastError () != WSA_INVALID_HANDLE) WSASetLastError (WSAEFAULT); else WSASetLastError ((event_mask & FD_CONNECT) ? WSAECONNRESET : WSAEINVAL); return SOCKET_ERROR; } } return ret; } void fhandler_socket_wsock::release_events () { if (WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED) { HANDLE evt = wsock_evt; HANDLE mtx = wsock_mtx; wsock_evt = wsock_mtx = NULL; ReleaseMutex (mtx); NtClose (evt); NtClose (mtx); } } void fhandler_socket_wsock::set_close_on_exec (bool val) { set_no_inheritance (wsock_mtx, val); set_no_inheritance (wsock_evt, val); if (need_fixup_before ()) { close_on_exec (val); debug_printf ("set close_on_exec for %s to %d", get_name (), val); } else fhandler_base::set_close_on_exec (val); } /* Called if a freshly created socket is not inheritable. In that case we have to use fixup_before_fork_exec. See comment in set_socket_handle for a description of the problem. */ void fhandler_socket_wsock::init_fixup_before () { prot_info_ptr = (LPWSAPROTOCOL_INFOW) cmalloc_abort (HEAP_BUF, sizeof (WSAPROTOCOL_INFOW)); cygheap->fdtab.inc_need_fixup_before (); } int fhandler_socket_wsock::fixup_before_fork_exec (DWORD win_pid) { SOCKET ret = WSADuplicateSocketW (get_socket (), win_pid, prot_info_ptr); if (ret) set_winsock_errno (); else debug_printf ("WSADuplicateSocket succeeded (%x)", prot_info_ptr->dwProviderReserved); return (int) ret; } void fhandler_socket_wsock::fixup_after_fork (HANDLE parent) { fork_fixup (parent, wsock_mtx, "wsock_mtx"); fork_fixup (parent, wsock_evt, "wsock_evt"); if (!need_fixup_before ()) { fhandler_base::fixup_after_fork (parent); return; } SOCKET new_sock = WSASocketW (FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, prot_info_ptr, 0, WSA_FLAG_OVERLAPPED); if (new_sock == INVALID_SOCKET) { set_winsock_errno (); set_handle ((HANDLE) INVALID_SOCKET); } else { /* Even though the original socket was not inheritable, the duplicated socket is potentially inheritable again. */ SetHandleInformation ((HANDLE) new_sock, HANDLE_FLAG_INHERIT, 0); set_handle ((HANDLE) new_sock); debug_printf ("WSASocket succeeded (%p)", new_sock); } } void fhandler_socket_wsock::fixup_after_exec () { if (need_fixup_before () && !close_on_exec ()) fixup_after_fork (NULL); /* No parent handle required. */ } int fhandler_socket_wsock::dup (fhandler_base *child, int flags) { debug_printf ("here"); fhandler_socket_wsock *fhs = (fhandler_socket_wsock *) child; if (!DuplicateHandle (GetCurrentProcess (), wsock_mtx, GetCurrentProcess (), &fhs->wsock_mtx, 0, TRUE, DUPLICATE_SAME_ACCESS)) { __seterrno (); return -1; } if (!DuplicateHandle (GetCurrentProcess (), wsock_evt, GetCurrentProcess (), &fhs->wsock_evt, 0, TRUE, DUPLICATE_SAME_ACCESS)) { __seterrno (); NtClose (fhs->wsock_mtx); return -1; } if (!need_fixup_before ()) { int ret = fhandler_base::dup (child, flags); if (ret) { NtClose (fhs->wsock_evt); NtClose (fhs->wsock_mtx); } return ret; } cygheap->user.deimpersonate (); fhs->init_fixup_before (); fhs->set_handle (get_handle ()); int ret = fhs->fixup_before_fork_exec (GetCurrentProcessId ()); cygheap->user.reimpersonate (); if (!ret) { fhs->fixup_after_fork (GetCurrentProcess ()); if (fhs->get_handle() != (HANDLE) INVALID_SOCKET) return 0; } cygheap->fdtab.dec_need_fixup_before (); NtClose (fhs->wsock_evt); NtClose (fhs->wsock_mtx); return -1; } int fhandler_socket_wsock::set_socket_handle (SOCKET sock, int af, int type, int flags) { DWORD hdl_flags; bool lsp_fixup = false; int file_flags = O_RDWR | O_BINARY; /* Usually sockets are inheritable IFS objects. Unfortunately some virus scanners or other network-oriented software replace normal sockets with their own kind, which is running through a filter driver called "layered service provider" (LSP) which, fortunately, are deprecated. LSP sockets are not kernel objects. They are typically not marked as inheritable, nor are they IFS handles. They are in fact not inheritable to child processes, and it does not help to mark them inheritable via SetHandleInformation. Subsequent socket calls in the child process fail with error 10038, WSAENOTSOCK. There's a neat way to workaround these annoying LSP sockets. WSAIoctl allows to fetch the underlying base socket, which is a normal, inheritable IFS handle. So we fetch the base socket, duplicate it, and close the original socket. Now we have a standard IFS socket which (hopefully) works as expected. If that doesn't work for some reason, mark the sockets for duplication via WSADuplicateSocket/WSASocket. This requires to start the child process in SUSPENDED state so we only do this if really necessary. */ if (!GetHandleInformation ((HANDLE) sock, &hdl_flags) || !(hdl_flags & HANDLE_FLAG_INHERIT)) { int ret; SOCKET base_sock; DWORD bret; lsp_fixup = true; debug_printf ("LSP handle: %p", sock); ret = WSAIoctl (sock, SIO_BASE_HANDLE, NULL, 0, (void *) &base_sock, sizeof (base_sock), &bret, NULL, NULL); if (ret) debug_printf ("WSAIoctl: %u", WSAGetLastError ()); else if (base_sock != sock) { if (GetHandleInformation ((HANDLE) base_sock, &hdl_flags) && (flags & HANDLE_FLAG_INHERIT)) { if (!DuplicateHandle (GetCurrentProcess (), (HANDLE) base_sock, GetCurrentProcess (), (PHANDLE) &base_sock, 0, TRUE, DUPLICATE_SAME_ACCESS)) debug_printf ("DuplicateHandle failed, %E"); else { ::closesocket (sock); sock = base_sock; lsp_fixup = false; } } } } set_handle ((HANDLE) sock); set_addr_family (af); set_socket_type (type); if (!init_events ()) return -1; if (flags & SOCK_NONBLOCK) file_flags |= O_NONBLOCK; if (flags & SOCK_CLOEXEC) { set_close_on_exec (true); file_flags |= O_CLOEXEC; } set_flags (file_flags); if (lsp_fixup) init_fixup_before (); set_unique_id (); if (get_socket_type () == SOCK_DGRAM) { /* Workaround the problem that a missing listener on a UDP socket in a call to sendto will result in select/WSAEnumNetworkEvents reporting that the socket has pending data and a subsequent call to recvfrom will return -1 with error set to WSAECONNRESET. This problem is a regression introduced in Windows 2000. Instead of fixing the problem, a new socket IOCTL code has been added, see http://support.microsoft.com/kb/263823 */ BOOL cr = FALSE; DWORD blen; if (WSAIoctl (sock, SIO_UDP_CONNRESET, &cr, sizeof cr, NULL, 0, &blen, NULL, NULL) == SOCKET_ERROR) debug_printf ("Reset SIO_UDP_CONNRESET: WinSock error %u", WSAGetLastError ()); } rmem () = 212992; wmem () = 212992; return 0; } fhandler_socket_inet::fhandler_socket_inet () : fhandler_socket_wsock (), oobinline (false), tcp_quickack (false), tcp_fastopen (false), tcp_keepidle (7200), /* WinSock default */ tcp_keepcnt (10), /* WinSock default */ tcp_keepintvl (1) /* WinSock default */ { } fhandler_socket_inet::~fhandler_socket_inet () { } int fhandler_socket_inet::socket (int af, int type, int protocol, int flags) { SOCKET sock; int ret; /* This test should be covered by ::socket, but make sure we don't accidentally try anything else. */ if (type != SOCK_STREAM && type != SOCK_DGRAM && type != SOCK_RAW) { set_errno (EINVAL); return -1; } sock = ::socket (af, type, protocol); if (sock == INVALID_SOCKET) { set_winsock_errno (); return -1; } ret = set_socket_handle (sock, af, type, flags); if (ret < 0) ::closesocket (sock); return ret; } int fhandler_socket_inet::socketpair (int af, int type, int protocol, int flags, fhandler_socket *fh_out) { set_errno (EAFNOSUPPORT); return -1; } int fhandler_socket_inet::bind (const struct sockaddr *name, int namelen) { int res = -1; if (!saw_reuseaddr ()) { /* If the application didn't explicitely request SO_REUSEADDR, enforce POSIX standard socket binding behaviour by setting the SO_EXCLUSIVEADDRUSE socket option. See cygwin_setsockopt() for a more detailed description. */ int on = 1; int ret = ::setsockopt (get_socket (), SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char *) &on, sizeof on); debug_printf ("%d = setsockopt(SO_EXCLUSIVEADDRUSE), %E", ret); } if (::bind (get_socket (), name, namelen)) set_winsock_errno (); else res = 0; return res; } int fhandler_socket_inet::connect (const struct sockaddr *name, int namelen) { struct sockaddr_storage sst; bool reset = (name->sa_family == AF_UNSPEC && get_socket_type () == SOCK_DGRAM); if (reset) { if (connect_state () == unconnected) return 0; /* To reset a connected DGRAM socket, call Winsock's connect function with the address member of the sockaddr structure filled with zeroes. */ memset (&sst, 0, sizeof sst); sst.ss_family = get_addr_family (); } else if (get_inet_addr_inet (name, namelen, &sst, &namelen) == SOCKET_ERROR) return SOCKET_ERROR; /* Initialize connect state to "connect_pending". In the SOCK_STREAM case, the state is ultimately set to "connected" or "connect_failed" in wait_for_events when the FD_CONNECT event occurs. Note that the underlying OS sockets are always non-blocking in this case and a successfully initiated non-blocking Winsock connect always returns WSAEWOULDBLOCK. Thus it's safe to rely on event handling. For DGRAM sockets, however, connect can return immediately. Check for either unconnected or connect_failed since in both cases it's allowed to retry connecting the socket. It's also ok (albeit ugly) to call connect to check if a previous non-blocking connect finished. Set connect_state before calling connect, otherwise a race condition with an already running select or poll might occur. */ if (connect_state () == unconnected || connect_state () == connect_failed) connect_state (connect_pending); int res = ::connect (get_socket (), (struct sockaddr *) &sst, namelen); if (!res) { if (reset) connect_state (unconnected); else connect_state (connected); } else if (!is_nonblocking () && res == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK) res = wait_for_events (FD_CONNECT | FD_CLOSE, 0); if (res) { DWORD err = WSAGetLastError (); /* Some applications use the ugly technique to check if a non-blocking connect succeeded by calling connect again, until it returns EISCONN. This circumvents the event handling and connect_state is never set. Thus we check for this situation here. */ if (err == WSAEISCONN) connect_state (connected); /* Winsock returns WSAEWOULDBLOCK if the non-blocking socket cannot be conected immediately. Convert to POSIX/Linux compliant EINPROGRESS. */ else if (is_nonblocking () && err == WSAEWOULDBLOCK) WSASetLastError (WSAEINPROGRESS); /* Winsock returns WSAEINVAL if the socket is already a listener. Convert to POSIX/Linux compliant EISCONN. */ else if (err == WSAEINVAL && connect_state () == listener) WSASetLastError (WSAEISCONN); /* Any other error except WSAEALREADY means the connect failed. */ else if (connect_state () == connect_pending && err != WSAEALREADY) connect_state (connect_failed); set_winsock_errno (); } return res; } int fhandler_socket_inet::listen (int backlog) { int res = ::listen (get_socket (), backlog); if (res && WSAGetLastError () == WSAEINVAL) { /* It's perfectly valid to call listen on an unbound INET socket. In this case the socket is automatically bound to an unused port number, listening on all interfaces. On WinSock, listen fails with WSAEINVAL when it's called on an unbound socket. So we have to bind manually here to have POSIX semantics. */ if (get_addr_family () == AF_INET) { struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = 0; sin.sin_addr.s_addr = INADDR_ANY; if (!::bind (get_socket (), (struct sockaddr *) &sin, sizeof sin)) res = ::listen (get_socket (), backlog); } else if (get_addr_family () == AF_INET6) { struct sockaddr_in6 sin6; memset (&sin6, 0, sizeof sin6); sin6.sin6_family = AF_INET6; if (!::bind (get_socket (), (struct sockaddr *) &sin6, sizeof sin6)) res = ::listen (get_socket (), backlog); } } if (!res) connect_state (listener); /* gets set to connected on accepted socket. */ else set_winsock_errno (); return res; } int fhandler_socket_inet::accept4 (struct sockaddr *peer, int *len, int flags) { int ret = -1; /* Allows NULL peer and len parameters. */ struct sockaddr_storage lpeer; int llen = sizeof (struct sockaddr_storage); /* Windows event handling does not check for the validity of the desired flags so we have to do it here. */ if (connect_state () != listener) { WSASetLastError (WSAEINVAL); set_winsock_errno (); return -1; } SOCKET res = INVALID_SOCKET; while (!(res = wait_for_events (FD_ACCEPT | FD_CLOSE, 0)) && (res = ::accept (get_socket (), (struct sockaddr *) &lpeer, &llen)) == INVALID_SOCKET && WSAGetLastError () == WSAEWOULDBLOCK) ; if (res == INVALID_SOCKET) set_winsock_errno (); else { cygheap_fdnew fd; if (fd >= 0) { fhandler_socket_inet *sock = (fhandler_socket_inet *) build_fh_dev (dev ()); if (sock && sock->set_socket_handle (res, get_addr_family (), get_socket_type (), get_socket_flags ()) == 0) { sock->async_io (false); /* set_socket_handle disables async. */ /* No locking necessary at this point. */ sock->wsock_events->events = wsock_events->events | FD_WRITE; sock->wsock_events->owner = wsock_events->owner; sock->connect_state (connected); fd = sock; if (fd <= 2) set_std_handle (fd); ret = fd; if (peer) { memcpy (peer, &lpeer, MIN (*len, llen)); *len = llen; } } else delete sock; } if (ret == -1) ::closesocket (res); } return ret; } int fhandler_socket_inet::getsockname (struct sockaddr *name, int *namelen) { int res = -1; /* WinSock just returns WSAEFAULT if the buffer is too small. Use a big enough local buffer and truncate later as necessary, per POSIX. */ struct sockaddr_storage sock; int len = sizeof sock; res = ::getsockname (get_socket (), (struct sockaddr *) &sock, &len); if (!res) { memcpy (name, &sock, MIN (*namelen, len)); *namelen = len; } else { if (WSAGetLastError () == WSAEINVAL) { /* WinSock returns WSAEINVAL if the socket is locally unbound. Per SUSv3 this is not an error condition. We're faking a valid return value here by creating the same content in the sockaddr structure as on Linux. */ memset (&sock, 0, sizeof sock); sock.ss_family = get_addr_family (); switch (get_addr_family ()) { case AF_INET: res = 0; len = (int) sizeof (struct sockaddr_in); break; case AF_INET6: res = 0; len = (int) sizeof (struct sockaddr_in6); break; default: WSASetLastError (WSAEOPNOTSUPP); break; } if (!res) { memcpy (name, &sock, MIN (*namelen, len)); *namelen = len; } } if (res) set_winsock_errno (); } return res; } int fhandler_socket_inet::getpeername (struct sockaddr *name, int *namelen) { /* Always use a local big enough buffer and truncate later as necessary per POSIX. WinSock unfortunately only returns WSAEFAULT if the buffer is too small. */ struct sockaddr_storage sock; int len = sizeof sock; int res = ::getpeername (get_socket (), (struct sockaddr *) &sock, &len); if (res) set_winsock_errno (); else { memcpy (name, &sock, MIN (*namelen, len)); *namelen = len; } return res; } int fhandler_socket_wsock::shutdown (int how) { int res = ::shutdown (get_socket (), how); /* Linux allows to call shutdown for any socket, even if it's not connected. This also disables to call accept on this socket, if shutdown has been called with the SHUT_RD or SHUT_RDWR parameter. In contrast, WinSock only allows to call shutdown on a connected socket. The accept function is in no way affected. So, what we do here is to fake success, and to change the event settings so that an FD_CLOSE event is triggered for the calling Cygwin function. The evaluate_events method handles the call from accept specially to generate a Linux-compatible behaviour. */ if (res && WSAGetLastError () != WSAENOTCONN) set_winsock_errno (); else { res = 0; switch (how) { case SHUT_RD: saw_shutdown_read (true); wsock_events->events |= FD_CLOSE; SetEvent (wsock_evt); break; case SHUT_WR: saw_shutdown_write (true); break; case SHUT_RDWR: saw_shutdown_read (true); saw_shutdown_write (true); wsock_events->events |= FD_CLOSE; SetEvent (wsock_evt); break; } } return res; } int fhandler_socket_wsock::close () { int res = 0; release_events (); while ((res = ::closesocket (get_socket ())) != 0) { if (WSAGetLastError () != WSAEWOULDBLOCK) { set_winsock_errno (); res = -1; break; } if (cygwait (10) == WAIT_SIGNALED) { set_errno (EINTR); res = -1; break; } WSASetLastError (0); } return res; } ssize_t fhandler_socket_inet::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg) { ssize_t res = 0; DWORD ret = 0, wret; int evt_mask = (wsamsg->dwFlags & MSG_OOB) ? FD_OOB : FD_READ; LPWSABUF &wsabuf = wsamsg->lpBuffers; ULONG &wsacnt = wsamsg->dwBufferCount; static NO_COPY LPFN_WSARECVMSG WSARecvMsg; bool read_oob = false; /* CV 2014-10-26: Do not check for the connect_state at this point. In certain scenarios there's no way to check the connect state reliably. Example (hexchat): Parent process creates socket, forks, child process calls connect, parent process calls read. Even if the event handling allows to check for FD_CONNECT in the parent, there is always yet another scenario we can easily break. */ DWORD wait_flags = wsamsg->dwFlags; bool waitall = !!(wait_flags & MSG_WAITALL); wsamsg->dwFlags &= (MSG_OOB | MSG_PEEK | MSG_DONTROUTE); if (use_recvmsg) { if (!WSARecvMsg && get_ext_funcptr (get_socket (), &WSARecvMsg) == SOCKET_ERROR) { if (wsamsg->Control.len > 0) { set_winsock_errno (); return SOCKET_ERROR; } use_recvmsg = false; } else /* Only MSG_PEEK is supported by WSARecvMsg. */ wsamsg->dwFlags &= MSG_PEEK; } if (waitall) { if (get_socket_type () != SOCK_STREAM) { WSASetLastError (WSAEOPNOTSUPP); set_winsock_errno (); return SOCKET_ERROR; } if (is_nonblocking () || (wsamsg->dwFlags & (MSG_OOB | MSG_PEEK))) waitall = false; } /* recv() returns EINVAL if MSG_OOB flag is set in inline mode. */ if (oobinline && (wsamsg->dwFlags & MSG_OOB)) { set_errno (EINVAL); return SOCKET_ERROR; } /* Check whether OOB data is ready or not */ if (get_socket_type () == SOCK_STREAM) if ((wsamsg->dwFlags & MSG_OOB) || oobinline) { u_long atmark = 0; /* SIOCATMARK = _IOR('s',7,u_long) */ int err = ::ioctlsocket (get_socket (), _IOR('s',7,u_long), &atmark); if (err) { set_winsock_errno (); return SOCKET_ERROR; } /* If there is no OOB data, recv() with MSG_OOB returns EINVAL. Note: The return value of SIOCATMARK in non-inline mode of winsock is FALSE if OOB data exists, TRUE otherwise. */ if (atmark && (wsamsg->dwFlags & MSG_OOB)) { /* No OOB data */ set_errno (EINVAL); return SOCKET_ERROR; } /* Inline mode for out-of-band (OOB) data of winsock is completely broken. That is, SIOCATMARK always returns TRUE in inline mode. Due to this problem, application cannot determine OOB data at all. Therefore the behavior of a socket with SO_OOBINLINE set is simulated using a socket with SO_OOBINLINE not set. In this fake inline mode, the order of the OOB and non-OOB data is not preserved. OOB data is read before non-OOB data sent prior to the OOB data. However, this most likely is not a problem in most cases. */ /* If there is OOB data, read OOB data using MSG_OOB in fake inline mode. */ if (!atmark && oobinline) { read_oob = true; evt_mask = FD_OOB; } } /* Note: Don't call WSARecvFrom(MSG_PEEK) without actually having data waiting in the buffers, otherwise the event handling gets messed up for some reason. */ while (!(res = wait_for_events (evt_mask | FD_CLOSE, wait_flags)) || saw_shutdown_read ()) { DWORD dwFlags = wsamsg->dwFlags | (read_oob ? MSG_OOB : 0); if (use_recvmsg) res = WSARecvMsg (get_socket (), wsamsg, &wret, NULL, NULL); /* This is working around a really weird problem in WinSock. Assume you create a socket, fork the process (thus duplicating the socket), connect the socket in the child, then call recv on the original socket handle in the parent process. In this scenario, calls to WinSock's recvfrom and WSARecvFrom in the parent will fail with WSAEINVAL, regardless whether both address parameters, name and namelen, are NULL or point to valid storage. However, calls to recv and WSARecv succeed as expected. Per MSDN, WSAEINVAL in the context of recv means "The socket has not been bound". It is as if the recvfrom functions test if the socket is bound locally, but in the parent process, WinSock doesn't know about that and fails, while the same test is omitted in the recv functions. This also covers another weird case: WinSock returns WSAEFAULT if 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, &dwFlags, NULL, NULL); else res = WSARecvFrom (get_socket (), wsabuf, wsacnt, &wret, &dwFlags, wsamsg->name, &wsamsg->namelen, NULL, NULL); if (!res) { ret += wret; if (!waitall) break; while (wret && wsacnt) { if (wsabuf->len > wret) { wsabuf->len -= wret; wsabuf->buf += wret; wret = 0; } else { wret -= wsabuf->len; ++wsabuf; --wsacnt; } } if (!wsacnt) break; } else if (WSAGetLastError () != WSAEWOULDBLOCK) break; } if (res) { /* According to SUSv3, errno isn't set in that case and no error condition is returned. */ if (WSAGetLastError () == WSAEMSGSIZE) ret += wret; else if (!ret) { /* ESHUTDOWN isn't defined for recv in SUSv3. Simply EOF is returned in this case. */ if (WSAGetLastError () == WSAESHUTDOWN) ret = 0; else { set_winsock_errno (); return SOCKET_ERROR; } } } return ret; } ssize_t fhandler_socket_wsock::recvfrom (void *in_ptr, size_t len, int flags, struct sockaddr *from, int *fromlen) { char *ptr = (char *) in_ptr; /* size_t is 64 bit, but the len member in WSABUF is 32 bit. Split buffer if necessary. */ DWORD bufcnt = len / UINT32_MAX + ((!len || (len % UINT32_MAX)) ? 1 : 0); WSABUF wsabuf[bufcnt]; WSAMSG wsamsg = { from, from && fromlen ? *fromlen : 0, wsabuf, bufcnt, { 0, NULL }, (DWORD) flags }; /* Don't use len as loop condition, it could be 0. */ for (WSABUF *wsaptr = wsabuf; bufcnt--; ++wsaptr) { wsaptr->len = MIN (len, UINT32_MAX); wsaptr->buf = ptr; len -= wsaptr->len; ptr += wsaptr->len; } ssize_t ret = recv_internal (&wsamsg, false); if (fromlen) *fromlen = wsamsg.namelen; return ret; } ssize_t fhandler_socket_wsock::recvmsg (struct msghdr *msg, int flags) { /* Disappointing but true: Even if WSARecvMsg is supported, it's only supported for datagram and raw sockets. */ bool use_recvmsg = true; if (get_socket_type () == SOCK_STREAM || get_addr_family () == AF_LOCAL) { use_recvmsg = false; msg->msg_controllen = 0; } WSABUF wsabuf[msg->msg_iovlen]; WSABUF *wsaptr = wsabuf + msg->msg_iovlen; const struct iovec *iovptr = msg->msg_iov + msg->msg_iovlen; while (--wsaptr >= wsabuf) { wsaptr->len = (--iovptr)->iov_len; wsaptr->buf = (char *) iovptr->iov_base; } WSAMSG wsamsg = { (struct sockaddr *) msg->msg_name, msg->msg_namelen, wsabuf, (DWORD) msg->msg_iovlen, { (DWORD) msg->msg_controllen, (char *) msg->msg_control }, (DWORD) flags }; ssize_t ret = recv_internal (&wsamsg, use_recvmsg); if (ret >= 0) { msg->msg_namelen = wsamsg.namelen; msg->msg_controllen = wsamsg.Control.len; msg->msg_flags = wsamsg.dwFlags; /* if a UDP_GRO packet is present, convert gso_size from Windows DWORD to Linux-compatible uint16_t. We don't have to change the msg_control block layout for that, assuming applications do as they have been told and only use CMSG_FIRSTHDR/CMSG_NXTHDR/CMSG_DATA to access control messages. The cmsghdr alignment saves our ass here! */ if (msg->msg_controllen && get_socket_type () == SOCK_DGRAM && (get_addr_family () == AF_INET || get_addr_family () == AF_INET6)) { struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR (msg); cmsg; cmsg = CMSG_NXTHDR (msg, cmsg)) { if (cmsg->cmsg_level == SOL_UDP && cmsg->cmsg_type == UDP_GRO) { PDWORD gso_size_win = (PDWORD) CMSG_DATA(cmsg); uint16_t *gso_size_cyg = (uint16_t *) CMSG_DATA(cmsg); uint16_t gso_size = (uint16_t) *gso_size_win; *gso_size_cyg = gso_size; break; } } } } return ret; } void fhandler_socket_wsock::read (void *in_ptr, size_t& len) { char *ptr = (char *) in_ptr; /* size_t is 64 bit, but the len member in WSABUF is 32 bit. Split buffer if necessary. */ DWORD bufcnt = len / UINT32_MAX + ((!len || (len % UINT32_MAX)) ? 1 : 0); WSABUF wsabuf[bufcnt]; WSAMSG wsamsg = { NULL, 0, wsabuf, bufcnt, { 0, NULL }, 0 }; /* Don't use len as loop condition, it could be 0. */ for (WSABUF *wsaptr = wsabuf; bufcnt--; ++wsaptr) { wsaptr->len = MIN (len, UINT32_MAX); wsaptr->buf = ptr; len -= wsaptr->len; ptr += wsaptr->len; } len = recv_internal (&wsamsg, false); } ssize_t fhandler_socket_wsock::readv (const struct iovec *const iov, const int iovcnt, ssize_t tot) { WSABUF wsabuf[iovcnt]; WSABUF *wsaptr = wsabuf + iovcnt; const struct iovec *iovptr = iov + iovcnt; while (--wsaptr >= wsabuf) { wsaptr->len = (--iovptr)->iov_len; wsaptr->buf = (char *) iovptr->iov_base; } WSAMSG wsamsg = { NULL, 0, wsabuf, (DWORD) iovcnt, { 0, NULL}, 0 }; return recv_internal (&wsamsg, false); } ssize_t fhandler_socket_wsock::send_internal (struct _WSAMSG *wsamsg, int flags) { ssize_t res = 0; DWORD ret = 0, sum = 0; WSABUF out_buf[wsamsg->dwBufferCount]; bool use_sendmsg = false; DWORD wait_flags = flags & MSG_DONTWAIT; bool nosignal = !!(flags & MSG_NOSIGNAL); /* MSG_EOR not supported by any protocol */ if (flags & MSG_EOR) { set_errno (EOPNOTSUPP); return SOCKET_ERROR; } flags &= (MSG_OOB | MSG_DONTROUTE); if (wsamsg->Control.len > 0) use_sendmsg = true; /* Workaround for MSDN KB 823764: Split a message into chunks <= SO_SNDBUF. in_idx is the index of the current lpBuffers from the input wsamsg buffer. in_off is used to keep track of the next byte to write from a wsamsg buffer which only gets partially written. */ for (DWORD in_idx = 0, in_off = 0; in_idx < wsamsg->dwBufferCount; in_off >= wsamsg->lpBuffers[in_idx].len && (++in_idx, (in_off = 0))) { /* Split a message into the least number of pieces to minimize the number of WsaSendTo calls. Don't split datagram messages (bad idea). out_idx is the index of the next buffer in the out_buf WSABUF, also the number of buffers given to WSASendTo. out_len is the number of bytes in the buffers given to WSASendTo. Don't split datagram messages (very bad idea). */ DWORD out_idx = 0; DWORD out_len = 0; if (get_socket_type () == SOCK_STREAM) { do { out_buf[out_idx].buf = wsamsg->lpBuffers[in_idx].buf + in_off; out_buf[out_idx].len = wsamsg->lpBuffers[in_idx].len - in_off; out_len += out_buf[out_idx].len; out_idx++; } while (out_len < (unsigned) wmem () && (in_off = 0, ++in_idx < wsamsg->dwBufferCount)); /* Tweak len of the last out_buf buffer so the entire number of bytes is (less than or) equal to wmem (). Fix out_len as well since it's used in a subsequent test expression. */ if (out_len > (unsigned) wmem ()) { out_buf[out_idx - 1].len -= out_len - (unsigned) wmem (); out_len = (unsigned) wmem (); } /* Add the bytes written from the current last buffer to in_off, so in_off points to the next byte to be written from that buffer, or beyond which lets the outper loop skip to the next buffer. */ in_off += out_buf[out_idx - 1].len; } do { if (use_sendmsg) res = WSASendMsg (get_socket (), wsamsg, flags, &ret, NULL, NULL); else if (get_socket_type () == SOCK_STREAM) res = WSASendTo (get_socket (), out_buf, out_idx, &ret, flags, wsamsg->name, wsamsg->namelen, NULL, NULL); else res = WSASendTo (get_socket (), wsamsg->lpBuffers, wsamsg->dwBufferCount, &ret, flags, wsamsg->name, wsamsg->namelen, NULL, NULL); if (res && (WSAGetLastError () == WSAEWOULDBLOCK)) { LOCK_EVENTS; wsock_events->events &= ~FD_WRITE; UNLOCK_EVENTS; } } while (res && (WSAGetLastError () == WSAEWOULDBLOCK) && !(res = wait_for_events (FD_WRITE | FD_CLOSE, wait_flags))); if (!res) { sum += ret; /* For streams, return to application if the number of bytes written is less than the number of bytes we intended to write in a single call to WSASendTo. Otherwise we would have to add code to backtrack in the input buffers, which is questionable. There was probably a good reason we couldn't write more. */ if (get_socket_type () != SOCK_STREAM || ret < out_len) break; } else if (is_nonblocking () || WSAGetLastError() != WSAEWOULDBLOCK) break; } if (sum) res = sum; else if (res == SOCKET_ERROR) { set_winsock_errno (); /* Special handling for EPIPE and SIGPIPE. EPIPE is generated if the local end has been shut down on a connection oriented socket. In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set. */ if ((get_errno () == ECONNABORTED || get_errno () == ESHUTDOWN) && get_socket_type () == SOCK_STREAM) { set_errno (EPIPE); if (!nosignal) raise (SIGPIPE); } } return res; } ssize_t fhandler_socket_inet::sendto (const void *in_ptr, size_t len, int flags, const struct sockaddr *to, int tolen) { char *ptr = (char *) in_ptr; struct sockaddr_storage sst; if (to && get_inet_addr_inet (to, tolen, &sst, &tolen) == SOCKET_ERROR) return SOCKET_ERROR; /* size_t is 64 bit, but the len member in WSABUF is 32 bit. Split buffer if necessary. */ DWORD bufcnt = len / UINT32_MAX + ((!len || (len % UINT32_MAX)) ? 1 : 0); WSABUF wsabuf[bufcnt]; WSAMSG wsamsg = { to ? (struct sockaddr *) &sst : NULL, tolen, wsabuf, bufcnt, { 0, NULL }, 0 }; /* Don't use len as loop condition, it could be 0. */ for (WSABUF *wsaptr = wsabuf; bufcnt--; ++wsaptr) { wsaptr->len = MIN (len, UINT32_MAX); wsaptr->buf = ptr; len -= wsaptr->len; ptr += wsaptr->len; } return send_internal (&wsamsg, flags); } ssize_t fhandler_socket_inet::sendmsg (const struct msghdr *in_msg, int flags) { struct sockaddr_storage sst; int len = 0; DWORD old_gso_size = MAXDWORD; ssize_t ret; /* Copy incoming msghdr into a local copy. We only access this from here on. Thus, make sure not to manipulate user space data. */ struct msghdr local_msg = *in_msg; struct msghdr *msg = &local_msg; if (msg->msg_name && get_inet_addr_inet ((struct sockaddr *) msg->msg_name, msg->msg_namelen, &sst, &len) == SOCKET_ERROR) return SOCKET_ERROR; /* Check for our optmem_max value */ if (msg->msg_controllen > NT_MAX_PATH) { set_errno (ENOBUFS); return SOCKET_ERROR; } /* WSASendMsg is supported only for datagram and raw sockets. */ if (get_socket_type () != SOCK_DGRAM && get_socket_type () != SOCK_RAW) msg->msg_controllen = 0; /* If we actually have control data, copy it to local storage. Control messages only handled by us have to be dropped from the msg_control block, and we don't want to change user space data. */ tmp_pathbuf tp; if (msg->msg_controllen) { void *local_cmsg = tp.c_get (); memcpy (local_cmsg, msg->msg_control, msg->msg_controllen); msg->msg_control = local_cmsg; } /* Check for control message we handle inside Cygwin. Right now this only affects UDP sockets, so check here early. */ if (msg->msg_controllen && get_socket_type () == SOCK_DGRAM) { struct cmsghdr *cmsg; bool dropped = false; for (cmsg = CMSG_FIRSTHDR (msg); cmsg; cmsg = dropped ? cmsg : CMSG_NXTHDR (msg, cmsg)) { dropped = false; /* cmsg within bounds? */ if (cmsg->cmsg_len < sizeof (struct cmsghdr) || cmsg->cmsg_len > (size_t) msg->msg_controllen - ((uintptr_t) cmsg - (uintptr_t) msg->msg_control)) { set_errno (EINVAL); return SOCKET_ERROR; } /* UDP_SEGMENT? Override gso_size for this single sendmsg. */ if (cmsg->cmsg_level == SOL_UDP && cmsg->cmsg_type == UDP_SEGMENT) { /* 16 bit unsigned, as on Linux */ DWORD gso_size = *(uint16_t *) CMSG_DATA(cmsg); int size = sizeof old_gso_size; /* Save the old gso_size and set the requested one. */ if (::getsockopt (get_socket (), IPPROTO_UDP, UDP_SEGMENT, (char *) &old_gso_size, &size) == SOCKET_ERROR || ::setsockopt (get_socket (), IPPROTO_UDP, UDP_SEGMENT, (char *) &gso_size, sizeof gso_size) == SOCKET_ERROR) { set_winsock_errno (); return SOCKET_ERROR; } /* Drop message from msgbuf, Windows doesn't know it. */ size_t cmsg_size = CMSG_ALIGN (cmsg->cmsg_len); struct cmsghdr *cmsg_next = CMSG_NXTHDR (msg, cmsg); if (cmsg_next) memmove (cmsg, cmsg_next, (char *) msg->msg_control + msg->msg_controllen - (char *) cmsg_next); msg->msg_controllen -= cmsg_size; dropped = true; /* Avoid infinite loop */ if (msg->msg_controllen <= 0) { cmsg = NULL; msg->msg_controllen = 0; } } } } /* Copy over msg_iov into an equivalent WSABUF array. */ WSABUF wsabuf[msg->msg_iovlen]; WSABUF *wsaptr = wsabuf; const struct iovec *iovptr = msg->msg_iov; for (int i = 0; i < msg->msg_iovlen; ++i) { wsaptr->len = iovptr->iov_len; (wsaptr++)->buf = (char *) (iovptr++)->iov_base; } /* Eventually copy over to a WSAMSG and call send_internal with that. */ WSAMSG wsamsg = { msg->msg_name ? (struct sockaddr *) &sst : NULL, len, wsabuf, (DWORD) msg->msg_iovlen, { (DWORD) msg->msg_controllen, msg->msg_controllen ? (char *) msg->msg_control : NULL }, 0 }; ret = send_internal (&wsamsg, flags); if (old_gso_size != MAXDWORD) ::setsockopt (get_socket (), IPPROTO_UDP, UDP_SEGMENT, (char *) &old_gso_size, sizeof old_gso_size); return ret; } ssize_t fhandler_socket_wsock::write (const void *in_ptr, size_t len) { char *ptr = (char *) in_ptr; /* size_t is 64 bit, but the len member in WSABUF is 32 bit. Split buffer if necessary. */ DWORD bufcnt = len / UINT32_MAX + ((!len || (len % UINT32_MAX)) ? 1 : 0); WSABUF wsabuf[bufcnt]; WSAMSG wsamsg = { NULL, 0, wsabuf, bufcnt, { 0, NULL }, 0 }; /* Don't use len as loop condition, it could be 0. */ for (WSABUF *wsaptr = wsabuf; bufcnt--; ++wsaptr) { wsaptr->len = MIN (len, UINT32_MAX); wsaptr->buf = ptr; len -= wsaptr->len; ptr += wsaptr->len; } return send_internal (&wsamsg, 0); } ssize_t fhandler_socket_wsock::writev (const struct iovec *const iov, const int iovcnt, ssize_t tot) { WSABUF wsabuf[iovcnt]; WSABUF *wsaptr = wsabuf; const struct iovec *iovptr = iov; for (int i = 0; i < iovcnt; ++i) { wsaptr->len = iovptr->iov_len; (wsaptr++)->buf = (char *) (iovptr++)->iov_base; } WSAMSG wsamsg = { NULL, 0, wsabuf, (DWORD) iovcnt, { 0, NULL}, 0 }; return send_internal (&wsamsg, 0); } #define TCP_MAXRT 5 /* Older systems don't support TCP_MAXRTMS TCP_MAXRT takes secs, not msecs. */ #ifndef SIO_TCP_SET_ACK_FREQUENCY #define SIO_TCP_SET_ACK_FREQUENCY _WSAIOW(IOC_VENDOR,23) #endif #define MAX_TCP_KEEPIDLE 32767 #define MAX_TCP_KEEPCNT 255 #define MAX_TCP_KEEPINTVL 32767 #define FIXED_WSOCK_TCP_KEEPCNT 10 int fhandler_socket_inet::set_keepalive (int keepidle, int keepcnt, int keepintvl) { struct tcp_keepalive tka; int so_keepalive = 0; int len = sizeof so_keepalive; int ret; DWORD dummy; /* Per MSDN, https://docs.microsoft.com/en-us/windows/win32/winsock/sio-keepalive-vals the subsequent keep-alive settings in struct tcp_keepalive are only used if the onoff member is != 0. Request the current state of SO_KEEPALIVE, then set the keep-alive options with onoff set to 1. On success, if SO_KEEPALIVE was 0, restore to the original SO_KEEPALIVE setting. Per the above MSDN doc, the SIO_KEEPALIVE_VALS settings are persistent across switching SO_KEEPALIVE. */ ret = ::getsockopt (get_socket (), SOL_SOCKET, SO_KEEPALIVE, (char *) &so_keepalive, &len); if (ret == SOCKET_ERROR) debug_printf ("getsockopt (SO_KEEPALIVE) failed, %u\n", WSAGetLastError ()); tka.onoff = 1; tka.keepalivetime = keepidle * MSPERSEC; /* WinSock TCP_KEEPCNT is fixed. But we still want that the keep-alive times out after TCP_KEEPIDLE + TCP_KEEPCNT * TCP_KEEPINTVL secs. To that end, we set keepaliveinterval so that keepaliveinterval * FIXED_WSOCK_TCP_KEEPCNT == TCP_KEEPINTVL * TCP_KEEPCNT FIXME? Does that make sense? Sidenote: Given the max values, the entire operation fits into an int. */ tka.keepaliveinterval = MSPERSEC / FIXED_WSOCK_TCP_KEEPCNT * keepcnt * keepintvl; if (WSAIoctl (get_socket (), SIO_KEEPALIVE_VALS, (LPVOID) &tka, sizeof tka, NULL, 0, &dummy, NULL, NULL) == SOCKET_ERROR) { set_winsock_errno (); return -1; } if (!so_keepalive) { ret = ::setsockopt (get_socket (), SOL_SOCKET, SO_KEEPALIVE, (const char *) &so_keepalive, sizeof so_keepalive); if (ret == SOCKET_ERROR) debug_printf ("setsockopt (SO_KEEPALIVE) failed, %u\n", WSAGetLastError ()); } return 0; } int fhandler_socket_inet::setsockopt (int level, int optname, const void *optval, socklen_t optlen) { bool ignore = false; int ret = -1; unsigned int winsock_val; /* Preprocessing setsockopt. Set ignore to true if setsockopt call should get skipped entirely. */ switch (level) { case SOL_SOCKET: switch (optname) { case SO_PEERCRED: set_errno (ENOPROTOOPT); return -1; case SO_REUSEADDR: /* Per POSIX we must not be able to reuse a complete duplicate of a local TCP address (same IP, same port), even if SO_REUSEADDR has been set. This behaviour is maintained in WinSock for backward compatibility, while the WinSock standard behaviour of stream socket binding is equivalent to the POSIX behaviour as if SO_REUSEADDR has been set. The SO_EXCLUSIVEADDRUSE option has been added to allow an application to request POSIX standard behaviour in the non-SO_REUSEADDR case. To emulate POSIX socket binding behaviour, note that SO_REUSEADDR has been set but don't call setsockopt. Instead fhandler_socket::bind sets SO_EXCLUSIVEADDRUSE if the application did not set SO_REUSEADDR. */ if (optlen < (socklen_t) sizeof (int)) { set_errno (EINVAL); return ret; } if (get_socket_type () == SOCK_STREAM) ignore = true; break; case SO_RCVTIMEO: case SO_SNDTIMEO: if (optlen < (socklen_t) sizeof (struct timeval)) { set_errno (EINVAL); return ret; } if (timeval_to_ms ((struct timeval *) optval, (optname == SO_RCVTIMEO) ? rcvtimeo () : sndtimeo ())) ret = 0; else set_errno (EDOM); return ret; case SO_OOBINLINE: /* Inline mode for out-of-band (OOB) data of winsock is completely broken. That is, SIOCATMARK always returns TRUE in inline mode. Due to this problem, application cannot determine OOB data at all. Therefore the behavior of a socket with SO_OOBINLINE set is simulated using a socket with SO_OOBINLINE not set. In this fake inline mode, the order of the OOB and non-OOB data is not preserved. OOB data is read before non-OOB data sent prior to the OOB data. However, this most likely is not a problem in most cases. */ /* Here, instead of actually setting inline mode, simply set the variable oobinline. */ oobinline = *(int *) optval ? true : false; ignore = true; break; default: break; } break; case IPPROTO_IP: switch (optname) { case IP_TOS: /* Winsock doesn't support setting the IP_TOS field with setsockopt and TOS was never implemented for TCP anyway. setsockopt returns WinSock error 10022, WSAEINVAL when trying to set the IP_TOS field. We just return 0 instead. */ ignore = true; break; default: break; } break; case IPPROTO_IPV6: switch (optname) { case IPV6_TCLASS: /* Unsupported */ ignore = true; break; default: break; } break; case IPPROTO_TCP: /* Check for stream socket early on, so we don't have to do this for every option. Also, WinSock returns EINVAL. */ if (type != SOCK_STREAM) { set_errno (EOPNOTSUPP); return -1; } switch (optname) { case TCP_MAXSEG: /* Winsock doesn't support setting TCP_MAXSEG, only requesting it via getsockopt. Make this a no-op. */ ignore = true; break; case TCP_QUICKACK: /* Various sources on the net claim that TCP_QUICKACK is supported by Windows, even using the same optname value of 12. However, the ws2ipdef.h header calls this option TCP_CONGESTION_ALGORITHM and there's no official statement, nor official documentation confirming or denying this option is equivalent to Linux' TCP_QUICKACK. Also, weirdly, this option takes values from 0..7. There is another undocumented option to WSAIoctl called SIO_TCP_SET_ACK_FREQUENCY which is already used by some projects, so we're going to use it here, too, for now. There's an open issue in the dotnet github, https://github.com/dotnet/runtime/issues/798 Hopefully this clarifies the situation in the not too distant future... */ { DWORD dummy; /* https://stackoverflow.com/questions/55034112/c-disable-delayed-ack-on-windows claims that valid values for SIO_TCP_SET_ACK_FREQUENCY are 1..255. In contrast to that, my own testing shows that valid values are 0 and 1 exclusively. */ int freq = !!*(int *) optval; if (WSAIoctl (get_socket (), SIO_TCP_SET_ACK_FREQUENCY, &freq, sizeof freq, NULL, 0, &dummy, NULL, NULL) == SOCKET_ERROR) { set_winsock_errno (); return -1; } ignore = true; tcp_quickack = freq ? true : false; } break; case TCP_MAXRT: /* Don't let this option slip through from user space. */ set_errno (EOPNOTSUPP); return -1; case TCP_USER_TIMEOUT: if (!wincap.has_tcp_maxrtms ()) { /* convert msecs to secs. Values < 1000 ms are converted to 0 secs, just as in WinSock. */ winsock_val = *(unsigned int *) optval / MSPERSEC; optname = TCP_MAXRT; optval = (const void *) &winsock_val; } break; case TCP_FASTOPEN: /* Fake FastOpen on older systems. */ if (!wincap.has_tcp_fastopen ()) { ignore = true; tcp_fastopen = *(int *) optval ? true : false; } break; case TCP_KEEPIDLE: /* Handle TCP_KEEPIDLE on older systems. */ if (!wincap.has_linux_tcp_keepalive_sockopts ()) { if (*(int *) optval < 1 || *(int *) optval > MAX_TCP_KEEPIDLE) { set_errno (EINVAL); return -1; } if (set_keepalive (*(int *) optval, tcp_keepcnt, tcp_keepintvl)) return -1; ignore = true; tcp_keepidle = *(int *) optval; } break; case TCP_KEEPCNT: /* Fake TCP_KEEPCNT on older systems. */ if (!wincap.has_linux_tcp_keepalive_sockopts ()) { if (*(int *) optval < 1 || *(int *) optval > MAX_TCP_KEEPCNT) { set_errno (EINVAL); return -1; } if (set_keepalive (tcp_keepidle, *(int *) optval, tcp_keepintvl)) return -1; ignore = true; tcp_keepcnt = *(int *) optval; } break; case TCP_KEEPINTVL: /* Handle TCP_KEEPINTVL on older systems. */ if (!wincap.has_linux_tcp_keepalive_sockopts ()) { if (*(int *) optval < 1 || *(int *) optval > MAX_TCP_KEEPINTVL) { set_errno (EINVAL); return -1; } if (set_keepalive (tcp_keepidle, tcp_keepcnt, *(int *) optval)) return -1; ignore = true; tcp_keepintvl = *(int *) optval; } break; default: break; } break; case IPPROTO_UDP: /* Check for dgram socket early on, so we don't have to do this for every option. Also, WinSock returns EINVAL. */ if (type != SOCK_DGRAM) { set_errno (EOPNOTSUPP); return -1; } if (optlen < (socklen_t) sizeof (int)) { set_errno (EINVAL); return ret; } switch (optname) { case UDP_SEGMENT: if (*(int *) optval < 0 || *(int *) optval > USHRT_MAX) { set_errno (EINVAL); return -1; } break; case UDP_GRO: /* In contrast to Windows' UDP_RECV_MAX_COALESCED_SIZE option, Linux' UDP_GRO option is just a bool. The max. packet size is dynamically evaluated from the MRU. There's no easy, reliable way to get the MRU. We assume that this is what Windows will do internally anyway and, given UDP_RECV_MAX_COALESCED_SIZE defines a *maximum* size for aggregated packages, we just choose the maximum sensible value. FIXME? IP_MTU_DISCOVER / IP_MTU */ winsock_val = *(int *) optval ? USHRT_MAX : 0; optval = &winsock_val; break; default: break; } break; default: break; } /* Call Winsock setsockopt (or not) */ if (ignore) ret = 0; else { ret = ::setsockopt (get_socket (), level, optname, (const char *) optval, optlen); if (ret == SOCKET_ERROR) { set_winsock_errno (); return ret; } } if (optlen == (socklen_t) sizeof (int)) debug_printf ("setsockopt optval=%x", *(int *) optval); /* Postprocessing setsockopt, setting fhandler_socket members, etc. */ switch (level) { case SOL_SOCKET: switch (optname) { case SO_REUSEADDR: saw_reuseaddr (*(int *) optval); break; case SO_RCVBUF: rmem (*(int *) optval); break; case SO_SNDBUF: wmem (*(int *) optval); break; default: break; } break; default: break; } return ret; } int fhandler_socket_inet::getsockopt (int level, int optname, const void *optval, socklen_t *optlen) { bool onebyte = false; int ret = -1; /* Preprocessing getsockopt. */ switch (level) { case SOL_SOCKET: switch (optname) { case SO_PEERCRED: set_errno (ENOPROTOOPT); return -1; case SO_REUSEADDR: { unsigned int *reuseaddr = (unsigned int *) optval; if (*optlen < (socklen_t) sizeof *reuseaddr) { set_errno (EINVAL); return -1; } *reuseaddr = saw_reuseaddr(); *optlen = (socklen_t) sizeof *reuseaddr; return 0; } case SO_RCVTIMEO: case SO_SNDTIMEO: { struct timeval *time_out = (struct timeval *) optval; if (*optlen < (socklen_t) sizeof *time_out) { set_errno (EINVAL); return -1; } DWORD ms = (optname == SO_RCVTIMEO) ? rcvtimeo () : sndtimeo (); if (ms == 0 || ms == INFINITE) { time_out->tv_sec = 0; time_out->tv_usec = 0; } else { time_out->tv_sec = ms / MSPERSEC; time_out->tv_usec = ((ms % MSPERSEC) * USPERSEC) / MSPERSEC; } *optlen = (socklen_t) sizeof *time_out; return 0; } case SO_TYPE: { unsigned int *type = (unsigned int *) optval; *type = get_socket_type (); *optlen = (socklen_t) sizeof *type; return 0; } case SO_OOBINLINE: *(int *) optval = oobinline ? 1 : 0; return 0; default: break; } break; case IPPROTO_IP: break; case IPPROTO_TCP: /* Check for stream socket early on, so we don't have to do this for every option. Also, WinSock returns EINVAL. */ if (type != SOCK_STREAM) { set_errno (EOPNOTSUPP); return -1; } switch (optname) { case TCP_QUICKACK: *(int *) optval = tcp_quickack ? 1 : 0; *optlen = sizeof (int); return 0; case TCP_MAXRT: /* Don't let this option slip through from user space. */ set_errno (EOPNOTSUPP); return -1; case TCP_USER_TIMEOUT: /* Older systems don't support TCP_MAXRTMS, just call TCP_MAXRT. */ if (!wincap.has_tcp_maxrtms ()) optname = TCP_MAXRT; break; case TCP_FASTOPEN: /* Fake FastOpen on older systems */ if (!wincap.has_tcp_fastopen ()) { *(int *) optval = tcp_fastopen ? 1 : 0; *optlen = sizeof (int); return 0; } break; case TCP_KEEPIDLE: /* Use stored value on older systems */ if (!wincap.has_linux_tcp_keepalive_sockopts ()) { *(int *) optval = tcp_keepidle; *optlen = sizeof (int); return 0; } break; case TCP_KEEPCNT: /* Use stored value on older systems */ if (!wincap.has_linux_tcp_keepalive_sockopts ()) { *(int *) optval = tcp_keepcnt; *optlen = sizeof (int); return 0; } break; case TCP_KEEPINTVL: /* Use stored value on older systems */ if (!wincap.has_linux_tcp_keepalive_sockopts ()) { *(int *) optval = tcp_keepintvl; *optlen = sizeof (int); return 0; } break; default: break; } break; case IPPROTO_UDP: /* Check for dgram socket early on, so we don't have to do this for every option. Also, WinSock returns EINVAL. */ if (type != SOCK_DGRAM) { set_errno (EOPNOTSUPP); return -1; } break; default: break; } /* Call Winsock getsockopt */ ret = ::getsockopt (get_socket (), level, optname, (char *) optval, (int *) optlen); if (ret == SOCKET_ERROR) { set_winsock_errno (); return ret; } /* Postprocessing getsockopt, setting fhandler_socket members, etc. Set onebyte true for options returning BOOLEAN instead of a boolean DWORD. */ switch (level) { case SOL_SOCKET: switch (optname) { case SO_ERROR: { int *e = (int *) optval; debug_printf ("WinSock SO_ERROR = %d", *e); *e = find_winsock_errno (*e); } break; case SO_KEEPALIVE: case SO_DONTROUTE: onebyte = true; break; default: break; } break; case IPPROTO_TCP: switch (optname) { case TCP_NODELAY: onebyte = true; break; case TCP_MAXRT: /* After above conversion from TCP_USER_TIMEOUT */ /* convert secs to msecs */ *(unsigned int *) optval *= MSPERSEC; break; case TCP_FASTOPEN: onebyte = true; break; default: break; } break; case IPPROTO_UDP: switch (optname) { case UDP_GRO: /* Convert to bool option */ *(unsigned int *) optval = *(unsigned int *) optval ? 1 : 0; break; default: break; } break; default: break; } if (onebyte) { /* Regression in 6.0 kernel and later: instead of a 4 byte BOOL value, a 1 byte BOOLEAN value is returned, in contrast to older systems and the documentation. Since an int type is expected by the calling application, we convert the result here. */ BOOLEAN *in = (BOOLEAN *) optval; int *out = (int *) optval; *out = *in; *optlen = 4; } return ret; } int fhandler_socket_wsock::ioctl (unsigned int cmd, void *p) { int res; switch (cmd) { /* Here we handle only ioctl commands which are understood by Winsock. However, we have a problem, which is, the different size of u_long in Windows and 64 bit Cygwin. This affects the definitions of FIOASYNC, etc, because they are defined in terms of sizeof(u_long). So we have to use case labels which are independent of the sizeof u_long. Since we're redefining u_long at the start of this file to matching Winsock's idea of u_long, we can use the real definitions in calls to Windows. In theory we also have to make sure to convert the different ideas of u_long between the application and Winsock, but fortunately, the parameters defined as u_long pointers are on Linux and BSD systems defined as int pointer, so the applications will use a type of the expected size. Hopefully. */ case FIOASYNC: case _IOW('f', 125, u_long): res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, *(int *) p ? ASYNC_MASK : 0); syscall_printf ("Async I/O on socket %s", *(int *) p ? "started" : "cancelled"); async_io (*(int *) p != 0); /* If async_io is switched off, revert the event handling. */ if (*(int *) p == 0) WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK); break; case FIONREAD: case _IOR('f', 127, u_long): /* Make sure to use the Winsock definition of FIONREAD. */ res = ::ioctlsocket (get_socket (), _IOR('f', 127, u_long), (u_long *) p); if (res == SOCKET_ERROR) set_winsock_errno (); break; case FIONBIO: case SIOCATMARK: /* Sockets are always non-blocking internally. So we just note the state here. */ /* Convert the different idea of u_long in the definition of cmd. */ if (((cmd >> 16) & IOCPARM_MASK) == sizeof (unsigned long)) cmd = (cmd & ~(IOCPARM_MASK << 16)) | (sizeof (u_long) << 16); if (cmd == FIONBIO) { syscall_printf ("socket is now %sblocking", *(int *) p ? "non" : ""); set_nonblocking (*(int *) p); res = 0; } else res = ::ioctlsocket (get_socket (), cmd, (u_long *) p); /* In winsock, the return value of SIOCATMARK is FALSE if OOB data exists, TRUE otherwise. This is almost opposite to expectation. */ /* SIOCATMARK = _IOR('s',7,u_long) */ if (cmd == _IOR('s',7,u_long) && !res) *(u_long *)p = !*(u_long *)p; break; default: res = fhandler_socket::ioctl (cmd, p); break; } syscall_printf ("%d = ioctl_socket(%x, %p)", res, cmd, p); return res; } int fhandler_socket_wsock::fcntl (int cmd, intptr_t arg) { int res = 0; switch (cmd) { case F_SETOWN: { pid_t pid = (pid_t) arg; LOCK_EVENTS; wsock_events->owner = pid; UNLOCK_EVENTS; debug_printf ("owner set to %d", pid); } break; case F_GETOWN: res = wsock_events->owner; break; default: res = fhandler_socket::fcntl (cmd, arg); break; } return res; }