diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2021-03-05 20:42:40 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2021-03-17 21:59:20 +0100 |
commit | d9c09e573db5dabbdece52e93df5a30dd937a5b5 (patch) | |
tree | d982a918202b8bdb764ba0893e3dd79eb1985f9c /src | |
parent | 666235c02866039536cdd535c36e8d0fd29dde93 (diff) | |
download | slirp-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.h | 1 | ||||
-rw-r--r-- | src/slirp.c | 9 | ||||
-rw-r--r-- | src/socket.c | 1 | ||||
-rw-r--r-- | src/socket.h | 1 | ||||
-rw-r--r-- | src/udp.c | 2 | ||||
-rw-r--r-- | src/util.h | 6 |
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) @@ -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); @@ -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; |