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