aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2021-03-05 20:42:40 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2021-03-17 21:59:20 +0100
commitd9c09e573db5dabbdece52e93df5a30dd937a5b5 (patch)
treed982a918202b8bdb764ba0893e3dd79eb1985f9c /src
parent666235c02866039536cdd535c36e8d0fd29dde93 (diff)
downloadslirp-d9c09e573db5dabbdece52e93df5a30dd937a5b5.zip
slirp-d9c09e573db5dabbdece52e93df5a30dd937a5b5.tar.gz
slirp-d9c09e573db5dabbdece52e93df5a30dd937a5b5.tar.bz2
hostfwd: Add SLIRP_HOSTFWD_V6ONLY flag
That allows to request binding on v6 addresses only. Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Diffstat (limited to 'src')
-rw-r--r--src/libslirp.h1
-rw-r--r--src/slirp.c9
-rw-r--r--src/socket.c1
-rw-r--r--src/socket.h1
-rw-r--r--src/udp.c2
-rw-r--r--src/util.h6
6 files changed, 18 insertions, 2 deletions
diff --git a/src/libslirp.h b/src/libslirp.h
index a0f0eb1..7049e5b 100644
--- a/src/libslirp.h
+++ b/src/libslirp.h
@@ -169,6 +169,7 @@ int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
int host_port);
#define SLIRP_HOSTFWD_UDP 1
+#define SLIRP_HOSTFWD_V6ONLY 2
int slirp_add_hostxfwd(Slirp *slirp,
const struct sockaddr *haddr, socklen_t haddrlen,
const struct sockaddr *gaddr, socklen_t gaddrlen,
diff --git a/src/slirp.c b/src/slirp.c
index 98cfd48..b1539af 100644
--- a/src/slirp.c
+++ b/src/slirp.c
@@ -1171,6 +1171,11 @@ int slirp_add_hostxfwd(Slirp *slirp,
int flags)
{
struct sockaddr_in gdhcp_addr;
+ int fwd_flags = SS_HOSTFWD;
+
+ if (flags & SLIRP_HOSTFWD_V6ONLY)
+ fwd_flags |= SS_HOSTFWD_V6ONLY;
+
if (gaddr->sa_family == AF_INET) {
const struct sockaddr_in *gaddr_in = (const struct sockaddr_in *) gaddr;
@@ -1202,12 +1207,12 @@ int slirp_add_hostxfwd(Slirp *slirp,
if (flags & SLIRP_HOSTFWD_UDP) {
if (!udpx_listen(slirp, haddr, haddrlen,
gaddr, gaddrlen,
- SS_HOSTFWD))
+ fwd_flags))
return -1;
} else {
if (!tcpx_listen(slirp, haddr, haddrlen,
gaddr, gaddrlen,
- SS_HOSTFWD))
+ fwd_flags))
return -1;
}
return 0;
diff --git a/src/socket.c b/src/socket.c
index d90c0a4..40c32a5 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -782,6 +782,7 @@ struct socket *tcpx_listen(Slirp *slirp,
s = slirp_socket(haddr->sa_family, SOCK_STREAM, 0);
if ((s < 0) ||
+ (haddr->sa_family == AF_INET6 && slirp_socket_set_v6only(s, (flags & SS_HOSTFWD_V6ONLY) != 0) < 0) ||
(slirp_socket_set_fast_reuse(s) < 0) ||
(bind(s, haddr, haddrlen) < 0) ||
(listen(s, 1) < 0)) {
diff --git a/src/socket.h b/src/socket.h
index 524312f..5ea3cf6 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -106,6 +106,7 @@ struct socket {
#define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */
#define SS_INCOMING \
0x2000 /* Connection was initiated by a host on the internet */
+#define SS_HOSTFWD_V6ONLY 0x4000 /* Only bind on v6 addresses */
static inline int sockaddr_equal(const struct sockaddr_storage *a,
const struct sockaddr_storage *b)
diff --git a/src/udp.c b/src/udp.c
index f49922b..aa44bc3 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -367,6 +367,8 @@ struct socket *udpx_listen(Slirp *slirp,
sofree(so);
return NULL;
}
+ if (haddr->sa_family == AF_INET6)
+ slirp_socket_set_v6only(so->s, (flags & SS_HOSTFWD_V6ONLY) != 0);
so->so_expire = curtime + SO_EXPIRE;
insque(so, &slirp->udb);
diff --git a/src/util.h b/src/util.h
index 8134db9..07654ec 100644
--- a/src/util.h
+++ b/src/util.h
@@ -39,6 +39,7 @@
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
+#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/tcp.h>
@@ -161,6 +162,11 @@ int slirp_inet_aton(const char *cp, struct in_addr *ia);
int slirp_socket(int domain, int type, int protocol);
void slirp_set_nonblock(int fd);
+static inline int slirp_socket_set_v6only(int fd, int v)
+{
+ return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v, sizeof(v));
+}
+
static inline int slirp_socket_set_nodelay(int fd)
{
int v = 1;