util: add API for resolving socket service names

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 <jtomko@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2019-06-24 11:26:28 +01:00
parent 836f4e0659
commit 012e0d40bf
3 changed files with 54 additions and 0 deletions

View File

@ -2903,6 +2903,7 @@ virSocketAddrParseIPv4;
virSocketAddrParseIPv6;
virSocketAddrPrefixToNetmask;
virSocketAddrPTRDomain;
virSocketAddrResolveService;
virSocketAddrSetIPv4Addr;
virSocketAddrSetIPv4AddrNetOrder;
virSocketAddrSetIPv6Addr;

View File

@ -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

View File

@ -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]);