diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2022-11-17 16:59:06 +1100 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2022-11-25 01:35:58 +0100 |
commit | 9b0cc33d6841bec78e1896d4cd1761a57bd250a7 (patch) | |
tree | 066855ba2b0967e581601e226c6b22fe51d5f5dc /util.c | |
parent | ebf56c7b56dfb61ef600890ea061b251dec08cc7 (diff) | |
download | passt-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.c | 17 |
1 files changed, 15 insertions, 2 deletions
@@ -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))) |