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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list