From 65c1796c4aeb54fc10430ba89f15141702f42eee Mon Sep 17 00:00:00 2001 From: David du Colombier Date: Fri, 13 Jul 2012 14:34:59 +0200 Subject: [PATCH] MINOR: IPv6 support for transparent proxy Set socket option IPV6_TRANSPARENT on binding to enable transparent proxy on IPv6. This option is available from Linux 2.6.37. --- include/common/compat.h | 3 +++ src/proto_tcp.c | 46 +++++++++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/include/common/compat.h b/include/common/compat.h index 80e1dd2936..c4ac08cf6c 100644 --- a/include/common/compat.h +++ b/include/common/compat.h @@ -88,6 +88,9 @@ #if !defined(IP_TRANSPARENT) #define IP_TRANSPARENT 19 #endif /* !IP_TRANSPARENT */ +#if !defined(IPV6_TRANSPARENT) +#define IPV6_TRANSPARENT 75 +#endif /* !IPV6_TRANSPARENT */ #endif /* CONFIG_HAP_LINUX_TPROXY */ /* We'll try to enable SO_REUSEPORT on Linux 2.4 and 2.6 if not defined. diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 59b8bc555a..1d38b3caa6 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -128,12 +128,25 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so #ifdef CONFIG_HAP_LINUX_TPROXY static int ip_transp_working = 1; - if (flags && ip_transp_working) { - if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == 0 - || setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0) - foreign_ok = 1; - else - ip_transp_working = 0; + static int ip6_transp_working = 1; + switch (local->ss_family) { + case AF_INET: + if (flags && ip_transp_working) { + if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == 0 + || setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0) + foreign_ok = 1; + else + ip_transp_working = 0; + } + break; + case AF_INET6: + if (flags && ip6_transp_working) { + if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == 0) + foreign_ok = 1; + else + ip6_transp_working = 0; + } + break; } #endif if (flags) { @@ -736,11 +749,22 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen) setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); #endif #ifdef CONFIG_HAP_LINUX_TPROXY - if ((listener->options & LI_O_FOREIGN) - && (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == -1) - && (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)) { - msg = "cannot make listening socket transparent"; - err |= ERR_ALERT; + if (listener->options & LI_O_FOREIGN) { + switch (listener->addr.ss_family) { + case AF_INET: + if ((setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == -1) + && (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)) { + msg = "cannot make listening socket transparent"; + err |= ERR_ALERT; + } + break; + case AF_INET6: + if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == -1) { + msg = "cannot make listening socket transparent"; + err |= ERR_ALERT; + } + break; + } } #endif #ifdef SO_BINDTODEVICE -- 2.47.3