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