Hi Willy,

It seams the changes where easier than i expected, assuming ive done it 'correctly'...
I generated 2 patch files:
-"FreeBSD IP_BINDANY git diff.patch" generated with a git diff (against a hopefully relatively recent source tree)(i couldnt get it to fetch http://git.1wt.eu/git/haproxy.git ..) -"FreeBSD IP_BINDANY diff -urN.patch" generated with diff -urN (against the 'port source')

I hope one of them can be used by you.
Please take a look and comment if something is amiss.

Greetings
PiBa-NL

Op 26-4-2013 23:40, PiBa-NL schreef:
Hi Willy,

Ill give it a try and send the patch as an attachment, though im not 100% comfortable with the code. I think i can do it.
Will take me a few days though..

Thanks sofar.

Op 26-4-2013 23:12, Willy Tarreau schreef:
On Fri, Apr 26, 2013 at 11:03:00PM +0200, PiBa-NL wrote:
Hi Willy / Lukas,

It seams to me OpenBSD doesn't support the IP_BINDANY flag..:
http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/netinet/in.h
<http://www.openbsd.org/cgi-bin/cvsweb/%7Echeckout%7E/src/sys/netinet/in.h>
it seems it has, but differently :

http://unix.derkeiler.com/Mailing-Lists/FreeBSD/net/2008-07/msg00399.html

While FreeBSD does:
http://svnweb.freebsd.org/base/head/sys/netinet/in.h?view=markup

But then again neither of them supports SOL_IP, so i would expect
compilation to simply 'fail'. When trying to compile with the
USE_LINUX_TPROXY option.
Which is exactly the reason I don't want to remap these things which
are linux-specific, and instead use the proper call depending on the
available flags. Eg something like this :

#if defined(SOL_IP) && defined(IP_TRANSPARENT)
     /* linux */
     ret = setsockop(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one));
#elif defined (IP_PROTOIP) && defined(IP_BINDANY)
     /* freebsd */
     ret = setsockop(fd, IP_PROTOIP, IP_BINDANY, &one, sizeof(one));
#elif defined (IP_PROTOIP) && defined(IP_BINDANY)
     /* openbsd */
     ret = setsockop(fd, SOL_SOCKET, SO_BINDANY, &one, sizeof(one));
#else
     /* unsupported platform */
     ret = -1;
#endif

The combination i think is unlikely to cause problems for other
currently working builds/systems..

If you want i can probably come up with a combination that makes it work
for FreeBSD with a special USE_FREEBSD_TPROXY make option.
No, really I think something like above is much better for the long
term. It's more work to adapt existing code first but will pay in the
long term, even in the short term if it allows us to support OpenBSD
at the same time.

Or go for the 'full automatic inclusion' depending on available flags.
Which i think is even 'nicer'. But probably needs more testing to
confirm proper working..
I would be willing to make these changes. Is this the way to go?
As you like, if you feel comfortable with changing the way the current
code works (the linux-specific one), feel free to try, otherwise I can
do it over the week-end, and then a second patch derived from yours will
bring in support for FreeBSD then OpenBSD if someone here is able to
test it.

Thanks for reviewing my proposed changes sofar.
you're welcome :-)

Willy



diff -urN workoriginal/haproxy-1.5-dev18/include/common/compat.h 
work/haproxy-1.5-dev18/include/common/compat.h
--- workoriginal/haproxy-1.5-dev18/include/common/compat.h      2013-04-26 
19:36:15.000000000 +0000
+++ work/haproxy-1.5-dev18/include/common/compat.h      2013-04-27 
14:56:27.000000000 +0000
@@ -93,6 +93,15 @@
 #endif /* !IPV6_TRANSPARENT */
 #endif /* CONFIG_HAP_LINUX_TPROXY */

