The getservent() APIs are not re-entrant safe so cannot be used in any threaded program. Add a wrapper around getaddrinfo() for resolving the service names to a port number. Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- src/libvirt_private.syms | 1 + src/util/virsocketaddr.c | 51 ++++++++++++++++++++++++++++++++++++++++ src/util/virsocketaddr.h | 2 ++ 3 files changed, 54 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ce614e04bd..1adf735a38 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2919,6 +2919,7 @@ virSocketAddrParseIPv4; virSocketAddrParseIPv6; virSocketAddrPrefixToNetmask; virSocketAddrPTRDomain; +virSocketAddrResolveService; virSocketAddrSetIPv4Addr; virSocketAddrSetIPv4AddrNetOrder; virSocketAddrSetIPv6Addr; diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 7a50cbe040..790bc0ebec 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -235,6 +235,57 @@ virSocketAddrParseIPv6(virSocketAddrPtr addr, const char *val) return virSocketAddrParse(addr, val, AF_INET6); } +/** + * virSocketAddrResolveService: + * @service: a service name or port number + * + * Resolve a service, which might be a plain port or service name, + * into a port number for IPv4/IPv6 usage + * + * Returns a numberic port number + */ +int virSocketAddrResolveService(const char *service) +{ + struct addrinfo *res, *tmp; + struct addrinfo hints; + int err; + int port = -1; + + memset(&hints, 0, sizeof(hints)); + + if ((err = getaddrinfo(NULL, service, &hints, &res)) != 0) { + virReportError(VIR_ERR_SYSTEM_ERROR, + _("Cannot parse socket service '%s': %s"), + service, gai_strerror(err)); + return -1; + } + + tmp = res; + while (tmp) { + if (tmp->ai_family == AF_INET) { + struct sockaddr_in in; + memcpy(&in, tmp->ai_addr, sizeof(in)); + port = in.sin_port; + goto cleanup; + } else if (tmp->ai_family == AF_INET6) { + struct sockaddr_in6 in; + memcpy(&in, tmp->ai_addr, sizeof(in)); + port = in.sin6_port; + goto cleanup; + } + tmp++; + } + + virReportError(VIR_ERR_SYSTEM_ERROR, + _("No matches for socket service '%s': %s"), + service, gai_strerror(err)); + + cleanup: + freeaddrinfo(res); + + return port; +} + /* * virSocketAddrSetIPv4AddrNetOrder: * @addr: the location to store the result diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h index 9dbd8caa0d..bb97e6e3a0 100644 --- a/src/util/virsocketaddr.h +++ b/src/util/virsocketaddr.h @@ -98,6 +98,8 @@ int virSocketAddrParseIPv4(virSocketAddrPtr addr, int virSocketAddrParseIPv6(virSocketAddrPtr addr, const char *val); +int virSocketAddrResolveService(const char *service); + void virSocketAddrSetIPv4AddrNetOrder(virSocketAddrPtr s, uint32_t addr); void virSocketAddrSetIPv4Addr(virSocketAddrPtr s, uint32_t addr); void virSocketAddrSetIPv6AddrNetOrder(virSocketAddrPtr s, uint32_t addr[4]); -- 2.21.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list