Add a feature for mapping a host unix socket to a guest tcp socket
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE4vRkF7O8asAeqx2F3PytNJui1S8FAmjixEQACgkQ3PytNJui 1S/prg/+I154XOH+ST2IbUzlg/wLnVmH9X0HcIbatdY55tsW1RLm89RRQjPCsogF HcLT+AKu4T43c2QFMQU9aetYVXSJP17PZXYG1grwBC6S+nwOVpJSI5q/nmwQ7llE 0wG+yDoclLyaJ4cfBbYKLAa3aLb+mFWqineLJCOyhht5Lwg285PkDyCIo1TzerR0 beR8xinxrfXgF9ELtQhvjHosfggw3+s/6EIXVI6uYdBLRwymYyebaI3JZr4aN9Kx 1rsj1PVMAyN1GJaV7ZJwHBRKNX7h9xtxx/TI7oFV8/kwx/PUOsoXWOSZufXDb5CU ltkZAQ788XkBGV5CaQfDiyZGfLd8wwcKI8rwes3uxrzUnzEyo1qJKeKPlrxiyC2h 0RtJZhC/973YDc0aQB9y4J0HP77DNwLlCCVtkS23/rk1EwSwHBwbxtENsDSuj9CY Nn9oFlhJpULGoPMpMvcOGC/PRpt/+58Vu4lDCFUlr84tNLPhUHhq/dh8/LhbL/SE 2UOw93aXrA6NQLnVczauX6VL+e0PACOzelAQZujRQuJf/Hi9cvJT6WsvBL75UQGF 5xC3D/Oraqeg8z+9NJkp9X5qOLAo6v4m4sXbiMDkMSD5IsxkHmmLEqE1WBjGu8jt 453ghqwyRQJLUv9G+AxRn3tSg1+0s/pKTtZ388EWz5xIM9pdn/A= =HIIY -----END PGP SIGNATURE----- Merge tag 'samuel-thibault' of https://people.debian.org/~sthibault/qemu into staging Add a feature for mapping a host unix socket to a guest tcp socket # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEE4vRkF7O8asAeqx2F3PytNJui1S8FAmjixEQACgkQ3PytNJui # 1S/prg/+I154XOH+ST2IbUzlg/wLnVmH9X0HcIbatdY55tsW1RLm89RRQjPCsogF # HcLT+AKu4T43c2QFMQU9aetYVXSJP17PZXYG1grwBC6S+nwOVpJSI5q/nmwQ7llE # 0wG+yDoclLyaJ4cfBbYKLAa3aLb+mFWqineLJCOyhht5Lwg285PkDyCIo1TzerR0 # beR8xinxrfXgF9ELtQhvjHosfggw3+s/6EIXVI6uYdBLRwymYyebaI3JZr4aN9Kx # 1rsj1PVMAyN1GJaV7ZJwHBRKNX7h9xtxx/TI7oFV8/kwx/PUOsoXWOSZufXDb5CU # ltkZAQ788XkBGV5CaQfDiyZGfLd8wwcKI8rwes3uxrzUnzEyo1qJKeKPlrxiyC2h # 0RtJZhC/973YDc0aQB9y4J0HP77DNwLlCCVtkS23/rk1EwSwHBwbxtENsDSuj9CY # Nn9oFlhJpULGoPMpMvcOGC/PRpt/+58Vu4lDCFUlr84tNLPhUHhq/dh8/LhbL/SE # 2UOw93aXrA6NQLnVczauX6VL+e0PACOzelAQZujRQuJf/Hi9cvJT6WsvBL75UQGF # 5xC3D/Oraqeg8z+9NJkp9X5qOLAo6v4m4sXbiMDkMSD5IsxkHmmLEqE1WBjGu8jt # 453ghqwyRQJLUv9G+AxRn3tSg1+0s/pKTtZ388EWz5xIM9pdn/A= # =HIIY # -----END PGP SIGNATURE----- # gpg: Signature made Sun 05 Oct 2025 12:17:24 PM PDT # gpg: using RSA key E2F46417B3BC6AC01EAB1D85DCFCAD349BA2D52F # gpg: Good signature from "Samuel Thibault <samuel.thibault@ens-lyon.org>" [unknown] # gpg: aka "Samuel Thibault <sthibault@debian.org>" [unknown] # gpg: aka "Samuel Thibault <samuel.thibault@gnu.org>" [unknown] # gpg: aka "Samuel Thibault <samuel.thibault@inria.fr>" [unknown] # gpg: aka "Samuel Thibault <samuel.thibault@labri.fr>" [unknown] # gpg: aka "Samuel Thibault <samuel.thibault@aquilenet.fr>" [unknown] # gpg: aka "Samuel Thibault <samuel.thibault@u-bordeaux.fr>" [unknown] # gpg: aka "Samuel Thibault <sthibault@hypra.fr>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 900C B024 B679 31D4 0F82 304B D017 8C76 7D06 9EE6 # Subkey fingerprint: E2F4 6417 B3BC 6AC0 1EAB 1D85 DCFC AD34 9BA2 D52F * tag 'samuel-thibault' of https://people.debian.org/~sthibault/qemu: Add a feature for mapping a host unix socket to a guest tcp socket Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
d9b32f457f
5 changed files with 100 additions and 33 deletions
|
|
@ -79,7 +79,7 @@ those sockets. To allow ping for GID 100 (usually users group)::
|
|||
|
||||
When using the built-in TFTP server, the router is also the TFTP server.
|
||||
|
||||
When using the ``'-netdev user,hostfwd=...'`` option, TCP or UDP
|
||||
When using the ``'-netdev user,hostfwd=...'`` option, TCP, UDP or UNIX
|
||||
connections can be redirected from the host to the guest. It allows for
|
||||
example to redirect X11, telnet or SSH connections.
|
||||
|
||||
|
|
|
|||
|
|
@ -1357,8 +1357,8 @@ ERST
|
|||
{
|
||||
.name = "hostfwd_add",
|
||||
.args_type = "arg1:s,arg2:s?",
|
||||
.params = "[netdev_id] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
|
||||
.help = "redirect TCP or UDP connections from host to guest (requires -net user)",
|
||||
.params = "[netdev_id] [tcp|udp|unix]:[[hostaddr]:hostport|hostpath]-[guestaddr]:guestport",
|
||||
.help = "redirect TCP, UDP or UNIX connections from host to guest (requires -net user)",
|
||||
.cmd = hmp_hostfwd_add,
|
||||
},
|
||||
#endif
|
||||
|
|
|
|||
114
net/slirp.c
114
net/slirp.c
|
|
@ -732,6 +732,7 @@ static SlirpState *slirp_lookup(Monitor *mon, const char *id)
|
|||
|
||||
void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
/* TODO: support removing unix fwd */
|
||||
struct sockaddr_in host_addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr = {
|
||||
|
|
@ -800,12 +801,13 @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
|
|||
|
||||
static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
|
||||
{
|
||||
struct sockaddr_in host_addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr = {
|
||||
.s_addr = INADDR_ANY,
|
||||
},
|
||||
};
|
||||
union {
|
||||
struct sockaddr_in in;
|
||||
#if !defined(WIN32) && SLIRP_CHECK_VERSION(4, 7, 0)
|
||||
struct sockaddr_un un;
|
||||
#endif
|
||||
} host_addr = {0};
|
||||
|
||||
struct sockaddr_in guest_addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr = {
|
||||
|
|
@ -816,9 +818,13 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
|
|||
int host_port, guest_port;
|
||||
const char *p;
|
||||
char buf[256];
|
||||
int is_udp;
|
||||
int is_udp = 0;
|
||||
#if !defined(WIN32) && SLIRP_CHECK_VERSION(4, 7, 0)
|
||||
int is_unix = 0;
|
||||
#endif
|
||||
const char *end;
|
||||
const char *fail_reason = "Unknown reason";
|
||||
socklen_t host_addr_size;
|
||||
|
||||
p = redir_str;
|
||||
if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||
|
|
@ -829,30 +835,83 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
|
|||
is_udp = 0;
|
||||
} else if (!strcmp(buf, "udp")) {
|
||||
is_udp = 1;
|
||||
} else {
|
||||
}
|
||||
#if !defined(WIN32) && SLIRP_CHECK_VERSION(4, 7, 0)
|
||||
else if (!strcmp(buf, "unix")) {
|
||||
is_unix = 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
fail_reason = "Bad protocol name";
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||
fail_reason = "Missing : separator";
|
||||
goto fail_syntax;
|
||||
}
|
||||
if (buf[0] != '\0' && !inet_aton(buf, &host_addr.sin_addr)) {
|
||||
fail_reason = "Bad host address";
|
||||
goto fail_syntax;
|
||||
}
|
||||
#if !defined(WIN32) && SLIRP_CHECK_VERSION(4, 7, 0)
|
||||
if (is_unix) {
|
||||
if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
|
||||
fail_reason = "Missing - separator";
|
||||
goto fail_syntax;
|
||||
}
|
||||
if (buf[0] == '\0') {
|
||||
fail_reason = "Missing unix socket path";
|
||||
goto fail_syntax;
|
||||
}
|
||||
if (buf[0] != '/') {
|
||||
fail_reason = "unix socket path must be absolute";
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
|
||||
fail_reason = "Bad host port separator";
|
||||
goto fail_syntax;
|
||||
size_t path_len = strlen(buf);
|
||||
if (path_len > sizeof(host_addr.un.sun_path) - 1) {
|
||||
fail_reason = "Unix socket path is too long";
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (stat(buf, &st) == 0) {
|
||||
if (!S_ISSOCK(st.st_mode)) {
|
||||
fail_reason = "file exists and it's not unix socket";
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
if (unlink(buf) < 0) {
|
||||
error_setg_errno(errp, errno, "Failed to unlink '%s'", buf);
|
||||
goto fail_syntax;
|
||||
}
|
||||
}
|
||||
host_addr.un.sun_family = AF_UNIX;
|
||||
memcpy(host_addr.un.sun_path, buf, path_len);
|
||||
host_addr_size = sizeof(host_addr.un);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
host_addr.in.sin_family = AF_INET;
|
||||
host_addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||
fail_reason = "Missing : separator";
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
if (buf[0] != '\0' && !inet_aton(buf, &host_addr.in.sin_addr)) {
|
||||
fail_reason = "Bad host address";
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
|
||||
fail_reason = "Bad host port separator";
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
err = qemu_strtoi(buf, &end, 0, &host_port);
|
||||
if (err || host_port < 0 || host_port > 65535) {
|
||||
fail_reason = "Bad host port";
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
host_addr.in.sin_port = htons(host_port);
|
||||
host_addr_size = sizeof(host_addr.in);
|
||||
}
|
||||
err = qemu_strtoi(buf, &end, 0, &host_port);
|
||||
if (err || host_port < 0 || host_port > 65535) {
|
||||
fail_reason = "Bad host port";
|
||||
goto fail_syntax;
|
||||
}
|
||||
host_addr.sin_port = htons(host_port);
|
||||
|
||||
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||
fail_reason = "Missing guest address";
|
||||
|
|
@ -872,12 +931,13 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
|
|||
|
||||
#if SLIRP_CHECK_VERSION(4, 5, 0)
|
||||
err = slirp_add_hostxfwd(s->slirp,
|
||||
(struct sockaddr *) &host_addr, sizeof(host_addr),
|
||||
(struct sockaddr *) &host_addr, host_addr_size,
|
||||
(struct sockaddr *) &guest_addr, sizeof(guest_addr),
|
||||
is_udp ? SLIRP_HOSTFWD_UDP : 0);
|
||||
#else
|
||||
(void) host_addr_size;
|
||||
err = slirp_add_hostfwd(s->slirp, is_udp,
|
||||
host_addr.sin_addr, host_port,
|
||||
host_addr.in.sin_addr, host_port,
|
||||
guest_addr.sin_addr, guest_port);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@
|
|||
#
|
||||
# @smbserver: IP address of the built-in SMB server
|
||||
#
|
||||
# @hostfwd: redirect incoming TCP or UDP host connections to guest
|
||||
# @hostfwd: redirect incoming TCP, UDP or UNIX host connections to guest
|
||||
# endpoints
|
||||
#
|
||||
# @guestfwd: forward guest TCP connections
|
||||
|
|
|
|||
|
|
@ -3324,8 +3324,8 @@ SRST
|
|||
|
||||
Note that a SAMBA server must be installed on the host OS.
|
||||
|
||||
``hostfwd=[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport``
|
||||
Redirect incoming TCP or UDP connections to the host port
|
||||
``hostfwd=[tcp|udp|unix]:[[hostaddr]:hostport|hostpath]-[guestaddr]:guestport``
|
||||
Redirect incoming TCP, UDP or UNIX connections to the host port
|
||||
hostport to the guest IP address guestaddr on guest port
|
||||
guestport. If guestaddr is not specified, its value is x.x.x.15
|
||||
(default first address given by the built-in DHCP server). By
|
||||
|
|
@ -3355,6 +3355,13 @@ SRST
|
|||
Then when you use on the host ``telnet localhost 5555``, you
|
||||
connect to the guest telnet server.
|
||||
|
||||
To redirect host unix socket /tmp/vm to guest tcp socket 23 use
|
||||
following:
|
||||
|
||||
.. parsed-literal::
|
||||
# on the host
|
||||
|qemu_system| -nic user,hostfwd=unix:/tmp/vm-:23
|
||||
|
||||
``guestfwd=[tcp]:server:port-dev``; \ ``guestfwd=[tcp]:server:port-cmd:command``
|
||||
Forward guest TCP connections to the IP address server on port
|
||||
port to the character device dev or to a program executed by
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue