On 03/19/2018 07:28 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 virSocketAddrParseQuiet and use it when simply testing if a host > name/addr is parsable. > > Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx> > --- > > A brute-force hack that also works is to remove AI_NUMERICHOST flag from > hints in virSocketAddrParseInternal, but I'm not sure what sort of havoc > that would wreak Perhaps rather than quiet/verbose flag - maybe ParseInternal should add a new parameter "ai_flags"? Then add virSocketAddrParseName which would pass 0 instead of AI_NUMERICHOST and expect to parse the name. FWIW, I have a faint recollection of some issue with getaddrinfo and dns delays on lookups when looking up by name. Been a while since I've had to think about that though, so I could be wrong as the memory fades/ages. You could also search on some other direct callers of getaddrinfo in libvirt sources - there's some interesting uses.. I also note (ironically) that if @addr == NULL, then error is splatted in ParseInternal regardless of @reportError value. > > Perhaps I should ask the obvious question first: Is virSocketAddrParse > expected to work with a host name? I suspec there are other callers that > could pass a name as well as a numeric IP addr, depending on URI provided > by user. Seems to me some comments [1] answer your question. There's a virSocketAddrNumericFamily - maybe that'll help you in deciding how to formulate things... Seems to be used by a few places already to determine whether one has a name or number (including the qemu migration path). FWIW: I also note callers to virSocketAddrNumericFamily don't necessarily handle the possible -1 return possibly... Looks like you're jumping into one of rabbit holes Laine usually falls into ;-) > > src/libvirt_private.syms | 1 + > src/rpc/virnetsocket.c | 2 +- > src/util/virsocketaddr.c | 60 +++++++++++++++++++++++++++++++++++------------- > src/util/virsocketaddr.h | 4 ++++ > 4 files changed, 50 insertions(+), 17 deletions(-) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index c3e4fd23d..acacbaeb1 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -2726,6 +2726,7 @@ virSocketAddrNumericFamily; > virSocketAddrParse; > virSocketAddrParseIPv4; > virSocketAddrParseIPv6; > +virSocketAddrParseQuiet; > virSocketAddrPrefixToNetmask; > virSocketAddrPTRDomain; > virSocketAddrSetIPv4Addr; > diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c > index 2d41a716b..07166ecc9 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 && > + !(virSocketAddrParseQuiet(&tmp_addr, nodename, AF_UNSPEC) > 0 && > virSocketAddrIsWildcard(&tmp_addr))) > hints.ai_flags |= AI_ADDRCONFIG; > > diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c > index 95b527436..711c634e8 100644 > --- a/src/util/virsocketaddr.c > +++ b/src/util/virsocketaddr.c > @@ -126,29 +126,24 @@ virSocketAddrParseInternal(struct addrinfo **res, > return 0; > } > > -/** > - * virSocketAddrParse: > - * @val: a numeric network address IPv4 or IPv6 > - * @addr: where to store the return value, optional. > - * @family: address family to pass down to getaddrinfo > - * > - * Mostly a wrapper for getaddrinfo() extracting the address storage > - * from the numeric string like 1.2.3.4 or 2001:db8:85a3:0:0:8a2e:370:7334 > - * [1] > - * Returns the length of the network address or -1 in case of error. > - */ > -int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) > +static int > +virSockAddrParseVerbose(virSocketAddrPtr addr, > + const char *val, > + int family, > + bool verbose) Could have gone with reportError like ParseInternal. John > { > int len; > struct addrinfo *res; > > - if (virSocketAddrParseInternal(&res, val, family, true) < 0) > + if (virSocketAddrParseInternal(&res, val, family, verbose) < 0) > return -1; > > if (res == NULL) { > - virReportError(VIR_ERR_SYSTEM_ERROR, > - _("No socket addresses found for '%s'"), > - val); > + if (verbose) { > + virReportError(VIR_ERR_SYSTEM_ERROR, > + _("No socket addresses found for '%s'"), > + val); > + } > return -1; > } > > @@ -162,6 +157,39 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) > return len; > } > > + > +/** > + * virSocketAddrParse: > + * @val: a numeric network address IPv4 or IPv6 > + * @addr: where to store the return value, optional. > + * @family: address family to pass down to getaddrinfo > + * > + * Mostly a wrapper for getaddrinfo() extracting the address storage > + * from the 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 virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) > +{ > + return virSockAddrParseVerbose(addr, val, family, true); > +} > + > +/** > + * virSocketAddrParseQuiet: > + * @val: a numeric network address IPv4 or IPv6 > + * @addr: where to store the return value, optional. > + * @family: address family to pass down to getaddrinfo > + * > + * A quiet version of virSocketAddrParse. No errors are reported in > + * error paths. > + * > + * Returns the length of the network address or -1 in case of error. > + */ > +int virSocketAddrParseQuiet(virSocketAddrPtr addr, const char *val, int family) > +{ > + return virSockAddrParseVerbose(addr, val, family, false); > +} > + > /* > * virSocketAddrParseIPv4: > * @val: an IPv4 numeric address > diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h > index 80e792618..99bb7a949 100644 > --- a/src/util/virsocketaddr.h > +++ b/src/util/virsocketaddr.h > @@ -92,6 +92,10 @@ int virSocketAddrParse(virSocketAddrPtr addr, > const char *val, > int family); > > +int virSocketAddrParseQuiet(virSocketAddrPtr addr, > + const char *val, > + int family); > + > int virSocketAddrParseIPv4(virSocketAddrPtr addr, > const char *val); > > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list