]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
util: add API for resolving socket service names
authorDaniel P. Berrangé <berrange@redhat.com>
Mon, 24 Jun 2019 10:26:28 +0000 (11:26 +0100)
committerDaniel P. Berrangé <berrange@redhat.com>
Thu, 11 Jul 2019 13:13:03 +0000 (14:13 +0100)
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>
src/libvirt_private.syms
src/util/virsocketaddr.c
src/util/virsocketaddr.h

index e226b85121980b5f83b99954bffb2bc4235b5267..02d5b7acce0240352d9019d84ca2a1f021054dd8 100644 (file)
@@ -2903,6 +2903,7 @@ virSocketAddrParseIPv4;
 virSocketAddrParseIPv6;
 virSocketAddrPrefixToNetmask;
 virSocketAddrPTRDomain;
+virSocketAddrResolveService;
 virSocketAddrSetIPv4Addr;
 virSocketAddrSetIPv4AddrNetOrder;
 virSocketAddrSetIPv6Addr;
index f961b413d33aa65b4af95b7bc0e6370bafc1f791..c1fd5ec3d2925fdd73ed75c8d3900d93055dd47c 100644 (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
index 9dbd8caa0d747d8c0ddd71de934809011c65e98f..bb97e6e3a0a4a596693991860b85a1c331bc1b65 100644 (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]);