[libvirt] [PATCH 0/2] utils: squelch errors from virNetSocketNewConnectTCP

Patch1 fixes a case where error is reported even when the reportError parameter is false. Patch2 is essentially a V2 of a patch posted earlier, incorporating some ideas from jferlan's review https://www.redhat.com/archives/libvir-list/2018-March/msg01120.html Jim Fehlig (2): util: honor reportError parameter in virSocketAddrParseInternal util: introduce virSocketAddrParseAny src/libvirt_private.syms | 1 + src/rpc/virnetsocket.c | 2 +- src/util/virsocketaddr.c | 53 ++++++++++++++++++++++++++++++++++++++++++++---- src/util/virsocketaddr.h | 5 +++++ 4 files changed, 56 insertions(+), 5 deletions(-) -- 2.16.2

Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/util/virsocketaddr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 95b527436..31a740cb8 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -107,7 +107,8 @@ virSocketAddrParseInternal(struct addrinfo **res, int err; if (val == NULL) { - virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing address")); + if (reportError) + virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing address")); return -1; } -- 2.16.2

On 03/26/2018 04:29 PM, Jim Fehlig wrote:
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/util/virsocketaddr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
Reviewed-by: John Ferlan <jferlan@redhat.com> May was well wait for 4.2.0 to be released before pushing... John
diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 95b527436..31a740cb8 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -107,7 +107,8 @@ virSocketAddrParseInternal(struct addrinfo **res, int err;
if (val == NULL) { - virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing address")); + if (reportError) + virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing address")); return -1; }

When preparing for migration, the libxl driver creates a new TCP listen socket for the incoming migration by calling virNetSocketNewListenTCP, passing the destination host name. virNetSocketNewListenTCP calls virSocketAddrParse to check if the host name is a wildcard address, in which case it avoids adding the AI_ADDRCONFIG flag to the hints passed to getaddrinfo. If the host name is not an IP address, virSocketAddrParse reports an error error : virSocketAddrParseInternal:121 : Cannot parse socket address 'myhost.example.com': Name or service not known But virNetSocketNewListenTCP succeeds regardless and the overall migration operation succeeds. Introduce virSocketAddrParseAny and use it when simply testing if a host name/addr is parsable. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- Essentially a V2 of https://www.redhat.com/archives/libvir-list/2018-March/msg01120.html It takes a slightly different approach by creating a function that can parse host names or IP addresses. src/libvirt_private.syms | 1 + src/rpc/virnetsocket.c | 2 +- src/util/virsocketaddr.c | 50 +++++++++++++++++++++++++++++++++++++++++++++--- src/util/virsocketaddr.h | 5 +++++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 03fe3b315..f6cdcde72 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2725,6 +2725,7 @@ virSocketAddrMask; virSocketAddrMaskByPrefix; virSocketAddrNumericFamily; virSocketAddrParse; +virSocketAddrParseAny; virSocketAddrParseIPv4; virSocketAddrParseIPv6; virSocketAddrPrefixToNetmask; diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index 2d41a716b..f362a0955 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -333,7 +333,7 @@ int virNetSocketNewListenTCP(const char *nodename, * startup in most cases. */ if (nodename && - !(virSocketAddrParse(&tmp_addr, nodename, AF_UNSPEC) > 0 && + !(virSocketAddrParseAny(&tmp_addr, nodename, AF_UNSPEC, false) > 0 && virSocketAddrIsWildcard(&tmp_addr))) hints.ai_flags |= AI_ADDRCONFIG; diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 31a740cb8..84610560f 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -101,6 +101,7 @@ static int virSocketAddrParseInternal(struct addrinfo **res, const char *val, int family, + int ai_flags, bool reportError) { struct addrinfo hints; @@ -114,7 +115,7 @@ virSocketAddrParseInternal(struct addrinfo **res, memset(&hints, 0, sizeof(hints)); hints.ai_family = family; - hints.ai_flags = AI_NUMERICHOST; + hints.ai_flags = ai_flags; if ((err = getaddrinfo(val, NULL, &hints, res)) != 0) { if (reportError) virReportError(VIR_ERR_SYSTEM_ERROR, @@ -143,7 +144,7 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) int len; struct addrinfo *res; - if (virSocketAddrParseInternal(&res, val, family, true) < 0) + if (virSocketAddrParseInternal(&res, val, family, AI_NUMERICHOST, true) < 0) return -1; if (res == NULL) { @@ -163,6 +164,49 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) return len; } +/** + * virSocketAddrParseAny: + * @addr: where to store the return value, optional. + * @val: a network host name or a numeric network address IPv4 or IPv6 + * @family: address family to pass down to getaddrinfo + * @reportError: boolean to control error reporting + * + * Mostly a wrapper for getaddrinfo() extracting the address storage + * from a host name like acme.example.com or a numeric string like 1.2.3.4 + * or 2001:db8:85a3:0:0:8a2e:370:7334 + * + * Returns the length of the network address or -1 in case of error. + */ +int virSocketAddrParseAny(virSocketAddrPtr addr, + const char *val, + int family, + bool reportError) +{ + int len; + struct addrinfo *res; + + if (virSocketAddrParseInternal(&res, val, family, 0, reportError) < 0) + return -1; + + if (res == NULL) { + if (reportError) { + virReportError(VIR_ERR_SYSTEM_ERROR, + _("No socket addresses found for '%s'"), + val); + } + return -1; + } + + len = res->ai_addrlen; + if (addr != NULL) { + memcpy(&addr->data.stor, res->ai_addr, len); + addr->len = res->ai_addrlen; + } + + freeaddrinfo(res); + return len; +} + /* * virSocketAddrParseIPv4: * @val: an IPv4 numeric address @@ -1105,7 +1149,7 @@ virSocketAddrNumericFamily(const char *address) struct addrinfo *res; unsigned short family; - if (virSocketAddrParseInternal(&res, address, AF_UNSPEC, false) < 0) + if (virSocketAddrParseInternal(&res, address, AF_UNSPEC, AI_NUMERICHOST, false) < 0) return -1; family = res->ai_addr->sa_family; diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h index 80e792618..302933848 100644 --- a/src/util/virsocketaddr.h +++ b/src/util/virsocketaddr.h @@ -92,6 +92,11 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family); +int virSocketAddrParseAny(virSocketAddrPtr addr, + const char *val, + int family, + bool reportError); + int virSocketAddrParseIPv4(virSocketAddrPtr addr, const char *val); -- 2.16.2

