aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNicholas Ngai <nicholas@ngai.me>2021-09-27 14:21:45 -0700
committerNicholas Ngai <nicholas@ngai.me>2021-09-27 14:21:45 -0700
commit92346097c2148d1a7ff73223d20409db4ac6ba22 (patch)
treeed0b67e72894061d34f96f0aee6bfd2cd70f5d89 /src
parent23db43abdb5740287bbb7cbf5cc99eb22e121298 (diff)
downloadslirp-92346097c2148d1a7ff73223d20409db4ac6ba22.zip
slirp-92346097c2148d1a7ff73223d20409db4ac6ba22.tar.gz
slirp-92346097c2148d1a7ff73223d20409db4ac6ba22.tar.bz2
Support Unix sockets in hostfwd
QEMU has an issue open (https://gitlab.com/qemu-project/qemu/-/issues/347) to forward a Unix domain socket to guest TCP port. Both of these protocols support stream modes of operation (and user-mode networking can only access the stream anyway), so this patch enables Unix-to-TCP hostfwds. Like with localhost hostfwds, the sotranslate_accept function will translate a Unix domain socket connection to a TCP connection originating from vhost_addr and a randomized ephemeral port. Signed-off-by: Nicholas Ngai <nicholas@ngai.me>
Diffstat (limited to 'src')
-rw-r--r--src/libslirp.h1
-rw-r--r--src/socket.c19
-rw-r--r--src/socket.h26
-rw-r--r--src/state.c2
4 files changed, 34 insertions, 14 deletions
diff --git a/src/libslirp.h b/src/libslirp.h
index 5760d53..afb6663 100644
--- a/src/libslirp.h
+++ b/src/libslirp.h
@@ -13,6 +13,7 @@
#else
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <sys/un.h>
#endif
#include "libslirp-version.h"
diff --git a/src/socket.c b/src/socket.c
index 2c1b789..09ce6bf 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -769,18 +769,6 @@ struct socket *tcpx_listen(Slirp *slirp,
socklen_t addrlen;
DEBUG_CALL("tcpx_listen");
- /* AF_INET6 addresses are bigger than AF_INET, so this is big enough. */
- char addrstr[INET6_ADDRSTRLEN];
- char portstr[6];
- int ret;
- ret = getnameinfo(haddr, haddrlen, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST|NI_NUMERICSERV);
- g_assert(ret == 0);
- DEBUG_ARG("haddr = %s", addrstr);
- DEBUG_ARG("hport = %s", portstr);
- ret = getnameinfo(laddr, laddrlen, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST|NI_NUMERICSERV);
- g_assert(ret == 0);
- DEBUG_ARG("laddr = %s", addrstr);
- DEBUG_ARG("lport = %s", portstr);
DEBUG_ARG("flags = %x", flags);
/*
@@ -1041,6 +1029,13 @@ void sotranslate_accept(struct socket *so)
}
break;
+ case AF_UNIX:
+ /* Translate Unix socket to random ephemeral source port. */
+ so->so_ffamily = AF_INET;
+ so->so_faddr = slirp->vhost_addr;
+ so->so_fport = g_rand_int_range(slirp->grand, 49152, 65536);
+ break;
+
default:
break;
}
diff --git a/src/socket.h b/src/socket.h
index a73175d..5f6242e 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -6,6 +6,8 @@
#ifndef SLIRP_SOCKET_H
#define SLIRP_SOCKET_H
+#include <string.h>
+
#include "misc.h"
#include "sbuf.h"
@@ -23,6 +25,16 @@ typedef union in4or6_addr in4or6_addr;
* Our socket structure
*/
+union slirp_sockaddr_host {
+ struct sockaddr sa;
+ struct sockaddr_storage ss;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+#ifndef _WIN32
+ struct sockaddr_un sun;
+#endif
+};
+
union slirp_sockaddr {
struct sockaddr sa;
struct sockaddr_storage ss;
@@ -47,11 +59,12 @@ struct socket {
struct tcpiphdr *so_ti; /* Pointer to the original ti within
* so_mconn, for non-blocking connections */
uint32_t so_urgc;
- union slirp_sockaddr fhost; /* Foreign host */
+ union slirp_sockaddr_host fhost; /* Foreign host */
#define so_faddr fhost.sin.sin_addr
#define so_fport fhost.sin.sin_port
#define so_faddr6 fhost.sin6.sin6_addr
#define so_fport6 fhost.sin6.sin6_port
+#define so_fpath fhost.sun.sun_path
#define so_ffamily fhost.ss.ss_family
union slirp_sockaddr lhost; /* Local host */
@@ -128,6 +141,13 @@ static inline int sockaddr_equal(const struct sockaddr_storage *a,
return (in6_equal(&a6->sin6_addr, &b6->sin6_addr) &&
a6->sin6_port == b6->sin6_port);
}
+#ifndef _WIN32
+ case AF_UNIX: {
+ const struct sockaddr_un *aun = (const struct sockaddr_un *)a;
+ const struct sockaddr_un *bun = (const struct sockaddr_un *)b;
+ return strncmp(aun->sun_path, bun->sun_path, sizeof(aun->sun_path)) == 0;
+ }
+#endif
default:
g_assert_not_reached();
}
@@ -142,6 +162,10 @@ static inline socklen_t sockaddr_size(const struct sockaddr_storage *a)
return sizeof(struct sockaddr_in);
case AF_INET6:
return sizeof(struct sockaddr_in6);
+#ifndef _WIN32
+ case AF_UNIX:
+ return sizeof(struct sockaddr_un);
+#endif
default:
g_assert_not_reached();
}
diff --git a/src/state.c b/src/state.c
index 22af77b..181d338 100644
--- a/src/state.c
+++ b/src/state.c
@@ -273,7 +273,7 @@ static const VMStateDescription vmstate_slirp_socket = {
VMSTATE_UINT16_TEST(so_lport, struct socket, slirp_older_than_v4),
/* v4 and newer */
VMSTATE_STRUCT(fhost, struct socket, 4, vmstate_slirp_socket_addr,
- union slirp_sockaddr),
+ union slirp_sockaddr_host),
VMSTATE_STRUCT(lhost, struct socket, 4, vmstate_slirp_socket_addr,
union slirp_sockaddr),