From 012e0d40bf9f71513cbf2a221e59b777b6c68046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Mon, 24 Jun 2019 11:26:28 +0100 Subject: [PATCH] util: add API for resolving socket service names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. Reviewed-by: Ján Tomko Signed-off-by: Daniel P. Berrangé --- 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 e226b85121..02d5b7acce 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2903,6 +2903,7 @@ virSocketAddrParseIPv4; virSocketAddrParseIPv6; virSocketAddrPrefixToNetmask; virSocketAddrPTRDomain; +virSocketAddrResolveService; virSocketAddrSetIPv4Addr; virSocketAddrSetIPv4AddrNetOrder; virSocketAddrSetIPv6Addr; diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index f961b413d3..c1fd5ec3d2 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 numeric port number, or -1 on error + */ +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]); -- GitLab