diff options
author | xiaoqiang zhao <zxq_yx_007@163.com> | 2020-05-16 11:13:25 +0800 |
---|---|---|
committer | Daniel P. Berrangé <berrange@redhat.com> | 2020-05-20 10:34:40 +0100 |
commit | 776b97d3605ed0fc94443048fdf988c7725e38a9 (patch) | |
tree | 2d8f731e49c1900ccb7c7f4e1e63d6a9c3590125 /util/qemu-sockets.c | |
parent | f2465433b43fb87766d79f42191607dac4aed5b4 (diff) |
qemu-sockets: add abstract UNIX domain socket support
unix_listen/connect_saddr now support abstract address types
two aditional BOOL switches are introduced:
tight: whether to set @addrlen to the minimal string length,
or the maximum sun_path length. default is TRUE
abstract: whether we use abstract address. default is FALSE
cli example:
-monitor unix:/tmp/unix.socket,abstract,tight=off
OR
-chardev socket,path=/tmp/unix.socket,id=unix1,abstract,tight=on
Signed-off-by: xiaoqiang zhao <zxq_yx_007@163.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Diffstat (limited to 'util/qemu-sockets.c')
-rw-r--r-- | util/qemu-sockets.c | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 86c48b9fa5..b37d288866 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -863,6 +863,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, char *pathbuf = NULL; const char *path; size_t pathlen; + size_t addrlen; sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { @@ -879,9 +880,11 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, } pathlen = strlen(path); - if (pathlen > sizeof(un.sun_path)) { + if (pathlen > sizeof(un.sun_path) || + (saddr->abstract && pathlen > (sizeof(un.sun_path) - 1))) { error_setg(errp, "UNIX socket path '%s' is too long", path); error_append_hint(errp, "Path must be less than %zu bytes\n", + saddr->abstract ? sizeof(un.sun_path) - 1 : sizeof(un.sun_path)); goto err; } @@ -903,7 +906,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, close(fd); } - if (unlink(path) < 0 && errno != ENOENT) { + if (!saddr->abstract && unlink(path) < 0 && errno != ENOENT) { error_setg_errno(errp, errno, "Failed to unlink socket %s", path); goto err; @@ -911,9 +914,19 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; - memcpy(un.sun_path, path, pathlen); + addrlen = sizeof(un); - if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { + if (saddr->abstract) { + un.sun_path[0] = '\0'; + memcpy(&un.sun_path[1], path, pathlen); + if (saddr->tight) { + addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen; + } + } else { + memcpy(un.sun_path, path, pathlen); + } + + if (bind(sock, (struct sockaddr *) &un, addrlen) < 0) { error_setg_errno(errp, errno, "Failed to bind socket to %s", path); goto err; } @@ -936,6 +949,7 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) struct sockaddr_un un; int sock, rc; size_t pathlen; + size_t addrlen; if (saddr->path == NULL) { error_setg(errp, "unix connect: no path specified"); @@ -949,21 +963,32 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) } pathlen = strlen(saddr->path); - if (pathlen > sizeof(un.sun_path)) { + if (pathlen > sizeof(un.sun_path) || + (saddr->abstract && pathlen > (sizeof(un.sun_path) - 1))) { error_setg(errp, "UNIX socket path '%s' is too long", saddr->path); error_append_hint(errp, "Path must be less than %zu bytes\n", + saddr->abstract ? sizeof(un.sun_path) - 1 : sizeof(un.sun_path)); goto err; } memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; - memcpy(un.sun_path, saddr->path, pathlen); + addrlen = sizeof(un); + if (saddr->abstract) { + un.sun_path[0] = '\0'; + memcpy(&un.sun_path[1], saddr->path, pathlen); + if (saddr->tight) { + addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen; + } + } else { + memcpy(un.sun_path, saddr->path, pathlen); + } /* connect to peer */ do { rc = 0; - if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { + if (connect(sock, (struct sockaddr *) &un, addrlen) < 0) { rc = -errno; } } while (rc == -EINTR); |