]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: IPv6 support for transparent proxy
authorDavid du Colombier <dducolombier@exceliance.fr>
Fri, 13 Jul 2012 12:34:59 +0000 (14:34 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Jul 2012 05:53:42 +0000 (07:53 +0200)
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
src/proto_tcp.c

index 80e1dd2936dfd521abfd6fa044ebe15093e14154..c4ac08cf6c9274e8bd094c20cf7ceeaa28b9c17c 100644 (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.
index 59b8bc555aa914e0092995c6017fa21b7431a0d3..1d38b3caa610299734aee7deb5f234e1189bf855 100644 (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