+#if (defined(SOL_IP)       && defined(IP_TRANSPARENT)) \
+ || (defined(SOL_IPV6)     && defined(IPV6_TRANSPARENT)) \
+ || (defined(SOL_IP)       && defined(IP_FREEBIND)) \
+ || (defined(IPPROTO_IP)   && defined(IP_BINDANY)) \
+ || (defined(IPPROTO_IPV6) && defined(IPV6_BINDANY)) \
+ || (defined(SOL_SOCKET)   && defined(SO_BINDANY))
+  #define HAP_TRANSPARENT
+#endif
+
 /* We'll try to enable SO_REUSEPORT on Linux 2.4 and 2.6 if not defined.
  * There are two families of values depending on the architecture. Those
  * are at least valid on Linux 2.4 and 2.6, reason why we'll rely on the
diff -urN workoriginal/haproxy-1.5-dev18/include/types/connection.h 
work/haproxy-1.5-dev18/include/types/connection.h
--- workoriginal/haproxy-1.5-dev18/include/types/connection.h   2013-04-26 
19:36:15.000000000 +0000
+++ work/haproxy-1.5-dev18/include/types/connection.h   2013-04-27 
14:56:30.000000000 +0000
@@ -219,7 +219,7 @@
        char *iface_name;                    /* bind interface name or NULL */
        struct port_range *sport_range;      /* optional per-server TCP source 
ports */
        struct sockaddr_storage source_addr; /* the address to which we want to 
bind for connect() */
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
        struct sockaddr_storage tproxy_addr; /* non-local address we want to 
bind to for connect() */
        char *bind_hdr_name;                 /* bind to this header name if 
defined */
        int bind_hdr_len;                    /* length of the name of the 
header above */
diff -urN workoriginal/haproxy-1.5-dev18/src/backend.c 
work/haproxy-1.5-dev18/src/backend.c
--- workoriginal/haproxy-1.5-dev18/src/backend.c        2013-04-26 
19:36:15.000000000 +0000
+++ work/haproxy-1.5-dev18/src/backend.c        2013-04-27 14:56:32.000000000 
+0000
@@ -884,7 +884,7 @@
  */
 static void assign_tproxy_address(struct session *s)
 {
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
        struct server *srv = objt_server(s->target);
        struct conn_src *src;

diff -urN workoriginal/haproxy-1.5-dev18/src/cfgparse.c 
work/haproxy-1.5-dev18/src/cfgparse.c
--- workoriginal/haproxy-1.5-dev18/src/cfgparse.c       2013-04-26 
19:36:15.000000000 +0000
+++ work/haproxy-1.5-dev18/src/cfgparse.c       2013-04-27 14:56:33.000000000 
+0000
@@ -4535,8 +4535,8 @@
                                cur_arg += 2;
                                while (*(args[cur_arg])) {
                                        if (!strcmp(args[cur_arg], "usesrc")) { 
 /* address to use outside */
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
+#if !defined(HAP_TRANSPARENT)
                                                if 
(!is_addr(&newsrv->conn_src.source_addr)) {
                                                        Alert("parsing [%s:%d] 
: '%s' requires an explicit '%s' address.\n",
                                                              file, linenum, 
"usesrc", "source");
@@ -4625,7 +4625,7 @@
                                                        newsrv->conn_src.opts 
|= CO_SRC_TPROXY_ADDR;
                                                }
                                                global.last_checks |= 
LSTCHK_NETADM;
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if !defined(HAP_TRANSPARENT)
                                                global.last_checks |= 
LSTCHK_CTTPROXY;
 #endif
                                                cur_arg += 2;
@@ -4635,7 +4635,7 @@
                                                      file, linenum, "usesrc");
                                                err_code |= ERR_ALERT | 
ERR_FATAL;
                                                goto out;
-#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
+#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT) */
                                        } /* "usesrc" */

                                        if (!strcmp(args[cur_arg], 
"interface")) { /* specifically bind to this interface */
@@ -5035,8 +5035,8 @@
                cur_arg = 2;
                while (*(args[cur_arg])) {
                        if (!strcmp(args[cur_arg], "usesrc")) {  /* address to 
use outside */
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
+#if !defined(HAP_TRANSPARENT)
                                if (!is_addr(&curproxy->conn_src.source_addr)) {
                                        Alert("parsing [%s:%d] : '%s' requires 
an explicit 'source' address.\n",
                                              file, linenum, "usesrc");
@@ -5125,7 +5125,7 @@
                                        curproxy->conn_src.opts |= 
CO_SRC_TPROXY_ADDR;
                                }
                                global.last_checks |= LSTCHK_NETADM;
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if !defined(HAP_TRANSPARENT)
                                global.last_checks |= LSTCHK_CTTPROXY;
 #endif
 #else  /* no TPROXY support */
@@ -6802,7 +6802,7 @@
                                }
                        }

-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
                        if (curproxy->conn_src.bind_hdr_occ) {
                                curproxy->conn_src.bind_hdr_occ = 0;
                                Warning("config : %s '%s' : ignoring use of 
header %s as source IP in non-HTTP mode.\n",
@@ -6829,7 +6829,7 @@
                                err_code |= ERR_WARN;
                        }

-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
                        if (curproxy->mode != PR_MODE_HTTP && 
newsrv->conn_src.bind_hdr_occ) {
                                newsrv->conn_src.bind_hdr_occ = 0;
                                Warning("config : %s '%s' : server %s cannot 
use header %s as source IP in non-HTTP mode.\n",
diff -urN workoriginal/haproxy-1.5-dev18/src/haproxy.c 
work/haproxy-1.5-dev18/src/haproxy.c
--- workoriginal/haproxy-1.5-dev18/src/haproxy.c        2013-04-26 
19:36:15.000000000 +0000
+++ work/haproxy-1.5-dev18/src/haproxy.c        2013-04-27 14:56:33.000000000 
+0000
@@ -289,6 +289,29 @@
 #else /* USE_OPENSSL */
        printf("Built without OpenSSL support (USE_OPENSSL not set)\n");
 #endif
+
+#ifdef HAP_TRANSPARENT
+  printf("Built with 'transparent proxy' support using:"
+  #if defined(SOL_IP)       && defined(IP_TRANSPARENT)
+    " IP_TRANSPARENT"
+  #endif
+  #if defined(SOL_IPV6)     && defined(IPV6_TRANSPARENT)
+    " IPV6_TRANSPARENT"
+  #endif
+  #if defined(SOL_IP)       && defined(IP_FREEBIND)
+    " IP_FREEBIND"
+  #endif
+  #if defined(IPPROTO_IP)   && defined(IP_BINDANY)
+    " IP_BINDANY"
+  #endif
+  #if defined(IPPROTO_IPV6) && defined(IPV6_BINDANY)
+    " IPV6_BINDANY"
+  #endif
+  #if defined(SOL_SOCKET)   && defined(SO_BINDANY)
+    " SO_BINDANY"
+  #endif
+  "\n");
+#endif
        putchar('\n');

        list_pollers(stdout);
diff -urN workoriginal/haproxy-1.5-dev18/src/proto_tcp.c 
work/haproxy-1.5-dev18/src/proto_tcp.c
--- workoriginal/haproxy-1.5-dev18/src/proto_tcp.c      2013-04-26 
19:36:15.000000000 +0000
+++ work/haproxy-1.5-dev18/src/proto_tcp.c      2013-04-27 14:56:34.000000000 
+0000
@@ -123,14 +123,26 @@
        int foreign_ok = 0;
        int ret;

-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef HAP_TRANSPARENT
        static int ip_transp_working = 1;
        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)
+                       int ret = 0;
+                       #if defined(SOL_IP)       && defined(IP_TRANSPARENT)
+                       ret |= setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(SOL_IP)       && defined(IP_FREEBIND)
+                       ret |= setsockopt(fd, SOL_IP, IP_FREEBIND, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(IPPROTO_IP)   && defined(IP_BINDANY)
+                       ret |= setsockopt(fd, IPPROTO_IP, IP_BINDANY, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(SOL_SOCKET)   && defined(SO_BINDANY)
+                       ret |= setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, 
sizeof(one)) == 0;
+                       #endif
+                       if (ret)
                                foreign_ok = 1;
                        else
                                ip_transp_working = 0;
@@ -138,7 +150,14 @@
                break;
        case AF_INET6:
                if (flags && ip6_transp_working) {
-                       if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, 
sizeof(one)) == 0)
+                       int ret = 0;
+                       #if defined(SOL_IPV6)     && defined(IPV6_TRANSPARENT)
+                       ret |= setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(IPPROTO_IPV6) && defined(IPV6_BINDANY)
+                       ret |= setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &one, 
sizeof(one)) == 0;
+                       #endif
+                       if (ret)
                                foreign_ok = 1;
                        else
                                ip6_transp_working = 0;
@@ -621,18 +640,36 @@
        if (!ext)
                setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
 #endif
-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef HAP_TRANSPARENT
        if (!ext && (listener->options & LI_O_FOREIGN)) {
+               int ret = 0;
                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)) {
+                       #if defined(SOL_IP)       && defined(IP_TRANSPARENT)
+                       ret = ret || setsockopt(fd, SOL_IP, IP_TRANSPARENT, 
&one, sizeof(one)) == 0;
+                       #endif
+                       #if defined(SOL_IP)       && defined(IP_FREEBIND)
+                       ret = ret || setsockopt(fd, SOL_IP, IP_FREEBIND, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(IPPROTO_IP)   && defined(IP_BINDANY)
+                       ret = ret || setsockopt(fd, IPPROTO_IP, IP_BINDANY, 
&one, sizeof(one)) == 0;
+                       #endif
+                       #if defined(SOL_SOCKET)   && defined(SO_BINDANY)
+                       ret = ret || setsockopt(fd, SOL_SOCKET, SO_BINDANY, 
&one, sizeof(one)) == 0;
+                       #endif
+                       if (!ret){
                                msg = "cannot make listening socket 
transparent";
                                err |= ERR_ALERT;
                        }
-               break;
+               break;
                case AF_INET6:
-                       if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, 
sizeof(one)) == -1) {
+                       #if defined(SOL_IPV6)     && defined(IPV6_TRANSPARENT)
+                       ret = ret || setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, 
&one, sizeof(one)) == 0;
+                       #endif
+                       #if defined(IPPROTO_IPV6) && defined(IPV6_BINDANY)
+                       ret = ret || setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, 
&one, sizeof(one)) == 0;
+                       #endif
+                       if (!ret) {
                                msg = "cannot make listening socket 
transparent";
                                err |= ERR_ALERT;
                        }
@@ -1546,7 +1583,7 @@
 }
 #endif

