Message ID | d7c1b8ff9247a09e54110abe6abe93543d59b8b6.1498654240.git.maozy.fnst@cn.fujitsu.com |
---|---|
State | New |
Headers | show |
On Wed, Jun 28, 2017 at 09:08:49PM +0800, Mao Zhongyi wrote: > diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h > index 5c326db..78e2b30 100644 > --- a/include/qemu/sockets.h > +++ b/include/qemu/sockets.h > if (qemu_isdigit(buf[0])) { > - if (!inet_aton(buf, &saddr->sin_addr)) > + if (!inet_aton(buf, &saddr->sin_addr)) { > + error_setg(errp, "host address '%s' is not a valid " > + "IPv4 address", buf); > return -1; > + } > } else { > - if ((he = gethostbyname(buf)) == NULL) > + he = gethostbyname(buf); > + if (he == NULL) { > + error_setg(errp, "can't resolve host address '%s': " > + "unknown host", buf); > return - 1; > + } gethostbyname sets 'h_errno' on failure, so you should pass that into error_setg_errno, instead of hardcoding 'unknown host' as a message Regards, Daniel
On 06/28/2017 08:23 AM, Daniel P. Berrange wrote: > On Wed, Jun 28, 2017 at 09:08:49PM +0800, Mao Zhongyi wrote: >> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h >> index 5c326db..78e2b30 100644 >> --- a/include/qemu/sockets.h >> +++ b/include/qemu/sockets.h > >> if (qemu_isdigit(buf[0])) { >> - if (!inet_aton(buf, &saddr->sin_addr)) >> + if (!inet_aton(buf, &saddr->sin_addr)) { >> + error_setg(errp, "host address '%s' is not a valid " >> + "IPv4 address", buf); >> return -1; >> + } >> } else { >> - if ((he = gethostbyname(buf)) == NULL) >> + he = gethostbyname(buf); >> + if (he == NULL) { >> + error_setg(errp, "can't resolve host address '%s': " >> + "unknown host", buf); >> return - 1; >> + } > > gethostbyname sets 'h_errno' on failure, so you should pass that > into error_setg_errno, instead of hardcoding 'unknown host' as a > message 'man gethostbyname' says it is deprecated, and that applications should use getaddrinfo/getnameinfo instead. What's our story here?
On Wed, Jun 28, 2017 at 09:24:58AM -0500, Eric Blake wrote: > On 06/28/2017 08:23 AM, Daniel P. Berrange wrote: > > On Wed, Jun 28, 2017 at 09:08:49PM +0800, Mao Zhongyi wrote: > >> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h > >> index 5c326db..78e2b30 100644 > >> --- a/include/qemu/sockets.h > >> +++ b/include/qemu/sockets.h > > > >> if (qemu_isdigit(buf[0])) { > >> - if (!inet_aton(buf, &saddr->sin_addr)) > >> + if (!inet_aton(buf, &saddr->sin_addr)) { > >> + error_setg(errp, "host address '%s' is not a valid " > >> + "IPv4 address", buf); > >> return -1; > >> + } > >> } else { > >> - if ((he = gethostbyname(buf)) == NULL) > >> + he = gethostbyname(buf); > >> + if (he == NULL) { > >> + error_setg(errp, "can't resolve host address '%s': " > >> + "unknown host", buf); > >> return - 1; > >> + } > > > > gethostbyname sets 'h_errno' on failure, so you should pass that > > into error_setg_errno, instead of hardcoding 'unknown host' as a > > message > > 'man gethostbyname' says it is deprecated, and that applications should > use getaddrinfo/getnameinfo instead. What's our story here? The real story is to get net/socket.c converted to QIOChannelSocket and kill this parse_host_port() method in sockets.c It is already broken by design since it takes a 'struct sockdddr_in' and thus can't do IPv6. This patch doesn't make the existing situation worse, so I think its fine to add this error reporting cleanup now, and not force immediate conversion to QIOChannelSocket today. The net/sockets.c code needs a further refactor before that conversion can be done in the right way - we've already reverted the wrong way twice ;-) Regards, Daniel
Hi, Daniel On 06/28/2017 09:23 PM, Daniel P. Berrange wrote: > On Wed, Jun 28, 2017 at 09:08:49PM +0800, Mao Zhongyi wrote: >> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h >> index 5c326db..78e2b30 100644 >> --- a/include/qemu/sockets.h >> +++ b/include/qemu/sockets.h > >> if (qemu_isdigit(buf[0])) { >> - if (!inet_aton(buf, &saddr->sin_addr)) >> + if (!inet_aton(buf, &saddr->sin_addr)) { >> + error_setg(errp, "host address '%s' is not a valid " >> + "IPv4 address", buf); >> return -1; >> + } >> } else { >> - if ((he = gethostbyname(buf)) == NULL) >> + he = gethostbyname(buf); >> + if (he == NULL) { >> + error_setg(errp, "can't resolve host address '%s': " >> + "unknown host", buf); >> return - 1; >> + } > > gethostbyname sets 'h_errno' on failure, so you should pass that > into error_setg_errno, instead of hardcoding 'unknown host' as a > message Yes, 'h_errno' will be seted detailed error message when gethostbyname() failed, but the value of 'h_errno', as far as I know, can be print by hstrerror(), herror() and gai_strerror(). I'm not sure 'h_errno' can be parsed correctly by error_setg_errno(), so I test it like this: herror("----herror----"); error_report("----hstrerror----%s", hstrerror(h_errno)); error_report("----gai_strerror----%s", gai_strerror(h_errno)); error_setg_errno(errp, h_errno, "can't resolve host address '%s'" ,buf); result: ----herror----: Unknown host qemu-system-x86_64: -net socket,listen=hostname:: ----hstrerror----Unknown host qemu-system-x86_64: -net socket,listen=hostname:: ----gai_strerror----Unknown error qemu-system-x86_64: -net socket,listen=hostname:: can't resolve host address 'hostname': Operation not permitted From the results, obviously the error message is different. error_setg_errno() prints a uncertain message like "Operation not permitted", I think that the value of 'h_errno' is treated as a standard error code for errno. Although they have the same value, the information contained may not be same. so is it really appropriate to pass 'h_errno' to error_setg_errno()? Thanks, Mao > Regards, > Daniel >
"Daniel P. Berrange" <berrange@redhat.com> writes: > On Wed, Jun 28, 2017 at 09:24:58AM -0500, Eric Blake wrote: >> On 06/28/2017 08:23 AM, Daniel P. Berrange wrote: >> > On Wed, Jun 28, 2017 at 09:08:49PM +0800, Mao Zhongyi wrote: >> >> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h >> >> index 5c326db..78e2b30 100644 >> >> --- a/include/qemu/sockets.h >> >> +++ b/include/qemu/sockets.h >> > >> >> if (qemu_isdigit(buf[0])) { >> >> - if (!inet_aton(buf, &saddr->sin_addr)) >> >> + if (!inet_aton(buf, &saddr->sin_addr)) { >> >> + error_setg(errp, "host address '%s' is not a valid " >> >> + "IPv4 address", buf); >> >> return -1; >> >> + } >> >> } else { >> >> - if ((he = gethostbyname(buf)) == NULL) >> >> + he = gethostbyname(buf); >> >> + if (he == NULL) { >> >> + error_setg(errp, "can't resolve host address '%s': " >> >> + "unknown host", buf); >> >> return - 1; >> >> + } >> > >> > gethostbyname sets 'h_errno' on failure, so you should pass that >> > into error_setg_errno, instead of hardcoding 'unknown host' as a >> > message 'unknown host' is misleading when h_errno != HOST_NOT_FOUND. >> 'man gethostbyname' says it is deprecated, and that applications should >> use getaddrinfo/getnameinfo instead. What's our story here? > > The real story is to get net/socket.c converted to QIOChannelSocket > and kill this parse_host_port() method in sockets.c It is already > broken by design since it takes a 'struct sockdddr_in' and thus > can't do IPv6. > > This patch doesn't make the existing situation worse, so I think > its fine to add this error reporting cleanup now, and not force > immediate conversion to QIOChannelSocket today. The net/sockets.c > code needs a further refactor before that conversion can be done > in the right way - we've already reverted the wrong way twice ;-) Until then, let's go with a generic error message, as I requested in my review of v5. Just drop the misleading ": unknown host" part.
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 5c326db..78e2b30 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -53,7 +53,8 @@ void socket_listen_cleanup(int fd, Error **errp); int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp); /* Old, ipv4 only bits. Don't use for new code. */ -int parse_host_port(struct sockaddr_in *saddr, const char *str); +int parse_host_port(struct sockaddr_in *saddr, const char *str, + Error **errp); int socket_init(void); /** diff --git a/net/net.c b/net/net.c index 6235aab..29cc7df 100644 --- a/net/net.c +++ b/net/net.c @@ -100,7 +100,8 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) return 0; } -int parse_host_port(struct sockaddr_in *saddr, const char *str) +int parse_host_port(struct sockaddr_in *saddr, const char *str, + Error **errp) { char buf[512]; struct hostent *he; @@ -108,24 +109,36 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str) int port; p = str; - if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { + error_setg(errp, "host address '%s' doesn't contain ':' " + "separating host from port", str); return -1; + } saddr->sin_family = AF_INET; if (buf[0] == '\0') { saddr->sin_addr.s_addr = 0; } else { if (qemu_isdigit(buf[0])) { - if (!inet_aton(buf, &saddr->sin_addr)) + if (!inet_aton(buf, &saddr->sin_addr)) { + error_setg(errp, "host address '%s' is not a valid " + "IPv4 address", buf); return -1; + } } else { - if ((he = gethostbyname(buf)) == NULL) + he = gethostbyname(buf); + if (he == NULL) { + error_setg(errp, "can't resolve host address '%s': " + "unknown host", buf); return - 1; + } saddr->sin_addr = *(struct in_addr *)he->h_addr; } } port = strtol(p, (char **)&r, 0); - if (r == p) + if (r == p) { + error_setg(errp, "port number '%s' is invalid", p); return -1; + } saddr->sin_port = htons(port); return 0; } diff --git a/net/socket.c b/net/socket.c index b6bacf4..90dd4c0 100644 --- a/net/socket.c +++ b/net/socket.c @@ -500,9 +500,12 @@ static int net_socket_listen_init(NetClientState *peer, NetSocketState *s; struct sockaddr_in saddr; int fd, ret; + Error *err = NULL; - if (parse_host_port(&saddr, host_str) < 0) + if (parse_host_port(&saddr, host_str, &err) < 0) { + error_report_err(err); return -1; + } fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { @@ -547,8 +550,10 @@ static int net_socket_connect_init(NetClientState *peer, struct sockaddr_in saddr; Error *err = NULL; - if (parse_host_port(&saddr, host_str) < 0) + if (parse_host_port(&saddr, host_str, &err) < 0) { + error_report_err(err); return -1; + } fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { @@ -600,8 +605,10 @@ static int net_socket_mcast_init(NetClientState *peer, struct in_addr localaddr, *param_localaddr; Error *err = NULL; - if (parse_host_port(&saddr, host_str) < 0) + if (parse_host_port(&saddr, host_str, &err) < 0) { + error_report_err(err); return -1; + } if (localaddr_str != NULL) { if (inet_aton(localaddr_str, &localaddr) == 0) @@ -643,11 +650,13 @@ static int net_socket_udp_init(NetClientState *peer, struct sockaddr_in laddr, raddr; Error *err = NULL; - if (parse_host_port(&laddr, lhost) < 0) { + if (parse_host_port(&laddr, lhost, &err) < 0) { + error_report_err(err); return -1; } - if (parse_host_port(&raddr, rhost) < 0) { + if (parse_host_port(&raddr, rhost, &err) < 0) { + error_report_err(err); return -1; }
Cc: berrange@redhat.com Cc: kraxel@redhat.com Cc: pbonzini@redhat.com Cc: jasowang@redhat.com Cc: armbru@redhat.com Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com> --- include/qemu/sockets.h | 3 ++- net/net.c | 23 ++++++++++++++++++----- net/socket.c | 19 ++++++++++++++----- 3 files changed, 34 insertions(+), 11 deletions(-)