passt/qemu/0001-net-Allow-also-UNIX-domain-sockets-to-be-used-as-net.patch
Stefano Brivio 087b5f4dbb LICENSES: Add license text files, add missing notices, fix SPDX tags
SPDX tags don't replace license files. Some notices were missing and
some tags were not according to the SPDX specification, too.

Now reuse --lint from the REUSE tool (https://reuse.software/) passes.

Reported-by: Martin Hauke <mardnh@gmx.de>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
2021-10-20 08:29:30 +02:00

198 lines
6.7 KiB
Diff

From ba51349d353f11e05c6341a7e065f2ade3874c68 Mon Sep 17 00:00:00 2001
Message-Id: <ba51349d353f11e05c6341a7e065f2ade3874c68.1619091389.git.sbrivio@redhat.com>
From: Stefano Brivio <sbrivio@redhat.com>
Date: Wed, 21 Apr 2021 18:51:18 +0200
Subject: [PATCH 1/2] net: Allow also UNIX domain sockets to be used as -netdev
socket
It has lower overhead compared to TCP, doesn't need a free port
and the adaptation is trivial.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
SPDX-FileCopyrightText: 2020-2021 Red Hat GmbH <sbrivio@redhat.com>
SPDX-License-Identifier: AGPL-3.0-or-later
net/socket.c | 106 ++++++++++++++++++++++++++++++++++++++++--------
qemu-options.hx | 12 +++---
2 files changed, 94 insertions(+), 24 deletions(-)
diff --git a/net/socket.c b/net/socket.c
index 15b410e8d825..aadd11dae2b3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -511,26 +511,60 @@ static int net_socket_listen_init(NetClientState *peer,
{
NetClientState *nc;
NetSocketState *s;
- struct sockaddr_in saddr;
- int fd, ret;
+ struct sockaddr_storage saddr;
+ struct sockaddr_in *saddr_in = (struct sockaddr_in *)&saddr;
+ struct sockaddr_un *saddr_un = (struct sockaddr_un *)&saddr;
+ size_t saddr_size;
+ int fd, ret, pf;
+
+#ifndef WIN32
+ if (strchr(host_str, ':')) {
+#endif
+ if (parse_host_port(saddr_in, host_str, errp) < 0)
+ return -1;
- if (parse_host_port(&saddr, host_str, errp) < 0) {
- return -1;
+ pf = PF_INET;
+ saddr_size = sizeof(*saddr_in);
+#ifndef WIN32
+ } else {
+ struct stat sb;
+
+ if (stat(host_str, &sb) == -1) {
+ error_setg_errno(errp, errno, "can't stat socket path");
+ return -1;
+ }
+
+ if ((sb.st_mode & S_IFMT) != S_IFSOCK) {
+ error_setg_errno(errp, errno, "path provided is not a socket");
+ return -1;
+ }
+
+ saddr_un->sun_family = PF_UNIX;
+ strncpy(saddr_un->sun_path, host_str, sizeof(saddr_un->sun_path));
+
+ pf = PF_UNIX;
+ saddr_size = sizeof(*saddr_un);
}
+#endif /* !WIN32 */
- fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
+ fd = qemu_socket(pf, SOCK_STREAM, 0);
if (fd < 0) {
error_setg_errno(errp, errno, "can't create stream socket");
return -1;
}
qemu_set_nonblock(fd);
- socket_set_fast_reuse(fd);
+ if (pf == PF_INET)
+ socket_set_fast_reuse(fd);
- ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
+ ret = bind(fd, (struct sockaddr *)&saddr, saddr_size);
if (ret < 0) {
- error_setg_errno(errp, errno, "can't bind ip=%s to socket",
- inet_ntoa(saddr.sin_addr));
+ if (pf == PF_INET)
+ error_setg_errno(errp, errno, "can't bind ip=%s to socket",
+ inet_ntoa(saddr_in->sin_addr));
+ else if (pf == PF_UNIX)
+ error_setg_errno(errp, errno, "can't create socket with path: %s",
+ host_str);
closesocket(fd);
return -1;
}
@@ -559,14 +593,44 @@ static int net_socket_connect_init(NetClientState *peer,
Error **errp)
{
NetSocketState *s;
- int fd, connected, ret;
- struct sockaddr_in saddr;
+ int fd, connected, ret, pf;
+ struct sockaddr_storage saddr;
+ size_t saddr_size;
+ struct sockaddr_in *saddr_in = (struct sockaddr_in *)&saddr;
+#ifndef WIN32
+ struct sockaddr_un *saddr_un = (struct sockaddr_un *)&saddr;
- if (parse_host_port(&saddr, host_str, errp) < 0) {
- return -1;
+
+ if (strchr(host_str, ':')) {
+#endif
+ if (parse_host_port(saddr_in, host_str, errp) < 0)
+ return -1;
+
+ pf = PF_INET;
+ saddr_size = sizeof(*saddr_in);
+#ifndef WIN32
+ } else {
+ struct stat sb;
+
+ if (stat(host_str, &sb) == -1) {
+ error_setg_errno(errp, errno, "can't stat socket path");
+ return -1;
+ }
+
+ if ((sb.st_mode & S_IFMT) != S_IFSOCK) {
+ error_setg_errno(errp, errno, "provided path is not a socket");
+ return -1;
+ }
+
+ saddr_un->sun_family = PF_UNIX;
+ strncpy(saddr_un->sun_path, host_str, sizeof(saddr_un->sun_path));
+
+ pf = PF_UNIX;
+ saddr_size = sizeof(*saddr_un);
}
+#endif /* !WIN32 */
- fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
+ fd = qemu_socket(pf, SOCK_STREAM, 0);
if (fd < 0) {
error_setg_errno(errp, errno, "can't create stream socket");
return -1;
@@ -575,7 +639,7 @@ static int net_socket_connect_init(NetClientState *peer,
connected = 0;
for(;;) {
- ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
+ ret = connect(fd, (struct sockaddr *)&saddr, saddr_size);
if (ret < 0) {
if (errno == EINTR || errno == EWOULDBLOCK) {
/* continue */
@@ -598,9 +662,15 @@ static int net_socket_connect_init(NetClientState *peer,
return -1;
}
- snprintf(s->nc.info_str, sizeof(s->nc.info_str),
- "socket: connect to %s:%d",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ if (pf == PF_INET) {
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
+ "socket: connect to %s:%d",
+ inet_ntoa(saddr_in->sin_addr), ntohs(saddr_in->sin_port));
+ } else if (pf == PF_UNIX) {
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
+ "socket: connect to %s", saddr_un->sun_path);
+ }
+
return 0;
}
diff --git a/qemu-options.hx b/qemu-options.hx
index fd21002bd61d..625a31dcdbc8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2847,13 +2847,13 @@ SRST
#connect a TAP device to bridge qemubr0
|qemu_system| linux.img -netdev bridge,br=qemubr0,id=n1 -device virtio-net,netdev=n1
-``-netdev socket,id=id[,fd=h][,listen=[host]:port][,connect=host:port]``
+``-netdev socket,id=id[,fd=h][,listen=[host]:port|path][,connect=host:port|path]``
This host network backend can be used to connect the guest's network
- to another QEMU virtual machine using a TCP socket connection. If
- ``listen`` is specified, QEMU waits for incoming connections on port
- (host is optional). ``connect`` is used to connect to another QEMU
- instance using the ``listen`` option. ``fd``\ =h specifies an
- already opened TCP socket.
+ to another QEMU virtual machine using a TCP or a UNIX domain socket
+ connection. If ``listen`` is specified, QEMU waits for incoming
+ connections on port (host is optional), or on path. ``connect`` is used
+ to connect to another QEMU instance using the ``listen`` option.
+ ``fd``\ =h specifies an already opened TCP or UNIX domain socket.
Example:
--
2.29.2