-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef HAP_TRANSPARENT
 /* parse the "transparent" bind keyword */
 static int bind_parse_transparent(char **args, int cur_arg, struct proxy *px, 
struct bind_conf *conf, char **err)
 {
@@ -1695,7 +1732,7 @@
 #ifdef TCP_FASTOPEN
        { "tfo",           bind_parse_tfo,          0 }, /* enable TCP_FASTOPEN 
of listening socket */
 #endif
-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef HAP_TRANSPARENT
        { "transparent",   bind_parse_transparent,  0 }, /* transparently bind 
to the specified addresses */
 #endif
 #ifdef IPV6_V6ONLY
 include/common/compat.h    |  9 +++++++
 include/types/connection.h |  2 +-
 src/backend.c              |  2 +-
 src/cfgparse.c             | 18 +++++++-------
 src/haproxy.c              | 23 ++++++++++++++++++
 src/proto_tcp.c            | 59 +++++++++++++++++++++++++++++++++++++---------
 6 files changed, 91 insertions(+), 22 deletions(-)

diff --git a/include/common/compat.h b/include/common/compat.h
index bb2d010..31fb9d9 100644
--- a/include/common/compat.h
+++ b/include/common/compat.h
@@ -93,6 +93,15 @@
 #endif /* !IPV6_TRANSPARENT */
 #endif /* CONFIG_HAP_LINUX_TPROXY */
 
+#if (defined(SOL_IP)       && defined(IP_TRANSPARENT)) \
+ || (defined(SOL_IPV6)     && defined(IPV6_TRANSPARENT)) \
+ || (defined(SOL_IP)       && defined(IP_FREEBIND)) \
+ || (defined(IPPROTO_IP)   && defined(IP_BINDANY)) \
+ || (defined(IPPROTO_IPV6) && defined(IPV6_BINDANY)) \
+ || (defined(SOL_SOCKET)   && defined(SO_BINDANY))
+  #define HAP_TRANSPARENT
+#endif  
+
 /* We'll try to enable SO_REUSEPORT on Linux 2.4 and 2.6 if not defined.
  * There are two families of values depending on the architecture. Those
  * are at least valid on Linux 2.4 and 2.6, reason why we'll rely on the
diff --git a/include/types/connection.h b/include/types/connection.h
index 255811c..34fa7b0 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -219,7 +219,7 @@ struct conn_src {
        char *iface_name;                    /* bind interface name or NULL */
        struct port_range *sport_range;      /* optional per-server TCP source 
ports */
        struct sockaddr_storage source_addr; /* the address to which we want to 
bind for connect() */
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
        struct sockaddr_storage tproxy_addr; /* non-local address we want to 
bind to for connect() */
        char *bind_hdr_name;                 /* bind to this header name if 
defined */
        int bind_hdr_len;                    /* length of the name of the 
header above */
diff --git a/src/backend.c b/src/backend.c
index 9f4e635..dc3c3c5 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -884,7 +884,7 @@ int assign_server_and_queue(struct session *s)
  */
 static void assign_tproxy_address(struct session *s)
 {
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
        struct server *srv = objt_server(s->target);
        struct conn_src *src;
 
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 49a91c0..39dd1fc 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -4535,8 +4535,8 @@ stats_error_parsing:
                                cur_arg += 2;
                                while (*(args[cur_arg])) {
                                        if (!strcmp(args[cur_arg], "usesrc")) { 
 /* address to use outside */
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
+#if !defined(HAP_TRANSPARENT)
                                                if 
(!is_addr(&newsrv->conn_src.source_addr)) {
                                                        Alert("parsing [%s:%d] 
: '%s' requires an explicit '%s' address.\n",
                                                              file, linenum, 
"usesrc", "source");
@@ -4625,7 +4625,7 @@ stats_error_parsing:
                                                        newsrv->conn_src.opts 
|= CO_SRC_TPROXY_ADDR;
                                                }
                                                global.last_checks |= 
LSTCHK_NETADM;
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if !defined(HAP_TRANSPARENT)
                                                global.last_checks |= 
LSTCHK_CTTPROXY;
 #endif
                                                cur_arg += 2;
@@ -4635,7 +4635,7 @@ stats_error_parsing:
                                                      file, linenum, "usesrc");
                                                err_code |= ERR_ALERT | 
ERR_FATAL;
                                                goto out;
-#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
+#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT) */
                                        } /* "usesrc" */
 
                                        if (!strcmp(args[cur_arg], 
"interface")) { /* specifically bind to this interface */
@@ -5035,8 +5035,8 @@ stats_error_parsing:
                cur_arg = 2;
                while (*(args[cur_arg])) {
                        if (!strcmp(args[cur_arg], "usesrc")) {  /* address to 
use outside */
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
+#if !defined(HAP_TRANSPARENT)
                                if (!is_addr(&curproxy->conn_src.source_addr)) {
                                        Alert("parsing [%s:%d] : '%s' requires 
an explicit 'source' address.\n",
                                              file, linenum, "usesrc");
@@ -5125,7 +5125,7 @@ stats_error_parsing:
                                        curproxy->conn_src.opts |= 
CO_SRC_TPROXY_ADDR;
                                }
                                global.last_checks |= LSTCHK_NETADM;
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if !defined(HAP_TRANSPARENT)
                                global.last_checks |= LSTCHK_CTTPROXY;
 #endif
 #else  /* no TPROXY support */
@@ -6802,7 +6802,7 @@ out_uri_auth_compat:
                                }
                        }
 
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
                        if (curproxy->conn_src.bind_hdr_occ) {
                                curproxy->conn_src.bind_hdr_occ = 0;
                                Warning("config : %s '%s' : ignoring use of 
header %s as source IP in non-HTTP mode.\n",
@@ -6829,7 +6829,7 @@ out_uri_auth_compat:
                                err_code |= ERR_WARN;
                        }
 
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(HAP_TRANSPARENT)
                        if (curproxy->mode != PR_MODE_HTTP && 
newsrv->conn_src.bind_hdr_occ) {
                                newsrv->conn_src.bind_hdr_occ = 0;
                                Warning("config : %s '%s' : server %s cannot 
use header %s as source IP in non-HTTP mode.\n",
diff --git a/src/haproxy.c b/src/haproxy.c
index dd1adcd..01e43b1 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -289,6 +289,29 @@ void display_build_opts()
 #else /* USE_OPENSSL */
        printf("Built without OpenSSL support (USE_OPENSSL not set)\n");
 #endif
+
+#ifdef HAP_TRANSPARENT
+  printf("Built with 'transparent proxy' support using:"
+  #if defined(SOL_IP)       && defined(IP_TRANSPARENT)
+    " IP_TRANSPARENT"
+  #endif
+  #if defined(SOL_IPV6)     && defined(IPV6_TRANSPARENT)
+    " IPV6_TRANSPARENT"
+  #endif
+  #if defined(SOL_IP)       && defined(IP_FREEBIND)
+    " IP_FREEBIND"
+  #endif
+  #if defined(IPPROTO_IP)   && defined(IP_BINDANY)
+    " IP_BINDANY"
+  #endif
+  #if defined(IPPROTO_IPV6) && defined(IPV6_BINDANY)
+    " IPV6_BINDANY"
+  #endif
+  #if defined(SOL_SOCKET)   && defined(SO_BINDANY)
+    " SO_BINDANY"
+  #endif
+  "\n");
+#endif
        putchar('\n');
 
        list_pollers(stdout);
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 781b24a..14a0184 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -123,14 +123,26 @@ int tcp_bind_socket(int fd, int flags, struct 
sockaddr_storage *local, struct so
        int foreign_ok = 0;
        int ret;
 
-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef HAP_TRANSPARENT
        static int ip_transp_working = 1;
        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)
+                       int ret = 0;
+                       #if defined(SOL_IP)       && defined(IP_TRANSPARENT)
+                       ret |= setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(SOL_IP)       && defined(IP_FREEBIND)
+                       ret |= setsockopt(fd, SOL_IP, IP_FREEBIND, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(IPPROTO_IP)   && defined(IP_BINDANY)
+                       ret |= setsockopt(fd, IPPROTO_IP, IP_BINDANY, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(SOL_SOCKET)   && defined(SO_BINDANY)
+                       ret |= setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, 
sizeof(one)) == 0;
+                       #endif
+                       if (ret)
                                foreign_ok = 1;
                        else
                                ip_transp_working = 0;
@@ -138,7 +150,14 @@ int tcp_bind_socket(int fd, int flags, struct 
sockaddr_storage *local, struct so
                break;
        case AF_INET6:
                if (flags && ip6_transp_working) {
-                       if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, 
sizeof(one)) == 0)
+                       int ret = 0;
+                       #if defined(SOL_IPV6)     && defined(IPV6_TRANSPARENT)
+                       ret |= setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(IPPROTO_IPV6) && defined(IPV6_BINDANY)
+                       ret |= setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &one, 
sizeof(one)) == 0;
+                       #endif                  
+                       if (ret)
                                foreign_ok = 1;
                        else
                                ip6_transp_working = 0;
@@ -621,18 +640,36 @@ int tcp_bind_listener(struct listener *listener, char 
*errmsg, int errlen)
        if (!ext)
                setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
 #endif
-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef HAP_TRANSPARENT
        if (!ext && (listener->options & LI_O_FOREIGN)) {
+               int ret = 0;
                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)) {
+                       #if defined(SOL_IP)       && defined(IP_TRANSPARENT)
+                       ret = ret || setsockopt(fd, SOL_IP, IP_TRANSPARENT, 
&one, sizeof(one)) == 0;
+                       #endif
+                       #if defined(SOL_IP)       && defined(IP_FREEBIND)
+                       ret = ret || setsockopt(fd, SOL_IP, IP_FREEBIND, &one, 
sizeof(one)) == 0;
+                       #endif
+                       #if defined(IPPROTO_IP)   && defined(IP_BINDANY)
+                       ret = ret || setsockopt(fd, IPPROTO_IP, IP_BINDANY, 
&one, sizeof(one)) == 0;
+                       #endif
+                       #if defined(SOL_SOCKET)   && defined(SO_BINDANY)
+                       ret = ret || setsockopt(fd, SOL_SOCKET, SO_BINDANY, 
&one, sizeof(one)) == 0;
+                       #endif
+                       if (!ret){
                                msg = "cannot make listening socket 
transparent";
                                err |= ERR_ALERT;
                        }
-               break;
+               break;  
                case AF_INET6:
-                       if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, 
sizeof(one)) == -1) {
+                       #if defined(SOL_IPV6)     && defined(IPV6_TRANSPARENT)
+                       ret = ret || setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, 
&one, sizeof(one)) == 0;
+                       #endif
+                       #if defined(IPPROTO_IPV6) && defined(IPV6_BINDANY)
+                       ret = ret || setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, 
&one, sizeof(one)) == 0;
+                       #endif                  
+                       if (!ret) {
                                msg = "cannot make listening socket 
transparent";
                                err |= ERR_ALERT;
                        }
@@ -1546,7 +1583,7 @@ static int bind_parse_v6only(char **args, int cur_arg, 
struct proxy *px, struct
 }
 #endif
 
-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef HAP_TRANSPARENT
 /* parse the "transparent" bind keyword */
 static int bind_parse_transparent(char **args, int cur_arg, struct proxy *px, 
struct bind_conf *conf, char **err)
 {
@@ -1695,7 +1732,7 @@ static struct bind_kw_list bind_kws = { "TCP", { }, {
 #ifdef TCP_FASTOPEN
        { "tfo",           bind_parse_tfo,          0 }, /* enable TCP_FASTOPEN 
of listening socket */
 #endif
-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef HAP_TRANSPARENT
        { "transparent",   bind_parse_transparent,  0 }, /* transparently bind 
to the specified addresses */
 #endif
 #ifdef IPV6_V6ONLY

Reply via email to