static int myAccept (int fd, struct sockaddr *addr, socklen_t *addrlen) { SOCKET fh = SOCKET_ERROR; int new_fd; /* Parameters to system calls are not guaranteed to generate a SIGSEGV and for this reason we must touch them manually. */ _gst_grey_oop_range (addr, *addrlen); #if defined SOCK_CLOEXEC && defined HAVE_ACCEPT4 && !defined __MSVCRT__ if (have_sock_cloexec >= 0) { fh = accept4 (FD_TO_SOCKET (fd), addr, addrlen, SOCK_CLOEXEC); if (!check_have_sock_cloexec (fh, ENOSYS)) return -1; } #endif if (fh == SOCKET_ERROR) { fh = accept (FD_TO_SOCKET (fd), addr, addrlen); socket_set_cloexec (fh); } new_fd = (fh == SOCKET_ERROR ? -1 : SOCKET_TO_FD (fh)); if (new_fd != SOCKET_ERROR) _gst_register_socket (new_fd, false); return new_fd; }
static int _gl_close_fd_maybe_socket (int fd) { SOCKET sock = FD_TO_SOCKET (fd); WSANETWORKEVENTS ev; ev.lNetworkEvents = 0xDEADBEEF; WSAEnumNetworkEvents (sock, NULL, &ev); if (ev.lNetworkEvents != 0xDEADBEEF) { /* FIXME: other applications, like squid, use an undocumented _free_osfhnd free function. But this is not enough: The 'osfile' flags for fd also needs to be cleared, but it is hard to access it. Instead, here we just close twice the file descriptor. */ if (closesocket (sock)) { set_winsock_errno (); return -1; } else { /* This call frees the file descriptor and does a CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails. */ _close (fd); return 0; } } else return _close (fd); }
static int ioctl_fd_maybe_socket (const struct fd_hook *remaining_list, gl_ioctl_fn primary, int fd, int request, void *arg) { SOCKET sock; WSANETWORKEVENTS ev; /* Test whether fd refers to a socket. */ sock = FD_TO_SOCKET (fd); ev.lNetworkEvents = 0xDEADBEEF; WSAEnumNetworkEvents (sock, NULL, &ev); if (ev.lNetworkEvents != 0xDEADBEEF) { /* fd refers to a socket. */ if (ioctlsocket (sock, request, arg) < 0) { set_winsock_errno (); return -1; } else return 0; } else /* Some other type of file descriptor. */ return execute_ioctl_hooks (remaining_list, primary, fd, request, arg); }
ssize_t rpl_recvfrom (int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { SOCKET sock = FD_TO_SOCKET (fd); if (sock == INVALID_SOCKET) { errno = EBADF; return -1; } else { int frombufsize = (from != NULL ? *fromlen : 0); int r = recvfrom (sock, buf, len, flags, from, fromlen); if (r < 0) set_winsock_errno (); /* Winsock recvfrom() only returns a valid 'from' when the socket is connectionless. POSIX gives a valid 'from' for all types of sockets. */ else if (from != NULL && *fromlen == frombufsize) rpl_getpeername (fd, from, fromlen); return r; } }
int rpl_setsockopt (int fd, int level, int optname, const void *optval, socklen_t optlen) { SOCKET sock = FD_TO_SOCKET (fd); int r; if (sock == INVALID_SOCKET) { errno = EBADF; return -1; } else { if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { const struct timeval *tv = optval; int milliseconds = tv->tv_sec * 1000 + tv->tv_usec / 1000; optval = &milliseconds; r = setsockopt (sock, level, optname, optval, sizeof (int)); } else { r = setsockopt (sock, level, optname, optval, optlen); } if (r < 0) set_winsock_errno (); return r; } }
int rpl_connect (int fd, const struct sockaddr *sockaddr, socklen_t len) { SOCKET sock = FD_TO_SOCKET (fd); if (sock == INVALID_SOCKET) { errno = EBADF; return -1; } else { int r = connect (sock, sockaddr, len); if (r < 0) { /* EINPROGRESS is not returned by WinSock 2.0; for backwards compatibility, connect(2) uses EWOULDBLOCK. */ if (WSAGetLastError () == WSAEWOULDBLOCK) WSASetLastError (WSAEINPROGRESS); set_winsock_errno (); } return r; } }
/* Same as connect, but forces the socket to be in non-blocking mode */ static int myConnect (int fd, struct sockaddr *sockaddr, int len) { SOCKET sock = FD_TO_SOCKET (fd); int rc; #ifdef __MSVCRT__ unsigned long iMode = 1; ioctlsocket (sock, FIONBIO, &iMode); #elif defined F_GETFL #ifndef O_NONBLOCK #warning Non-blocking I/O could not be enabled #else int oldflags = fcntl (sock, F_GETFL, NULL); if (!(oldflags & O_NONBLOCK)) fcntl (sock, F_SETFL, oldflags | O_NONBLOCK); #endif #endif fix_sockaddr (sockaddr); rc = connect (sock, sockaddr, len); if (rc == 0 || is_socket_error (EINPROGRESS) || is_socket_error (EWOULDBLOCK)) return 0; else return -1; }
bool ssl_connect_wget (int fd, const char *hostname) { SSL *conn; struct scwt_context scwt_ctx; struct openssl_transport_context *ctx; DEBUGP (("Initiating SSL handshake.\n")); assert (ssl_ctx != NULL); conn = SSL_new (ssl_ctx); if (!conn) goto error; #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) /* If the SSL library was build with support for ServerNameIndication then use it whenever we have a hostname. If not, don't, ever. */ if (! is_valid_ip_address (hostname)) { if (! SSL_set_tlsext_host_name (conn, hostname)) { DEBUGP (("Failed to set TLS server-name indication.")); goto error; } } #endif #ifndef FD_TO_SOCKET # define FD_TO_SOCKET(X) (X) #endif if (!SSL_set_fd (conn, FD_TO_SOCKET (fd))) goto error; SSL_set_connect_state (conn); scwt_ctx.ssl = conn; if (run_with_timeout(opt.read_timeout, ssl_connect_with_timeout_callback, &scwt_ctx)) { DEBUGP (("SSL handshake timed out.\n")); goto timeout; } if (scwt_ctx.result <= 0 || conn->state != SSL_ST_OK) goto error; ctx = xnew0 (struct openssl_transport_context); ctx->conn = conn; /* Register FD with Wget's transport layer, i.e. arrange that our functions are used for reading, writing, and polling. */ fd_register_transport (fd, &openssl_transport, ctx); DEBUGP (("Handshake successful; connected socket %d to SSL handle 0x%0*lx\n", fd, PTR_FORMAT (conn))); return true; error: DEBUGP (("SSL handshake failed.\n")); print_errors (); timeout: if (conn) SSL_free (conn); return false; }
static int mySendto (int fd, const char *buf, int len, int flags, struct sockaddr *to, int tolen) { fix_sockaddr (to); return sendto (FD_TO_SOCKET (fd), buf, len, flags, to, tolen); }
ssize_t _gst_send (int fd, PTR buffer, size_t size, int flags) { #ifdef HAVE_SOCKETS ssize_t result; int save_errno = errno; for (;;) { result = send (FD_TO_SOCKET (fd), buffer, size, flags); if (is_socket_error (EFAULT)) abort (); if (is_socket_error (EINTR)) clear_socket_error (); else break; } if (errno == EINTR) errno = save_errno; return result; #else errno = ENOSYS; return -1; #endif }
static int myListen (int fd, int backlog) { int r = listen (FD_TO_SOCKET (fd), backlog); if (r != SOCKET_ERROR) _gst_register_socket (fd, true); return r; }
bool ssl_connect_wget (int fd) { static const int cert_type_priority[] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 }; struct wgnutls_transport_context *ctx; gnutls_session session; int err; int allowed_protocols[4] = {0, 0, 0, 0}; gnutls_init (&session, GNUTLS_CLIENT); gnutls_set_default_priority (session); gnutls_certificate_type_set_priority (session, cert_type_priority); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials); #ifndef FD_TO_SOCKET # define FD_TO_SOCKET(X) (X) #endif gnutls_transport_set_ptr (session, (gnutls_transport_ptr) FD_TO_SOCKET (fd)); err = 0; switch (opt.secure_protocol) { case secure_protocol_auto: break; case secure_protocol_sslv2: case secure_protocol_sslv3: allowed_protocols[0] = GNUTLS_SSL3; err = gnutls_protocol_set_priority (session, allowed_protocols); break; case secure_protocol_tlsv1: allowed_protocols[0] = GNUTLS_TLS1_0; allowed_protocols[1] = GNUTLS_TLS1_1; allowed_protocols[2] = GNUTLS_TLS1_2; err = gnutls_protocol_set_priority (session, allowed_protocols); break; default: abort (); } if (err < 0) { logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err)); gnutls_deinit (session); return false; } err = gnutls_handshake (session); if (err < 0) { logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err)); gnutls_deinit (session); return false; } ctx = xnew0 (struct wgnutls_transport_context); ctx->session = session; fd_register_transport (fd, &wgnutls_transport, ctx); return true; }
static int myGetsockopt (int fd, int level, int optname, char *optval, socklen_t *optlen) { /* Parameters to system calls are not guaranteed to generate a SIGSEGV and for this reason we must touch them manually. */ _gst_grey_oop_range (optval, *optlen); return getsockopt (FD_TO_SOCKET (fd), level, optname, optval, optlen); }
static int myGetsockname (int fd, struct sockaddr *addr, socklen_t *addrlen) { /* Parameters to system calls are not guaranteed to generate a SIGSEGV and for this reason we must touch them manually. */ _gst_grey_oop_range (addr, *addrlen); return getsockname (FD_TO_SOCKET (fd), addr, addrlen); }
int rpl_listen (int fd, int backlog) { SOCKET sock = FD_TO_SOCKET (fd); int r = listen (sock, backlog); if (r < 0) set_winsock_errno (); return r; }
ssize_t rpl_send (int fd, const void *buf, size_t len, int flags) { SOCKET sock = FD_TO_SOCKET (fd); int r = send (sock, buf, len, flags); if (r < 0) set_winsock_errno (); return r; }
int rpl_getpeername (int fd, struct sockaddr *addr, socklen_t *addrlen) { SOCKET sock = FD_TO_SOCKET (fd); int r = getpeername (sock, addr, addrlen); if (r < 0) set_winsock_errno (); return r; }
int rpl_shutdown (int fd, int how) { SOCKET sock = FD_TO_SOCKET (fd); int r = shutdown (sock, how); if (r < 0) set_winsock_errno (); return r; }
int rpl_bind (int fd, struct sockaddr *sockaddr, int len) { SOCKET sock = FD_TO_SOCKET (fd); int r = bind (sock, sockaddr, len); if (r < 0) set_winsock_errno (); return r; }
int rpl_getsockopt (int fd, int level, int optname, void *optval, socklen_t *optlen) { SOCKET sock = FD_TO_SOCKET (fd); if (sock == INVALID_SOCKET) { errno = EBADF; return -1; } else { int r; if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { int milliseconds; int milliseconds_len = sizeof (int); struct timeval tv; size_t n; r = getsockopt (sock, level, optname, (char *) &milliseconds, &milliseconds_len); tv.tv_sec = milliseconds / 1000; tv.tv_usec = (milliseconds - 1000 * tv.tv_sec) * 1000; n = sizeof (struct timeval); if (n > *optlen) n = *optlen; memcpy (optval, &tv, n); *optlen = n; } else { r = getsockopt (sock, level, optname, optval, optlen); } if (r < 0) set_winsock_errno (); return r; } }
int VMPI_close(int fildes) { SOCKET sd = FD_TO_SOCKET(fildes); if( WIN32_is_socket( sd ) ) { int result = closesocket( sd ); if( (result == SOCKET_ERROR) || (result == INVALID_SOCKET) ) { errno = WIN32_winsock_to_errno(); return -1; } return result; } return _close( fildes ); }
int rpl_shutdown (int fd, int how) { SOCKET sock = FD_TO_SOCKET (fd); if (sock == INVALID_SOCKET) { errno = EBADF; return -1; } else { int r = shutdown (sock, how); if (r < 0) set_winsock_errno (); return r; } }
int rpl_bind (int fd, const struct sockaddr *sockaddr, socklen_t len) { SOCKET sock = FD_TO_SOCKET (fd); if (sock == INVALID_SOCKET) { errno = EBADF; return -1; } else { int r = bind (sock, sockaddr, len); if (r < 0) set_winsock_errno (); return r; } }
int rpl_listen (int fd, int backlog) { SOCKET sock = FD_TO_SOCKET (fd); if (sock == INVALID_SOCKET) { errno = EBADF; return -1; } else { int r = listen (sock, backlog); if (r < 0) set_winsock_errno (); return r; } }
int rpl_getpeername (int fd, struct sockaddr *addr, socklen_t *addrlen) { SOCKET sock = FD_TO_SOCKET (fd); if (sock == INVALID_SOCKET) { errno = EBADF; return -1; } else { int r = getpeername (sock, addr, addrlen); if (r < 0) set_winsock_errno (); return r; } }
int rpl_ioctl (int fd, int req, ...) { void *buf; va_list args; SOCKET sock; int r; va_start (args, req); buf = va_arg (args, void *); va_end (args); sock = FD_TO_SOCKET (fd); r = ioctlsocket (sock, req, buf); if (r < 0) set_winsock_errno (); return r; }
ssize_t rpl_send (int fd, const void *buf, size_t len, int flags) { SOCKET sock = FD_TO_SOCKET (fd); if (sock == INVALID_SOCKET) { errno = EBADF; return -1; } else { int r = send (sock, buf, len, flags); if (r < 0) set_winsock_errno (); return r; } }
int VMPI_shutdown(int socket, int how) { int result; if( WIN32_SocketStart(2,2) == 0 ) { result = shutdown( FD_TO_SOCKET(socket), how ); } else { return -1; } if( (result == SOCKET_ERROR) || (result == INVALID_SOCKET) ) { errno = WIN32_winsock_to_errno(); return -1; } return result; }
int VMPI_send(int socket, const void *buffer, size_t length, int flags) { int result; if( WIN32_SocketStart(2,2) == 0 ) { result = send( FD_TO_SOCKET(socket), (const char *)buffer, (int)length, flags ); } else { return -1; } if( (result == SOCKET_ERROR) || (result == INVALID_SOCKET) ) { errno = WIN32_winsock_to_errno(); return -1; } return result; }
int VMPI_sendto(int socket, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len) { int result; if( WIN32_SocketStart(2,2) == 0 ) { result = sendto( FD_TO_SOCKET(socket), (const char *)message, (int)length, flags, dest_addr, dest_len ); } else { return -1; } if( (result == SOCKET_ERROR) || (result == INVALID_SOCKET) ) { errno = WIN32_winsock_to_errno(); return -1; } return result; }