On 03/26/2018 04:29 PM, Jim Fehlig wrote:
When preparing for migration, the libxl driver creates a new TCP listen socket for the incoming migration by calling virNetSocketNewListenTCP, passing the destination host name. virNetSocketNewListenTCP calls virSocketAddrParse to check if the host name is a wildcard address, in which case it avoids adding the AI_ADDRCONFIG flag to the hints passed to getaddrinfo. If the host name is not an IP address, virSocketAddrParse reports an error
error : virSocketAddrParseInternal:121 : Cannot parse socket address 'myhost.example.com': Name or service not known
But virNetSocketNewListenTCP succeeds regardless and the overall migration operation succeeds.
Introduce virSocketAddrParseAny and use it when simply testing if a host name/addr is parsable.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
Essentially a V2 of
https://www.redhat.com/archives/libvir-list/2018-March/msg01120.html
It takes a slightly different approach by creating a function that can parse host names or IP addresses.
src/libvirt_private.syms | 1 + src/rpc/virnetsocket.c | 2 +- src/util/virsocketaddr.c | 50 +++++++++++++++++++++++++++++++++++++++++++++--- src/util/virsocketaddr.h | 5 +++++ 4 files changed, 54 insertions(+), 4 deletions(-)
Reviewed-by: John Ferlan <jferlan@redhat.com> Wait for 4.2.0 for this one... John BTW: Your call on whether to add to the new API comments something about the API could be susceptible to a delay due to network name resolution lookup pause. That is, from the getaddrinfo man page: "The AI_NUMERICHOST flag suppresses any potentially lengthy network host address lookups."

