[libvirt] [PATCH 06/11] Expand virSocketFormat to be more flexible

Daniel P. Berrange berrange at redhat.com
Thu Oct 21 18:17:20 UTC 2010


The getnameinfo() function is more flexible than inet_ntop()
avoiding the need to if/else the code based on socket family.
Also make it support UNIX socket addrs and allow inclusion
of a port (service) address. Finally do proper error reporting
via normal APIs.

* src/conf/domain_conf.c, src/nwfilter/nwfilter_ebiptables_driver.c,
  src/qemu/qemu_conf.c: Fix error handling with virSocketFormat
* src/util/network.c: Rewrite virSocketFormat to use getnameinfo
  and cope with UNIX socket addrs.
---
 po/POTFILES.in                            |    1 +
 src/conf/domain_conf.c                    |    5 +--
 src/libvirt_private.syms                  |    1 +
 src/nwfilter/nwfilter_ebiptables_driver.c |   12 +----
 src/qemu/qemu_conf.c                      |    2 +
 src/util/network.c                        |   82 ++++++++++++++++++++++-------
 src/util/network.h                        |    5 ++
 7 files changed, 75 insertions(+), 33 deletions(-)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index e30fea0..60ba68b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -83,6 +83,7 @@ src/util/hostusb.c
 src/util/interface.c
 src/util/json.c
 src/util/macvtap.c
+src/util/network.c
 src/util/pci.c
 src/util/processinfo.c
 src/util/stats_linux.c
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 53c8d09..945c1f4 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5960,11 +5960,8 @@ virDomainChrDefFormat(virBufferPtr buf,
             }
 
             const char *addr = virSocketFormatAddr(def->target.addr);
-            if (addr == NULL) {
-                virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                     _("Unable to format guestfwd address"));
+            if (addr == NULL)
                 return -1;
-            }
 
             virBufferVSprintf(buf, " address='%s' port='%d'",
                               addr, port);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0b1c482..5c7f929 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -485,6 +485,7 @@ virFree;
 virSocketAddrIsNetmask;
 virSocketCheckNetmask;
 virSocketFormatAddr;
