diff options
-rw-r--r-- | include/qemu/sockets.h | 1 | ||||
-rw-r--r-- | net/socket.c | 9 | ||||
-rw-r--r-- | net/tap.c | 25 | ||||
-rw-r--r-- | util/oslib-posix.c | 26 | ||||
-rw-r--r-- | util/oslib-win32.c | 57 |
5 files changed, 79 insertions, 39 deletions
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 57cd049..7d1f813 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -18,6 +18,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); int socket_set_cork(int fd, int v); int socket_set_nodelay(int fd); void qemu_set_block(int fd); +int qemu_try_set_nonblock(int fd); void qemu_set_nonblock(int fd); int socket_set_fast_reuse(int fd); diff --git a/net/socket.c b/net/socket.c index c923540..2d21fdd 100644 --- a/net/socket.c +++ b/net/socket.c @@ -725,13 +725,18 @@ int net_init_socket(const Netdev *netdev, const char *name, } if (sock->has_fd) { - int fd; + int fd, ret; fd = monitor_fd_param(cur_mon, sock->fd, errp); if (fd == -1) { return -1; } - qemu_set_nonblock(fd); + ret = qemu_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return -1; + } if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast, errp)) { return -1; @@ -690,6 +690,8 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, } if (vhostfdname) { + int ret; + vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err); if (vhostfd == -1) { if (tap->has_vhostforce && tap->vhostforce) { @@ -699,7 +701,12 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, } return; } - qemu_set_nonblock(vhostfd); + ret = qemu_try_set_nonblock(vhostfd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return; + } } else { vhostfd = open("/dev/vhost-net", O_RDWR); if (vhostfd < 0) { @@ -767,6 +774,7 @@ int net_init_tap(const Netdev *netdev, const char *name, Error *err = NULL; const char *vhostfdname; char ifname[128]; + int ret = 0; assert(netdev->type == NET_CLIENT_DRIVER_TAP); tap = &netdev->u.tap; @@ -795,7 +803,12 @@ int net_init_tap(const Netdev *netdev, const char *name, return -1; } - qemu_set_nonblock(fd); + ret = qemu_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return -1; + } vnet_hdr = tap_probe_vnet_hdr(fd); @@ -810,7 +823,6 @@ int net_init_tap(const Netdev *netdev, const char *name, char **fds; char **vhost_fds; int nfds = 0, nvhosts = 0; - int ret = 0; if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_helper || tap->has_queues || @@ -842,7 +854,12 @@ int net_init_tap(const Netdev *netdev, const char *name, goto free_fail; } - qemu_set_nonblock(fd); + ret = qemu_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + goto free_fail; + } if (i == 0) { vnet_hdr = tap_probe_vnet_hdr(fd); diff --git a/util/oslib-posix.c b/util/oslib-posix.c index e60aea8..36bf859 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -260,25 +260,35 @@ void qemu_set_block(int fd) assert(f != -1); } -void qemu_set_nonblock(int fd) +int qemu_try_set_nonblock(int fd) { int f; f = fcntl(fd, F_GETFL); - assert(f != -1); - f = fcntl(fd, F_SETFL, f | O_NONBLOCK); -#ifdef __OpenBSD__ if (f == -1) { + return -errno; + } + if (fcntl(fd, F_SETFL, f | O_NONBLOCK) == -1) { +#ifdef __OpenBSD__ /* * Previous to OpenBSD 6.3, fcntl(F_SETFL) is not permitted on * memory devices and sets errno to ENODEV. * It's OK if we fail to set O_NONBLOCK on devices like /dev/null, * because they will never block anyway. */ - assert(errno == ENODEV); - } -#else - assert(f != -1); + if (errno == ENODEV) { + return 0; + } #endif + return -errno; + } + return 0; +} + +void qemu_set_nonblock(int fd) +{ + int f; + f = qemu_try_set_nonblock(fd); + assert(f == 0); } int socket_set_fast_reuse(int fd) diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 3b49d27..7eedbe5 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -132,31 +132,6 @@ struct tm *localtime_r(const time_t *timep, struct tm *result) } #endif /* CONFIG_LOCALTIME_R */ -void qemu_set_block(int fd) -{ - unsigned long opt = 0; - WSAEventSelect(fd, NULL, 0); - ioctlsocket(fd, FIONBIO, &opt); -} - -void qemu_set_nonblock(int fd) -{ - unsigned long opt = 1; - ioctlsocket(fd, FIONBIO, &opt); - qemu_fd_register(fd); -} - -int socket_set_fast_reuse(int fd) -{ - /* Enabling the reuse of an endpoint that was used by a socket still in - * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows - * fast reuse is the default and SO_REUSEADDR does strange things. So we - * don't have to do anything here. More info can be found at: - * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ - return 0; -} - - static int socket_error(void) { switch (WSAGetLastError()) { @@ -233,6 +208,38 @@ static int socket_error(void) } } +void qemu_set_block(int fd) +{ + unsigned long opt = 0; + WSAEventSelect(fd, NULL, 0); + ioctlsocket(fd, FIONBIO, &opt); +} + +int qemu_try_set_nonblock(int fd) +{ + unsigned long opt = 1; + if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) { + return -socket_error(); + } + qemu_fd_register(fd); + return 0; +} + +void qemu_set_nonblock(int fd) +{ + (void)qemu_try_set_nonblock(fd); +} + +int socket_set_fast_reuse(int fd) +{ + /* Enabling the reuse of an endpoint that was used by a socket still in + * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows + * fast reuse is the default and SO_REUSEADDR does strange things. So we + * don't have to do anything here. More info can be found at: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ + return 0; +} + int inet_aton(const char *cp, struct in_addr *ia) { uint32_t addr = inet_addr(cp); |