mirror of https://gitee.com/openkylin/libvirt.git
Expand virSocketFormat to be more flexible
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.
This commit is contained in:
parent
7ab7d17bfb
commit
497adba2d4
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -501,6 +501,7 @@ virReallocN;
|
|||
virSocketAddrIsNetmask;
|
||||
virSocketCheckNetmask;
|
||||
virSocketFormatAddr;
|
||||
virSocketFormatAddrFull;
|
||||
virSocketGetPort;
|
||||
virSocketGetRange;
|
||||
virSocketParseAddr;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
||||
if (addr == NULL)
|
||||
return NULL;
|
||||
|
||||
if (addr->data.stor.ss_family == AF_INET) {
|
||||
outlen = INET_ADDRSTRLEN;
|
||||
inaddr = &addr->data.inet4.sin_addr;
|
||||
}
|
||||
|
||||
else if (addr->data.stor.ss_family == AF_INET6) {
|
||||
outlen = INET6_ADDRSTRLEN;
|
||||
inaddr = &addr->data.inet6.sin6_addr;
|
||||
}
|
||||
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (VIR_ALLOC_N(out, outlen) < 0)
|
||||
return NULL;
|
||||
|
||||
if (inet_ntop(addr->data.stor.ss_family, inaddr, out, outlen) == NULL) {
|
||||
VIR_FREE(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return out;
|
||||
return virSocketFormatAddrFull(addr, false, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
if (addr == NULL) {
|
||||
virSocketError(VIR_ERR_INVALID_ARG, _("Missing address"));
|
||||
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 ((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 (withService) {
|
||||
if (virAsprintf(&addrstr, "%s%s%s", host, separator, port) == -1)
|
||||
goto no_memory;
|
||||
} else {
|
||||
if (!(addrstr = strdup(host)))
|
||||
goto no_memory;
|
||||
}
|
||||
|
||||
return addrstr;
|
||||
|
||||
no_memory:
|
||||
virReportOOMError();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* virSocketSetPort:
|
||||
* @addr: an initialized virSocketAddrPtr
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue