}
-bool qemu_socket_select(SOCKET s, WSAEVENT hEventObject,
+bool qemu_socket_select(int sockfd, WSAEVENT hEventObject,
long lNetworkEvents, Error **errp)
{
+ SOCKET s = _get_osfhandle(sockfd);
+
if (errp == NULL) {
errp = &error_warn;
}
+ if (s == INVALID_SOCKET) {
+ error_setg(errp, "invalid socket fd=%d", sockfd);
+ return false;
+ }
+
if (WSAEventSelect(s, hEventObject, lNetworkEvents) != 0) {
error_setg_win32(errp, WSAGetLastError(), "failed to WSAEventSelect()");
return false;
return true;
}
-bool qemu_socket_unselect(SOCKET s, Error **errp)
+bool qemu_socket_unselect(int sockfd, Error **errp)
{
- return qemu_socket_select(s, NULL, 0, errp);
+ return qemu_socket_select(sockfd, NULL, 0, errp);
}
#undef connect
socklen_t addrlen)
{
int ret;
- ret = connect(sockfd, addr, addrlen);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = connect(s, addr, addrlen);
if (ret < 0) {
if (WSAGetLastError() == WSAEWOULDBLOCK) {
errno = EINPROGRESS;
int qemu_listen_wrap(int sockfd, int backlog)
{
int ret;
- ret = listen(sockfd, backlog);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = listen(s, backlog);
if (ret < 0) {
errno = socket_error();
}
socklen_t addrlen)
{
int ret;
- ret = bind(sockfd, addr, addrlen);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = bind(s, addr, addrlen);
if (ret < 0) {
errno = socket_error();
}
}
-#undef socket
-int qemu_socket_wrap(int domain, int type, int protocol)
+#undef closesocket
+int qemu_closesocket_wrap(int fd)
{
int ret;
- ret = socket(domain, type, protocol);
+ DWORD flags = 0;
+ SOCKET s = _get_osfhandle(fd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ /*
+ * If we were to just call _close on the descriptor, it would close the
+ * HANDLE, but it wouldn't free any of the resources associated to the
+ * SOCKET, and we can't call _close after calling closesocket, because
+ * closesocket has already closed the HANDLE, and _close would attempt to
+ * close the HANDLE again, resulting in a double free. We can however
+ * protect the HANDLE from actually being closed long enough to close the
+ * file descriptor, then close the socket itself.
+ */
+ if (!GetHandleInformation((HANDLE)s, &flags)) {
+ errno = EACCES;
+ return -1;
+ }
+
+ if (!SetHandleInformation((HANDLE)s, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE)) {
+ errno = EACCES;
+ return -1;
+ }
+
+ ret = close(fd);
+
+ if (!SetHandleInformation((HANDLE)s, flags, flags)) {
+ errno = EACCES;
+ return -1;
+ }
+
+ /*
+ * close() returns EBADF since we PROTECT_FROM_CLOSE the underlying handle,
+ * but the FD is actually freed
+ */
+ if (ret < 0 && errno != EBADF) {
+ return ret;
+ }
+
+ ret = closesocket(s);
if (ret < 0) {
errno = socket_error();
}
+
return ret;
}
+#undef socket
+int qemu_socket_wrap(int domain, int type, int protocol)
+{
+ SOCKET s;
+ int fd;
+
+ s = socket(domain, type, protocol);
+ if (s == -1) {
+ errno = socket_error();
+ return -1;
+ }
+
+ fd = _open_osfhandle(s, _O_BINARY);
+ if (fd < 0) {
+ closesocket(s);
+ /* _open_osfhandle may not set errno, and closesocket() may override it */
+ errno = ENOMEM;
+ }
+
+ return fd;
+}
+
+
#undef accept
int qemu_accept_wrap(int sockfd, struct sockaddr *addr,
socklen_t *addrlen)
{
- int ret;
- ret = accept(sockfd, addr, addrlen);
- if (ret < 0) {
+ int fd;
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ s = accept(s, addr, addrlen);
+ if (s == -1) {
errno = socket_error();
+ return -1;
}
- return ret;
+
+ fd = _open_osfhandle(s, _O_BINARY);
+ if (fd < 0) {
+ closesocket(s);
+ /* _open_osfhandle may not set errno, and closesocket() may override it */
+ errno = ENOMEM;
+ }
+
+ return fd;
}
int qemu_shutdown_wrap(int sockfd, int how)
{
int ret;
- ret = shutdown(sockfd, how);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = shutdown(s, how);
if (ret < 0) {
errno = socket_error();
}
int qemu_ioctlsocket_wrap(int fd, int req, void *val)
{
int ret;
- ret = ioctlsocket(fd, req, val);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
+ SOCKET s = _get_osfhandle(fd);
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
-#undef closesocket
-int qemu_closesocket_wrap(int fd)
-{
- int ret;
- ret = closesocket(fd);
+ ret = ioctlsocket(s, req, val);
if (ret < 0) {
errno = socket_error();
}
void *optval, socklen_t *optlen)
{
int ret;
- ret = getsockopt(sockfd, level, optname, optval, optlen);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = getsockopt(s, level, optname, optval, optlen);
if (ret < 0) {
errno = socket_error();
}
const void *optval, socklen_t optlen)
{
int ret;
- ret = setsockopt(sockfd, level, optname, optval, optlen);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = setsockopt(s, level, optname, optval, optlen);
if (ret < 0) {
errno = socket_error();
}
socklen_t *addrlen)
{
int ret;
- ret = getpeername(sockfd, addr, addrlen);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = getpeername(s, addr, addrlen);
if (ret < 0) {
errno = socket_error();
}
socklen_t *addrlen)
{
int ret;
- ret = getsockname(sockfd, addr, addrlen);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = getsockname(s, addr, addrlen);
if (ret < 0) {
errno = socket_error();
}
ssize_t qemu_send_wrap(int sockfd, const void *buf, size_t len, int flags)
{
int ret;
- ret = send(sockfd, buf, len, flags);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = send(s, buf, len, flags);
if (ret < 0) {
errno = socket_error();
}
const struct sockaddr *addr, socklen_t addrlen)
{
int ret;
- ret = sendto(sockfd, buf, len, flags, addr, addrlen);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = sendto(s, buf, len, flags, addr, addrlen);
if (ret < 0) {
errno = socket_error();
}
ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags)
{
int ret;
- ret = recv(sockfd, buf, len, flags);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = recv(s, buf, len, flags);
if (ret < 0) {
errno = socket_error();
}
struct sockaddr *addr, socklen_t *addrlen)
{
int ret;
- ret = recvfrom(sockfd, buf, len, flags, addr, addrlen);
+ SOCKET s = _get_osfhandle(sockfd);
+
+ if (s == INVALID_SOCKET) {
+ return -1;
+ }
+
+ ret = recvfrom(s, buf, len, flags, addr, addrlen);
if (ret < 0) {
errno = socket_error();
}