net/socket: Improve -net socket error reporting

When -net socket fails, it first reports a specific error, then
a generic one, like this:

    $ ./x86_64-softmmu/qemu-system-x86_64 -net socket,mcast=230.0.0.1:1234,listen
    qemu-system-x86_64: -net socket,mcast=230.0.0.1:1234,listen: exactly one of listen=, connect=, mcast= or udp= is required
    qemu-system-x86_64: -net socket,mcast=230.0.0.1:1234,listen: Device 'socket' could not be initialized

Convert net_socket_*_init() to Error to get rid of the superfluous second
error message. After the patch, the effect like this:

    $ ./x86_64-softmmu/qemu-system-x86_64 -net socket,mcast=230.0.0.1:1234,listen
    qemu-system-x86_64: -net socket,mcast=230.0.0.1:1234,listen: exactly one of listen=, connect=, mcast= or udp= is requireda

This also fixes a few silent failures to report an error.

Cc: jasowang@redhat.com
Cc: armbru@redhat.com
Cc: berrange@redhat.com
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
Mao Zhongyi 2017-09-04 22:35:40 +08:00 committed by Jason Wang
parent bcd4dfd685
commit 0522a959ae
1 changed files with 44 additions and 48 deletions

View File

@ -489,22 +489,21 @@ static void net_socket_accept(void *opaque)
static int net_socket_listen_init(NetClientState *peer, static int net_socket_listen_init(NetClientState *peer,
const char *model, const char *model,
const char *name, const char *name,
const char *host_str) const char *host_str,
Error **errp)
{ {
NetClientState *nc; NetClientState *nc;
NetSocketState *s; NetSocketState *s;
struct sockaddr_in saddr; struct sockaddr_in saddr;
int fd, ret; int fd, ret;
Error *err = NULL;
if (parse_host_port(&saddr, host_str, &err) < 0) { if (parse_host_port(&saddr, host_str, errp) < 0) {
error_report_err(err);
return -1; return -1;
} }
fd = qemu_socket(PF_INET, SOCK_STREAM, 0); fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0) { if (fd < 0) {
perror("socket"); error_setg_errno(errp, errno, "can't create stream socket");
return -1; return -1;
} }
qemu_set_nonblock(fd); qemu_set_nonblock(fd);
@ -513,13 +512,14 @@ static int net_socket_listen_init(NetClientState *peer,
ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret < 0) { if (ret < 0) {
perror("bind"); error_setg_errno(errp, errno, "can't bind ip=%s to socket",
inet_ntoa(saddr.sin_addr));
closesocket(fd); closesocket(fd);
return -1; return -1;
} }
ret = listen(fd, 0); ret = listen(fd, 0);
if (ret < 0) { if (ret < 0) {
perror("listen"); error_setg_errno(errp, errno, "can't listen on socket");
closesocket(fd); closesocket(fd);
return -1; return -1;
} }
@ -538,21 +538,20 @@ static int net_socket_listen_init(NetClientState *peer,
static int net_socket_connect_init(NetClientState *peer, static int net_socket_connect_init(NetClientState *peer,
const char *model, const char *model,
const char *name, const char *name,
const char *host_str) const char *host_str,
Error **errp)
{ {
NetSocketState *s; NetSocketState *s;
int fd, connected, ret; int fd, connected, ret;
struct sockaddr_in saddr; struct sockaddr_in saddr;
Error *err = NULL;
if (parse_host_port(&saddr, host_str, &err) < 0) { if (parse_host_port(&saddr, host_str, errp) < 0) {
error_report_err(err);
return -1; return -1;
} }
fd = qemu_socket(PF_INET, SOCK_STREAM, 0); fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0) { if (fd < 0) {
perror("socket"); error_setg_errno(errp, errno, "can't create stream socket");
return -1; return -1;
} }
qemu_set_nonblock(fd); qemu_set_nonblock(fd);
@ -568,7 +567,7 @@ static int net_socket_connect_init(NetClientState *peer,
errno == EINVAL) { errno == EINVAL) {
break; break;
} else { } else {
perror("connect"); error_setg_errno(errp, errno, "can't connect socket");
closesocket(fd); closesocket(fd);
return -1; return -1;
} }
@ -577,9 +576,8 @@ static int net_socket_connect_init(NetClientState *peer,
break; break;
} }
} }
s = net_socket_fd_init(peer, model, name, fd, connected, NULL, &err); s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp);
if (!s) { if (!s) {
error_report_err(err);
return -1; return -1;
} }
@ -593,36 +591,36 @@ static int net_socket_mcast_init(NetClientState *peer,
const char *model, const char *model,
const char *name, const char *name,
const char *host_str, const char *host_str,
const char *localaddr_str) const char *localaddr_str,
Error **errp)
{ {
NetSocketState *s; NetSocketState *s;
int fd; int fd;
struct sockaddr_in saddr; struct sockaddr_in saddr;
struct in_addr localaddr, *param_localaddr; struct in_addr localaddr, *param_localaddr;
Error *err = NULL;
if (parse_host_port(&saddr, host_str, &err) < 0) { if (parse_host_port(&saddr, host_str, errp) < 0) {
error_report_err(err);
return -1; return -1;
} }
if (localaddr_str != NULL) { if (localaddr_str != NULL) {
if (inet_aton(localaddr_str, &localaddr) == 0) if (inet_aton(localaddr_str, &localaddr) == 0) {
error_setg(errp, "localaddr '%s' is not a valid IPv4 address",
localaddr_str);
return -1; return -1;
}
param_localaddr = &localaddr; param_localaddr = &localaddr;
} else { } else {
param_localaddr = NULL; param_localaddr = NULL;
} }
fd = net_socket_mcast_create(&saddr, param_localaddr, &err); fd = net_socket_mcast_create(&saddr, param_localaddr, errp);
if (fd < 0) { if (fd < 0) {
error_report_err(err);
return -1; return -1;
} }
s = net_socket_fd_init(peer, model, name, fd, 0, NULL, &err); s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
if (!s) { if (!s) {
error_report_err(err);
return -1; return -1;
} }
@ -639,45 +637,45 @@ static int net_socket_udp_init(NetClientState *peer,
const char *model, const char *model,
const char *name, const char *name,
const char *rhost, const char *rhost,
const char *lhost) const char *lhost,
Error **errp)
{ {
NetSocketState *s; NetSocketState *s;
int fd, ret; int fd, ret;
struct sockaddr_in laddr, raddr; struct sockaddr_in laddr, raddr;
Error *err = NULL;
if (parse_host_port(&laddr, lhost, &err) < 0) { if (parse_host_port(&laddr, lhost, errp) < 0) {
error_report_err(err);
return -1; return -1;
} }
if (parse_host_port(&raddr, rhost, &err) < 0) { if (parse_host_port(&raddr, rhost, errp) < 0) {
error_report_err(err);
return -1; return -1;
} }
fd = qemu_socket(PF_INET, SOCK_DGRAM, 0); fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0) { if (fd < 0) {
perror("socket(PF_INET, SOCK_DGRAM)"); error_setg_errno(errp, errno, "can't create datagram socket");
return -1; return -1;
} }
ret = socket_set_fast_reuse(fd); ret = socket_set_fast_reuse(fd);
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, errno,
"can't set socket option SO_REUSEADDR");
closesocket(fd); closesocket(fd);
return -1; return -1;
} }
ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)); ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
if (ret < 0) { if (ret < 0) {
perror("bind"); error_setg_errno(errp, errno, "can't bind ip=%s to socket",
inet_ntoa(laddr.sin_addr));
closesocket(fd); closesocket(fd);
return -1; return -1;
} }
qemu_set_nonblock(fd); qemu_set_nonblock(fd);
s = net_socket_fd_init(peer, model, name, fd, 0, NULL, &err); s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
if (!s) { if (!s) {
error_report_err(err);
return -1; return -1;
} }
@ -692,8 +690,6 @@ static int net_socket_udp_init(NetClientState *peer,
int net_init_socket(const Netdev *netdev, const char *name, int net_init_socket(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp) NetClientState *peer, Error **errp)
{ {
/* FIXME error_setg(errp, ...) on failure */
Error *err = NULL;
const NetdevSocketOptions *sock; const NetdevSocketOptions *sock;
assert(netdev->type == NET_CLIENT_DRIVER_SOCKET); assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
@ -701,22 +697,21 @@ int net_init_socket(const Netdev *netdev, const char *name,
if (sock->has_listen + sock->has_connect + sock->has_mcast + if (sock->has_listen + sock->has_connect + sock->has_mcast +
sock->has_udp > 1) { sock->has_udp > 1) {
error_report("exactly one of listen=, connect=, mcast= or udp=" error_setg(errp, "exactly one of listen=, connect=, mcast= or udp="
" is required"); " is required");
return -1; return -1;
} }
if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) { if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
error_report("localaddr= is only valid with mcast= or udp="); error_setg(errp, "localaddr= is only valid with mcast= or udp=");
return -1; return -1;
} }
if (sock->has_fd) { if (sock->has_fd) {
int fd; int fd;
fd = monitor_fd_param(cur_mon, sock->fd, &err); fd = monitor_fd_param(cur_mon, sock->fd, errp);
if (fd == -1) { if (fd == -1) {
error_report_err(err);
return -1; return -1;
} }
qemu_set_nonblock(fd); qemu_set_nonblock(fd);
@ -728,15 +723,16 @@ int net_init_socket(const Netdev *netdev, const char *name,
} }
if (sock->has_listen) { if (sock->has_listen) {
if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) { if (net_socket_listen_init(peer, "socket", name, sock->listen, errp)
< 0) {
return -1; return -1;
} }
return 0; return 0;
} }
if (sock->has_connect) { if (sock->has_connect) {
if (net_socket_connect_init(peer, "socket", name, sock->connect) == if (net_socket_connect_init(peer, "socket", name, sock->connect, errp)
-1) { < 0) {
return -1; return -1;
} }
return 0; return 0;
@ -746,7 +742,7 @@ int net_init_socket(const Netdev *netdev, const char *name,
/* if sock->localaddr is missing, it has been initialized to "all bits /* if sock->localaddr is missing, it has been initialized to "all bits
* zero" */ * zero" */
if (net_socket_mcast_init(peer, "socket", name, sock->mcast, if (net_socket_mcast_init(peer, "socket", name, sock->mcast,
sock->localaddr) == -1) { sock->localaddr, errp) < 0) {
return -1; return -1;
} }
return 0; return 0;
@ -754,11 +750,11 @@ int net_init_socket(const Netdev *netdev, const char *name,
assert(sock->has_udp); assert(sock->has_udp);
if (!sock->has_localaddr) { if (!sock->has_localaddr) {
error_report("localaddr= is mandatory with udp="); error_setg(errp, "localaddr= is mandatory with udp=");
return -1; return -1;
} }
if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) == if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr,
-1) { errp) < 0) {
return -1; return -1;
} }
return 0; return 0;