aboutgitcodebugslistschat
path: root/util.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2022-11-17 16:59:06 +1100
committerStefano Brivio <sbrivio@redhat.com>2022-11-25 01:35:58 +0100
commit9b0cc33d6841bec78e1896d4cd1761a57bd250a7 (patch)
tree066855ba2b0967e581601e226c6b22fe51d5f5dc /util.c
parentebf56c7b56dfb61ef600890ea061b251dec08cc7 (diff)
downloadpasst-9b0cc33d6841bec78e1896d4cd1761a57bd250a7.tar
passt-9b0cc33d6841bec78e1896d4cd1761a57bd250a7.tar.gz
passt-9b0cc33d6841bec78e1896d4cd1761a57bd250a7.tar.bz2
passt-9b0cc33d6841bec78e1896d4cd1761a57bd250a7.tar.lz
passt-9b0cc33d6841bec78e1896d4cd1761a57bd250a7.tar.xz
passt-9b0cc33d6841bec78e1896d4cd1761a57bd250a7.tar.zst
passt-9b0cc33d6841bec78e1896d4cd1761a57bd250a7.zip
util: Allow sock_l4() to open dual stack sockets
Currently, when instructed to open an IPv6 socket, sock_l4() explicitly sets the IPV6_V6ONLY socket option so that the socket will only respond to IPv6 connections. Linux (and probably other platforms) allow "dual stack" sockets: IPv6 sockets which can also accept IPv4 connections. Extend sock_l4() to be able to make such sockets, by passing AF_UNSPEC as the address family and no bind address (binding to a specific address would defeat the purpose). We add a Makefile define 'DUAL_STACK_SOCKETS' to indicate availability of this feature on the target platform. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'util.c')
-rw-r--r--util.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/util.c b/util.c
index 2125a67..59c6641 100644
--- a/util.c
+++ b/util.c
@@ -22,6 +22,8 @@
#include <string.h>
#include <time.h>
#include <errno.h>
+#include <stdbool.h>
+#include <assert.h>
#include "util.h"
#include "passt.h"
@@ -112,6 +114,7 @@ int sock_l4(const struct ctx *c, int af, uint8_t proto,
0, IN6ADDR_ANY_INIT, 0,
};
const struct sockaddr *sa;
+ bool dual_stack = false;
struct epoll_event ev;
int fd, sl, y = 1;
@@ -119,6 +122,13 @@ int sock_l4(const struct ctx *c, int af, uint8_t proto,
proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6)
return -1; /* Not implemented. */
+ if (af == AF_UNSPEC) {
+ if (!DUAL_STACK_SOCKETS || bind_addr)
+ return -1;
+ dual_stack = true;
+ af = AF_INET6;
+ }
+
if (proto == IPPROTO_TCP)
fd = socket(af, SOCK_STREAM | SOCK_NONBLOCK, proto);
else
@@ -158,8 +168,11 @@ int sock_l4(const struct ctx *c, int af, uint8_t proto,
sa = (const struct sockaddr *)&addr6;
sl = sizeof(addr6);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &y, sizeof(y)))
- debug("Failed to set IPV6_V6ONLY on socket %i", fd);
+ if (!dual_stack)
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ &y, sizeof(y)))
+ debug("Failed to set IPV6_V6ONLY on socket %i",
+ fd);
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(y)))