+virSocketFormatAddrFull;
 virSocketGetPort;
 virSocketGetRange;
 virSocketParseAddr;
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index caa37cb..21b1b51 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -190,12 +190,8 @@ _printDataType(virNWFilterHashTablePtr vars,
     switch (item->datatype) {
     case DATATYPE_IPADDR:
         data = virSocketFormatAddr(&item->u.ipaddr);
-        if (!data) {
-            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                   _("internal IPv4 address representation "
-                                     "is bad"));
+        if (!data)
             return 1;
-        }
         if (snprintf(buf, bufsize, "%s", data) >= bufsize) {
             virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                    _("buffer too small for IP address"));
@@ -207,12 +203,8 @@ _printDataType(virNWFilterHashTablePtr vars,
 
     case DATATYPE_IPV6ADDR:
         data = virSocketFormatAddr(&item->u.ipaddr);
-        if (!data) {
-            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                   _("internal IPv6 address representation "
-                                     "is bad"));
+        if (!data)
             return 1;
-        }
 
         if (snprintf(buf, bufsize, "%s", data) >= bufsize) {
             virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 6719578..e2c67a3 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -4727,6 +4727,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
             ADD_ARG(devstr);
 
             char *addr = virSocketFormatAddr(channel->target.addr);
+            if (!addr)
+                goto error;
             int port = virSocketGetPort(channel->target.addr);
 
             ADD_ARG_LIT("-netdev");
diff --git a/src/util/network.c b/src/util/network.c
index de22ded..7c6ced9 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -13,6 +13,13 @@
 
 #include "memory.h"
 #include "network.h"
+#include "util.h"
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+#define virSocketError(code, ...)                                       \
+    virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__,           \
+                         __FUNCTION__, __LINE__, __VA_ARGS__)
 
 /*
  * Helpers to extract the IP arrays from the virSocketAddrPtr
@@ -129,38 +136,75 @@ virSocketParseIpv6Addr(const char *val, virSocketAddrPtr addr) {
  */
 char *
 virSocketFormatAddr(virSocketAddrPtr addr) {
-    char   *out;
-    size_t outlen;
-    void   *inaddr;
+    return virSocketFormatAddrFull(addr, false, NULL);
+}
 
-    if (addr == NULL)
-        return NULL;
 
-    if (addr->data.stor.ss_family == AF_INET) {
-        outlen = INET_ADDRSTRLEN;
-        inaddr = &addr->data.inet4.sin_addr;
-    }
+/*
+ * virSocketFormatAddr:
+ * @addr: an initialized virSocketAddrPtr
+ * @withService: if true, then service info is appended
+ * @separator: separator between hostname & service.
+ *
+ * Returns a string representation of the given address
+ * Returns NULL on any error
+ * Caller must free the returned string
+ */
+char *
+virSocketFormatAddrFull(virSocketAddrPtr addr,
+                        bool withService,
+                        const char *separator)
+{
+    char host[NI_MAXHOST], port[NI_MAXSERV];
+    char *addrstr;
+    int err;
 
-    else if (addr->data.stor.ss_family == AF_INET6) {
-        outlen = INET6_ADDRSTRLEN;
-        inaddr = &addr->data.inet6.sin6_addr;
+    if (addr == NULL) {
+        virSocketError(VIR_ERR_INVALID_ARG, _("Missing address"));
+        return NULL;
     }
 
-    else {
-        return NULL;
+    /* Short-circuit since getnameinfo doesn't work
+     * nicely for UNIX sockets */
+    if (addr->data.sa.sa_family == AF_UNIX) {
+        if (withService) {
+            if (virAsprintf(&addrstr, "127.0.0.1%s0",
+                            separator ? separator : ":") < 0)
+                goto no_memory;
+        } else {
+            if (!(addrstr = strdup("127.0.0.1")))
+                goto no_memory;
+        }
+        return addrstr;
     }
 
-    if (VIR_ALLOC_N(out, outlen) < 0)
+    if ((err = getnameinfo(&addr->data.sa,
+                           addr->len,
+                           host, sizeof(host),
+                           port, sizeof(port),
+                           NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
+        virSocketError(VIR_ERR_SYSTEM_ERROR,
+                       _("Cannot convert socket address to string: %s"),
+                       gai_strerror(err));
         return NULL;
+    }
 
-    if (inet_ntop(addr->data.stor.ss_family, inaddr, out, outlen) == NULL) {
-        VIR_FREE(out);
-        return NULL;
+    if (withService) {
+        if (virAsprintf(&addrstr, "%s%s%s", host, separator, port) == -1)
+            goto no_memory;
+    } else {
+        if (!(addrstr = strdup(host)))
+            goto no_memory;
     }
 
-    return out;
+    return addrstr;
+
+no_memory:
+    virReportOOMError();
+    return NULL;
 }
 
+
 /*
  * virSocketSetPort:
  * @addr: an initialized virSocketAddrPtr
diff --git a/src/util/network.h b/src/util/network.h
index ef92c9b..5147ea5 100644
--- a/src/util/network.h
+++ b/src/util/network.h
@@ -16,9 +16,11 @@
 # include <sys/types.h>
 # include <sys/socket.h>
 # include <netdb.h>
+# include <stdbool.h>
 
 typedef struct {
     union {
+        struct sockaddr sa;
         struct sockaddr_storage stor;
         struct sockaddr_in inet4;
         struct sockaddr_in6 inet6;
@@ -39,6 +41,9 @@ int virSocketParseIpv6Addr(const char *val,
                            virSocketAddrPtr addr);
 
 char * virSocketFormatAddr(virSocketAddrPtr addr);
+char * virSocketFormatAddrFull(virSocketAddrPtr addr,
+                               bool withService,
+                               const char *separator);
 
 int virSocketSetPort(virSocketAddrPtr addr, int port);
 
-- 
1.7.2.3




More information about the libvir-list mailing list