Merge branch 'listen_v6only' into 'master'
Listen v6only
See merge request slirp/libslirp!77
diff --git a/src/libslirp.h b/src/libslirp.h
index ab446ca..aac182e 100644
--- a/src/libslirp.h
+++ b/src/libslirp.h
@@ -169,6 +169,7 @@
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 fcaa179..ba41843 100644
--- a/src/slirp.c
+++ b/src/slirp.c
@@ -1172,6 +1172,11 @@
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;
@@ -1208,12 +1213,12 @@
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 2e5fbda..bf50058 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -780,6 +780,7 @@
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 518aebb..932f391 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -106,6 +106,7 @@
#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 bb65ecf..b9694c2 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -370,6 +370,8 @@
errno = save_errno;
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_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;