]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Expand virSocketFormat to be more flexible
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 20 Oct 2010 14:13:00 +0000 (15:13 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 22 Oct 2010 10:24:12 +0000 (11:24 +0100)
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
src/conf/domain_conf.c
src/libvirt_private.syms
src/nwfilter/nwfilter_ebiptables_driver.c
src/qemu/qemu_conf.c
src/util/network.c
src/util/network.h

index e30fea02696f43f52f49d796e8b44e12897e1677..60ba68b95c2ffc4a9df09c95214717d4dcfa454f 100644 (file)
@@ -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
index 53c8d0940a3d8f9a96a07ba2a3e3ed808c318cc3..945c1f4a3704e36114a8e342cec719896ccaf4fa 100644 (file)
@@ -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);
index edfb254f645a005b2fa7d5995add5777b9abea4e..1a71e79b8e50e7fd7dcc0d8b0575eac50f7046cb 100644 (file)
@@ -501,6 +501,7 @@ virReallocN;
 virSocketAddrIsNetmask;
 virSocketCheckNetmask;
 virSocketFormatAddr;
+virSocketFormatAddrFull;
 virSocketGetPort;
 virSocketGetRange;
 virSocketParseAddr;
index caa37cba79e7f4a3393d8eecd062513b804720da..21b1b5122b6734d0299f30c5e9f988f3cca216f4 100644 (file)
@@ -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",
index 67195784da2a501c0855c1a51a257fbb0868440e..e2c67a31a3361187dc37eab51d0f8267be7e7fac 100644 (file)
@@ -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");
index de22ded6b88b1cc4660c5bb9c943720c07ac1ffa..0c7cb633561c5283d4840caf3891294a6d5b3564 100644 (file)
 
 #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;
-    }
+/*
+ * virSocketFormatAddrFull:
+ * @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
index ef92c9b38dfe2b9acc48b6f8677a93f32054ff34..5147ea522774574bd2e42d418f28c1b94f789389 100644 (file)
 # 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);