On 03/29/2018 11:27 AM, John Ferlan wrote:
On 03/26/2018 04:29 PM, Jim Fehlig wrote:
When preparing for migration, the libxl driver creates a new TCP listen socket for the incoming migration by calling virNetSocketNewListenTCP, passing the destination host name. virNetSocketNewListenTCP calls virSocketAddrParse to check if the host name is a wildcard address, in which case it avoids adding the AI_ADDRCONFIG flag to the hints passed to getaddrinfo. If the host name is not an IP address, virSocketAddrParse reports an error
error : virSocketAddrParseInternal:121 : Cannot parse socket address 'myhost.example.com': Name or service not known
But virNetSocketNewListenTCP succeeds regardless and the overall migration operation succeeds.
Introduce virSocketAddrParseAny and use it when simply testing if a host name/addr is parsable.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
Essentially a V2 of
https://www.redhat.com/archives/libvir-list/2018-March/msg01120.html
It takes a slightly different approach by creating a function that can parse host names or IP addresses.
src/libvirt_private.syms | 1 + src/rpc/virnetsocket.c | 2 +- src/util/virsocketaddr.c | 50 +++++++++++++++++++++++++++++++++++++++++++++--- src/util/virsocketaddr.h | 5 +++++ 4 files changed, 54 insertions(+), 4 deletions(-)
Reviewed-by: John Ferlan <jferlan@redhat.com>
Wait for 4.2.0 for this one...
John
BTW: Your call on whether to add to the new API comments something about the API could be susceptible to a delay due to network name resolution lookup pause. That is, from the getaddrinfo man page:
"The AI_NUMERICHOST flag suppresses any potentially lengthy network host address lookups."
Good point. I squashed in the below comment to this patch before pushing both. Regards, Jim diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 84610560f..99dc54830 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -173,7 +173,10 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) * * Mostly a wrapper for getaddrinfo() extracting the address storage * from a host name like acme.example.com or a numeric string like 1.2.3.4 - * or 2001:db8:85a3:0:0:8a2e:370:7334 + * or 2001:db8:85a3:0:0:8a2e:370:7334. + * + * When @val is a network host name, this function may be susceptible to a + * delay due to potentially lengthy netork host address lookups. * * Returns the length of the network address or -1 in case of error. */

On 04/05/2018 02:55 PM, Jim Fehlig wrote:
On 03/29/2018 11:27 AM, John Ferlan wrote:
On 03/26/2018 04:29 PM, Jim Fehlig wrote:
When preparing for migration, the libxl driver creates a new TCP listen socket for the incoming migration by calling virNetSocketNewListenTCP, passing the destination host name. virNetSocketNewListenTCP calls virSocketAddrParse to check if the host name is a wildcard address, in which case it avoids adding the AI_ADDRCONFIG flag to the hints passed to getaddrinfo. If the host name is not an IP address, virSocketAddrParse reports an error
error : virSocketAddrParseInternal:121 : Cannot parse socket address 'myhost.example.com': Name or service not known
But virNetSocketNewListenTCP succeeds regardless and the overall migration operation succeeds.
Introduce virSocketAddrParseAny and use it when simply testing if a host name/addr is parsable.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
Essentially a V2 of
https://www.redhat.com/archives/libvir-list/2018-March/msg01120.html
It takes a slightly different approach by creating a function that can parse host names or IP addresses.
src/libvirt_private.syms | 1 + src/rpc/virnetsocket.c | 2 +- src/util/virsocketaddr.c | 50 +++++++++++++++++++++++++++++++++++++++++++++--- src/util/virsocketaddr.h | 5 +++++ 4 files changed, 54 insertions(+), 4 deletions(-)
Reviewed-by: John Ferlan <jferlan@redhat.com>
Wait for 4.2.0 for this one...
John
BTW: Your call on whether to add to the new API comments something about the API could be susceptible to a delay due to network name resolution lookup pause. That is, from the getaddrinfo man page:
"The AI_NUMERICHOST flag suppresses any potentially lengthy network host address lookups."
Good point. I squashed in the below comment to this patch before pushing both.
Regards, Jim
diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 84610560f..99dc54830 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -173,7 +173,10 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) * * Mostly a wrapper for getaddrinfo() extracting the address storage * from a host name like acme.example.com or a numeric string like 1.2.3.4 - * or 2001:db8:85a3:0:0:8a2e:370:7334 + * or 2001:db8:85a3:0:0:8a2e:370:7334. + * + * When @val is a network host name, this function may be susceptible to a + * delay due to potentially lengthy netork host address lookups.
Heh, only now did I notice the misspelling of 'network'. I'll push a trivial followup. Regards, Jim
participants (2)
-
Jim Fehlig
-
John Ferlan