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.
This commit is contained in:
David du Colombier 2012-07-13 14:34:59 +02:00 committed by Willy Tarreau
parent 5b88da269c
commit 65c1796c4a
2 changed files with 38 additions and 11 deletions

View File

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

View File

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