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:
parent
ebf56c7b56
commit
9b0cc33d68
2 changed files with 20 additions and 2 deletions
5
Makefile
5
Makefile
|
@ -11,6 +11,10 @@
|
||||||
|
|
||||||
VERSION ?= $(shell git describe --tags HEAD 2>/dev/null || echo "unknown\ version")
|
VERSION ?= $(shell git describe --tags HEAD 2>/dev/null || echo "unknown\ version")
|
||||||
|
|
||||||
|
# Does the target platform allow IPv4 connections to be handled via
|
||||||
|
# the IPv6 socket API? (Linux does)
|
||||||
|
DUAL_STACK_SOCKETS := 1
|
||||||
|
|
||||||
RLIMIT_STACK_VAL := $(shell /bin/sh -c 'ulimit -s')
|
RLIMIT_STACK_VAL := $(shell /bin/sh -c 'ulimit -s')
|
||||||
ifeq ($(RLIMIT_STACK_VAL),unlimited)
|
ifeq ($(RLIMIT_STACK_VAL),unlimited)
|
||||||
RLIMIT_STACK_VAL := 1024
|
RLIMIT_STACK_VAL := 1024
|
||||||
|
@ -36,6 +40,7 @@ FLAGS += -DPASST_AUDIT_ARCH=AUDIT_ARCH_$(AUDIT_ARCH)
|
||||||
FLAGS += -DRLIMIT_STACK_VAL=$(RLIMIT_STACK_VAL)
|
FLAGS += -DRLIMIT_STACK_VAL=$(RLIMIT_STACK_VAL)
|
||||||
FLAGS += -DARCH=\"$(TARGET_ARCH)\"
|
FLAGS += -DARCH=\"$(TARGET_ARCH)\"
|
||||||
FLAGS += -DVERSION=\"$(VERSION)\"
|
FLAGS += -DVERSION=\"$(VERSION)\"
|
||||||
|
FLAGS += -DDUAL_STACK_SOCKETS=$(DUAL_STACK_SOCKETS)
|
||||||
|
|
||||||
PASST_SRCS = arch.c arp.c checksum.c conf.c dhcp.c dhcpv6.c icmp.c igmp.c \
|
PASST_SRCS = arch.c arp.c checksum.c conf.c dhcp.c dhcpv6.c icmp.c igmp.c \
|
||||||
isolation.c lineread.c log.c mld.c ndp.c netlink.c packet.c passt.c \
|
isolation.c lineread.c log.c mld.c ndp.c netlink.c packet.c passt.c \
|
||||||
|
|
17
util.c
17
util.c
|
@ -22,6 +22,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "passt.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,
|
0, IN6ADDR_ANY_INIT, 0,
|
||||||
};
|
};
|
||||||
const struct sockaddr *sa;
|
const struct sockaddr *sa;
|
||||||
|
bool dual_stack = false;
|
||||||
struct epoll_event ev;
|
struct epoll_event ev;
|
||||||
int fd, sl, y = 1;
|
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)
|
proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6)
|
||||||
return -1; /* Not implemented. */
|
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)
|
if (proto == IPPROTO_TCP)
|
||||||
fd = socket(af, SOCK_STREAM | SOCK_NONBLOCK, proto);
|
fd = socket(af, SOCK_STREAM | SOCK_NONBLOCK, proto);
|
||||||
else
|
else
|
||||||
|
@ -158,8 +168,11 @@ int sock_l4(const struct ctx *c, int af, uint8_t proto,
|
||||||
sa = (const struct sockaddr *)&addr6;
|
sa = (const struct sockaddr *)&addr6;
|
||||||
sl = sizeof(addr6);
|
sl = sizeof(addr6);
|
||||||
|
|
||||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &y, sizeof(y)))
|
if (!dual_stack)
|
||||||
debug("Failed to set IPV6_V6ONLY on socket %i", fd);
|
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)))
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(y)))
|
||||||
|
|
Loading…
Reference in a new issue