#endif /* !IPV6_TRANSPARENT */
#endif /* CONFIG_HAP_LINUX_TPROXY */
+#if defined(IP_FREEBIND) \
+ || defined(IP_TRANSPARENT) \
+ || defined(IPV6_TRANSPARENT)
+#define CONFIG_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
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(CONFIG_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 */
*/
static void assign_tproxy_address(struct session *s)
{
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
struct server *srv = objt_server(s->target);
struct conn_src *src;
curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
curproxy->conn_src.opts = defproxy.conn_src.opts;
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
#endif
}
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(CONFIG_HAP_TRANSPARENT)
+#if !defined(CONFIG_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");
newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
}
global.last_checks |= LSTCHK_NETADM;
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if !defined(CONFIG_HAP_TRANSPARENT)
global.last_checks |= LSTCHK_CTTPROXY;
#endif
cur_arg += 2;
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(CONFIG_HAP_TRANSPARENT) */
} /* "usesrc" */
if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
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(CONFIG_HAP_TRANSPARENT)
+#if !defined(CONFIG_HAP_TRANSPARENT)
if (!is_addr(&curproxy->conn_src.source_addr)) {
Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
file, linenum, "usesrc");
curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
}
global.last_checks |= LSTCHK_NETADM;
-#if !defined(CONFIG_HAP_LINUX_TPROXY)
+#if !defined(CONFIG_HAP_TRANSPARENT)
global.last_checks |= LSTCHK_CTTPROXY;
#endif
#else /* no TPROXY support */
}
}
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_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",
err_code |= ERR_WARN;
}
-#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
+#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_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",
printf("Built without PCRE support (using libc's regex instead)\n");
#endif
+#if defined(CONFIG_HAP_TRANSPARENT) || defined(CONFIG_HAP_CTTPROXY)
+ printf("Built with transparent proxy support using:"
+#if defined(CONFIG_HAP_CTTPROXY)
+ " CTTPROXY"
+#endif
+#if defined(IP_TRANSPARENT)
+ " IP_TRANSPARENT"
+#endif
+#if defined(IPV6_TRANSPARENT)
+ " IPV6_TRANSPARENT"
+#endif
+#if defined(IP_FREEBIND)
+ " IP_FREEBIND"
+#endif
+ "\n");
+#endif
putchar('\n');
list_pollers(stdout);
struct sockaddr_storage bind_addr;
int foreign_ok = 0;
int ret;
-
-#ifdef CONFIG_HAP_LINUX_TPROXY
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)
+ /* This deserves some explanation. Some platforms will support
+ * multiple combinations of certain methods, so we try the
+ * supported ones until one succeeds.
+ */
+ if (0
+#if defined(IP_TRANSPARENT)
+ || (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == 0)
+#endif
+#if defined(IP_FREEBIND)
+ || (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0)
+#endif
+ )
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)
+ if (0
+#if defined(IPV6_TRANSPARENT)
+ || (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == 0)
+#endif
+ )
foreign_ok = 1;
else
ip6_transp_working = 0;
}
break;
}
-#endif
+
if (flags) {
memset(&bind_addr, 0, sizeof(bind_addr));
bind_addr.ss_family = remote->ss_family;
if (!ext)
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
#endif
-#ifdef CONFIG_HAP_LINUX_TPROXY
+
if (!ext && (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)) {
+ if (1
+#if defined(IP_TRANSPARENT)
+ && (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == -1)
+#endif
+#if defined(IP_FREEBIND)
+ && (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)
+#endif
+ ) {
msg = "cannot make listening socket transparent";
err |= ERR_ALERT;
}
break;
case AF_INET6:
- if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == -1) {
+ if (1
+#if defined(IPV6_TRANSPARENT)
+ && (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == -1)
+#endif
+ ) {
msg = "cannot make listening socket transparent";
err |= ERR_ALERT;
}
break;
}
}
-#endif
+
#ifdef SO_BINDTODEVICE
/* Note: this might fail if not CAP_NET_RAW */
if (!ext && listener->interface) {
}
#endif
-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef CONFIG_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)
{
#ifdef TCP_FASTOPEN
{ "tfo", bind_parse_tfo, 0 }, /* enable TCP_FASTOPEN of listening socket */
#endif
-#ifdef CONFIG_HAP_LINUX_TPROXY
+#ifdef CONFIG_HAP_TRANSPARENT
{ "transparent", bind_parse_transparent, 0 }, /* transparently bind to the specified addresses */
#endif
#ifdef IPV6_V6ONLY