1
0
Fork 0
mirror of https://passt.top/passt synced 2025-08-14 19:03:12 +02:00

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>
This commit is contained in:
David Gibson 2022-11-17 16:59:06 +11:00 committed by Stefano Brivio
commit 9b0cc33d68
2 changed files with 20 additions and 2 deletions

17
util.c
View file

@ -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)))