#include "clients.h"
#include "monitor/monitor.h"
#include "qapi/error.h"
-#include "qemu-common.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
#include "qemu/sockets.h"
NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
ssize_t ret;
- do {
- ret = qemu_sendto(s->fd, buf, size, 0,
- (struct sockaddr *)&s->dgram_dst,
- sizeof(s->dgram_dst));
- } while (ret == -1 && errno == EINTR);
+ ret = RETRY_ON_EINTR(
+ s->dgram_dst.sin_family != AF_UNIX ?
+ sendto(s->fd, buf, size, 0,
+ (struct sockaddr *)&s->dgram_dst,
+ sizeof(s->dgram_dst)) :
+ send(s->fd, buf, size, 0)
+ );
if (ret == -1 && errno == EAGAIN) {
net_socket_write_poll(s, true);
uint8_t buf1[NET_BUFSIZE];
const uint8_t *buf;
- size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
+ size = recv(s->fd, buf1, sizeof(buf1), 0);
if (size < 0) {
if (errno != EWOULDBLOCK)
goto eoc;
if (s->listen_fd != -1) {
qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
}
- closesocket(s->fd);
+ close(s->fd);
s->fd = -1;
net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
s->nc.link_down = true;
- memset(s->nc.info_str, 0, sizeof(s->nc.info_str));
+ qemu_set_info_str(&s->nc, "%s", "");
return;
}
NetSocketState *s = opaque;
int size;
- size = qemu_recv(s->fd, s->rs.buf, sizeof(s->rs.buf), 0);
+ size = recv(s->fd, s->rs.buf, sizeof(s->rs.buf), 0);
if (size < 0)
return;
if (size == 0) {
* only on posix systems.
*/
val = 1;
- ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+ ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
if (ret < 0) {
error_setg_errno(errp, errno,
"can't set socket option SO_REUSEADDR");
imr.imr_interface.s_addr = htonl(INADDR_ANY);
}
- ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &imr, sizeof(struct ip_mreq));
+ ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ &imr, sizeof(struct ip_mreq));
if (ret < 0) {
error_setg_errno(errp, errno,
"can't add socket to multicast group %s",
/* Force mcast msgs to loopback (eg. several QEMUs in same host */
loop = 1;
- ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
- &loop, sizeof(loop));
+ ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
+ &loop, sizeof(loop));
if (ret < 0) {
error_setg_errno(errp, errno,
"can't force multicast message to loopback");
/* If a bind address is given, only send packets from that address */
if (localaddr != NULL) {
- ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
- localaddr, sizeof(*localaddr));
+ ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
+ localaddr, sizeof(*localaddr));
if (ret < 0) {
error_setg_errno(errp, errno,
"can't set the default network send interface");
}
}
- qemu_set_nonblock(fd);
+ qemu_socket_set_nonblock(fd);
return fd;
fail:
if (fd >= 0)
- closesocket(fd);
+ close(fd);
return -1;
}
}
if (s->listen_fd != -1) {
qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
- closesocket(s->listen_fd);
+ close(s->listen_fd);
s->listen_fd = -1;
}
}
int newfd;
NetClientState *nc;
NetSocketState *s;
+ SocketAddress *sa;
+ SocketAddressType sa_type;
+
+ sa = socket_local_address(fd, errp);
+ if (!sa) {
+ return NULL;
+ }
+ sa_type = sa->type;
+ qapi_free_SocketAddress(sa);
/* fd passed: multicast: "learn" dgram_dst address from bound address and save it
* Because this may be "shared" socket from a "master" process, datagrams would be recv()
net_socket_read_poll(s, true);
/* mcast: save bound address as dst */
- if (is_connected) {
+ if (is_connected && mcast != NULL) {
s->dgram_dst = saddr;
- snprintf(nc->info_str, sizeof(nc->info_str),
- "socket: fd=%d (cloned mcast=%s:%d)",
- fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ qemu_set_info_str(nc, "socket: fd=%d (cloned mcast=%s:%d)", fd,
+ inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
} else {
- snprintf(nc->info_str, sizeof(nc->info_str),
- "socket: fd=%d", fd);
+ if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) {
+ s->dgram_dst.sin_family = AF_UNIX;
+ }
+
+ qemu_set_info_str(nc, "socket: fd=%d %s", fd,
+ SocketAddressType_str(sa_type));
}
return s;
err:
- closesocket(fd);
+ close(fd);
return NULL;
}
nc = qemu_new_net_client(&net_socket_info, peer, model, name);
- snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd);
+ qemu_set_info_str(nc, "socket: fd=%d", fd);
s = DO_UPCAST(NetSocketState, nc, nc);
return s;
}
-static NetSocketState *net_socket_fd_init(NetClientState *peer,
- const char *model, const char *name,
- int fd, int is_connected,
- const char *mc, Error **errp)
+static int net_socket_fd_check(int fd, Error **errp)
{
- int so_type = -1, optlen=sizeof(so_type);
+ int so_type, optlen = sizeof(so_type);
- if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
- (socklen_t *)&optlen)< 0) {
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
+ (socklen_t *)&optlen) < 0) {
error_setg(errp, "can't get socket option SO_TYPE");
- closesocket(fd);
- return NULL;
+ return -1;
}
- switch(so_type) {
- case SOCK_DGRAM:
- return net_socket_fd_init_dgram(peer, model, name, fd, is_connected,
- mc, errp);
- case SOCK_STREAM:
- return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
- default:
- error_report("socket type=%d for fd=%d must be either"
- " SOCK_DGRAM or SOCK_STREAM", so_type, fd);
- closesocket(fd);
+ if (so_type != SOCK_DGRAM && so_type != SOCK_STREAM) {
+ error_setg(errp, "socket type=%d for fd=%d must be either"
+ " SOCK_DGRAM or SOCK_STREAM", so_type, fd);
+ return -1;
}
- return NULL;
+ return so_type;
}
static void net_socket_accept(void *opaque)
s->fd = fd;
s->nc.link_down = false;
net_socket_connect(s);
- snprintf(s->nc.info_str, sizeof(s->nc.info_str),
- "socket: connection from %s:%d",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ qemu_set_info_str(&s->nc, "socket: connection from %s:%d",
+ inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
}
static int net_socket_listen_init(NetClientState *peer,
error_setg_errno(errp, errno, "can't create stream socket");
return -1;
}
- qemu_set_nonblock(fd);
+ qemu_socket_set_nonblock(fd);
socket_set_fast_reuse(fd);
if (ret < 0) {
error_setg_errno(errp, errno, "can't bind ip=%s to socket",
inet_ntoa(saddr.sin_addr));
- closesocket(fd);
+ close(fd);
return -1;
}
ret = listen(fd, 0);
if (ret < 0) {
error_setg_errno(errp, errno, "can't listen on socket");
- closesocket(fd);
+ close(fd);
return -1;
}
error_setg_errno(errp, errno, "can't create stream socket");
return -1;
}
- qemu_set_nonblock(fd);
+ qemu_socket_set_nonblock(fd);
connected = 0;
for(;;) {
if (errno == EINTR || errno == EWOULDBLOCK) {
/* continue */
} else if (errno == EINPROGRESS ||
- errno == EALREADY ||
- errno == EINVAL) {
+ errno == EALREADY) {
break;
} else {
error_setg_errno(errp, errno, "can't connect socket");
- closesocket(fd);
+ close(fd);
return -1;
}
} else {
break;
}
}
- s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp);
+ s = net_socket_fd_init_stream(peer, model, name, fd, connected);
if (!s) {
return -1;
}
- snprintf(s->nc.info_str, sizeof(s->nc.info_str),
- "socket: connect to %s:%d",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ qemu_set_info_str(&s->nc, "socket: connect to %s:%d",
+ inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
return 0;
}
return -1;
}
- s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
+ s = net_socket_fd_init_dgram(peer, model, name, fd, 0, NULL, errp);
if (!s) {
return -1;
}
s->dgram_dst = saddr;
- snprintf(s->nc.info_str, sizeof(s->nc.info_str),
- "socket: mcast=%s:%d",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ qemu_set_info_str(&s->nc, "socket: mcast=%s:%d",
+ inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
return 0;
}
if (ret < 0) {
error_setg_errno(errp, errno,
"can't set socket option SO_REUSEADDR");
- closesocket(fd);
+ close(fd);
return -1;
}
ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
if (ret < 0) {
error_setg_errno(errp, errno, "can't bind ip=%s to socket",
inet_ntoa(laddr.sin_addr));
- closesocket(fd);
+ close(fd);
return -1;
}
- qemu_set_nonblock(fd);
+ qemu_socket_set_nonblock(fd);
- s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
+ s = net_socket_fd_init_dgram(peer, model, name, fd, 0, NULL, errp);
if (!s) {
return -1;
}
s->dgram_dst = raddr;
- snprintf(s->nc.info_str, sizeof(s->nc.info_str),
- "socket: udp=%s:%d",
- inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
+ qemu_set_info_str(&s->nc, "socket: udp=%s:%d", inet_ntoa(raddr.sin_addr),
+ ntohs(raddr.sin_port));
return 0;
}
assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
sock = &netdev->u.socket;
- if (sock->has_listen + sock->has_connect + sock->has_mcast +
- sock->has_udp > 1) {
+ if (!!sock->fd + !!sock->listen + !!sock->connect + !!sock->mcast +
+ !!sock->udp != 1) {
error_setg(errp, "exactly one of listen=, connect=, mcast= or udp="
" is required");
return -1;
}
- if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
+ if (sock->localaddr && !sock->mcast && !sock->udp) {
error_setg(errp, "localaddr= is only valid with mcast= or udp=");
return -1;
}
- if (sock->has_fd) {
- int fd;
+ if (sock->fd) {
+ int fd, ret, so_type;
- fd = monitor_fd_param(cur_mon, sock->fd, errp);
+ fd = monitor_fd_param(monitor_cur(), sock->fd, errp);
if (fd == -1) {
return -1;
}
- qemu_set_nonblock(fd);
- if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast,
- errp)) {
+ so_type = net_socket_fd_check(fd, errp);
+ if (so_type < 0) {
+ return -1;
+ }
+ ret = qemu_socket_try_set_nonblock(fd);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
+ name, fd);
return -1;
}
+ switch (so_type) {
+ case SOCK_DGRAM:
+ if (!net_socket_fd_init_dgram(peer, "socket", name, fd, 1,
+ sock->mcast, errp)) {
+ return -1;
+ }
+ break;
+ case SOCK_STREAM:
+ if (!net_socket_fd_init_stream(peer, "socket", name, fd, 1)) {
+ return -1;
+ }
+ break;
+ }
return 0;
}
- if (sock->has_listen) {
+ if (sock->listen) {
if (net_socket_listen_init(peer, "socket", name, sock->listen, errp)
< 0) {
return -1;
return 0;
}
- if (sock->has_connect) {
+ if (sock->connect) {
if (net_socket_connect_init(peer, "socket", name, sock->connect, errp)
< 0) {
return -1;
return 0;
}
- if (sock->has_mcast) {
+ if (sock->mcast) {
/* if sock->localaddr is missing, it has been initialized to "all bits
* zero" */
if (net_socket_mcast_init(peer, "socket", name, sock->mcast,
return 0;
}
- assert(sock->has_udp);
- if (!sock->has_localaddr) {
+ assert(sock->udp);
+ if (!sock->localaddr) {
error_setg(errp, "localaddr= is mandatory with udp=");
return -1;
}