util: introduce virSocketAddrParseAny

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>
Reviewed-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
Jim Fehlig 2018-03-26 12:53:05 -06:00
parent 0987730301
commit 412afdb8f4
4 changed files with 57 additions and 4 deletions

View File

@ -2731,6 +2731,7 @@ virSocketAddrMask;
virSocketAddrMaskByPrefix; virSocketAddrMaskByPrefix;
virSocketAddrNumericFamily; virSocketAddrNumericFamily;
virSocketAddrParse; virSocketAddrParse;
virSocketAddrParseAny;
virSocketAddrParseIPv4; virSocketAddrParseIPv4;
virSocketAddrParseIPv6; virSocketAddrParseIPv6;
virSocketAddrPrefixToNetmask; virSocketAddrPrefixToNetmask;

View File

@ -333,7 +333,7 @@ int virNetSocketNewListenTCP(const char *nodename,
* startup in most cases. * startup in most cases.
*/ */
if (nodename && if (nodename &&
!(virSocketAddrParse(&tmp_addr, nodename, AF_UNSPEC) > 0 && !(virSocketAddrParseAny(&tmp_addr, nodename, AF_UNSPEC, false) > 0 &&
virSocketAddrIsWildcard(&tmp_addr))) virSocketAddrIsWildcard(&tmp_addr)))
hints.ai_flags |= AI_ADDRCONFIG; hints.ai_flags |= AI_ADDRCONFIG;

View File

@ -101,6 +101,7 @@ static int
virSocketAddrParseInternal(struct addrinfo **res, virSocketAddrParseInternal(struct addrinfo **res,
const char *val, const char *val,
int family, int family,
int ai_flags,
bool reportError) bool reportError)
{ {
struct addrinfo hints; struct addrinfo hints;
@ -114,7 +115,7 @@ virSocketAddrParseInternal(struct addrinfo **res,
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = family; hints.ai_family = family;
hints.ai_flags = AI_NUMERICHOST; hints.ai_flags = ai_flags;
if ((err = getaddrinfo(val, NULL, &hints, res)) != 0) { if ((err = getaddrinfo(val, NULL, &hints, res)) != 0) {
if (reportError) if (reportError)
virReportError(VIR_ERR_SYSTEM_ERROR, virReportError(VIR_ERR_SYSTEM_ERROR,
@ -143,7 +144,7 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family)
int len; int len;
struct addrinfo *res; struct addrinfo *res;
if (virSocketAddrParseInternal(&res, val, family, true) < 0) if (virSocketAddrParseInternal(&res, val, family, AI_NUMERICHOST, true) < 0)
return -1; return -1;
if (res == NULL) { if (res == NULL) {
@ -163,6 +164,52 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family)
return len; 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.
*
* 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.
*/
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: * virSocketAddrParseIPv4:
* @val: an IPv4 numeric address * @val: an IPv4 numeric address
@ -1105,7 +1152,7 @@ virSocketAddrNumericFamily(const char *address)
struct addrinfo *res; struct addrinfo *res;
unsigned short family; unsigned short family;
if (virSocketAddrParseInternal(&res, address, AF_UNSPEC, false) < 0) if (virSocketAddrParseInternal(&res, address, AF_UNSPEC, AI_NUMERICHOST, false) < 0)
return -1; return -1;
family = res->ai_addr->sa_family; family = res->ai_addr->sa_family;

View File

@ -92,6 +92,11 @@ int virSocketAddrParse(virSocketAddrPtr addr,
const char *val, const char *val,
int family); int family);
int virSocketAddrParseAny(virSocketAddrPtr addr,
const char *val,
int family,
bool reportError);
int virSocketAddrParseIPv4(virSocketAddrPtr addr, int virSocketAddrParseIPv4(virSocketAddrPtr addr,
const char *val); const char *val);