int sock_inet6_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b);
int sock_inet_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
int sock_inet_is_foreign(int fd, sa_family_t family);
+int sock_inet4_make_foreign(int fd);
+int sock_inet6_make_foreign(int fd);
#endif /* _HAPROXY_SOCK_INET_H */
* 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
-#if defined(IP_BINDANY)
- || (setsockopt(fd, IPPROTO_IP, IP_BINDANY, &one, sizeof(one)) == 0)
-#endif
-#if defined(SO_BINDANY)
- || (setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, sizeof(one)) == 0)
-#endif
- )
+ if (sock_inet4_make_foreign(fd))
foreign_ok = 1;
else
ip_transp_working = 0;
break;
case AF_INET6:
if (flags && ip6_transp_working) {
- if (0
-#if defined(IPV6_TRANSPARENT) && defined(SOL_IPV6)
- || (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == 0)
-#endif
-#if defined(IP_FREEBIND)
- || (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0)
-#endif
-#if defined(IPV6_BINDANY)
- || (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &one, sizeof(one)) == 0)
-#endif
-#if defined(SO_BINDANY)
- || (setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, sizeof(one)) == 0)
-#endif
- )
+ if (sock_inet6_make_foreign(fd))
foreign_ok = 1;
else
ip6_transp_working = 0;
if (!ext && (listener->options & LI_O_FOREIGN)) {
switch (listener->addr.ss_family) {
case AF_INET:
- 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
-#if defined(IP_BINDANY)
- && (setsockopt(fd, IPPROTO_IP, IP_BINDANY, &one, sizeof(one)) == -1)
-#endif
-#if defined(SO_BINDANY)
- && (setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, sizeof(one)) == -1)
-#endif
- ) {
+ if (!sock_inet4_make_foreign(fd)) {
msg = "cannot make listening socket transparent";
err |= ERR_ALERT;
}
break;
case AF_INET6:
- if (1
-#if defined(IPV6_TRANSPARENT) && defined(SOL_IPV6)
- && (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == -1)
-#endif
-#if defined(IP_FREEBIND)
- && (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)
-#endif
-#if defined(IPV6_BINDANY)
- && (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &one, sizeof(one)) == -1)
-#endif
-#if defined(SO_BINDANY)
- && (setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, sizeof(one)) == -1)
-#endif
- ) {
+ if (!sock_inet6_make_foreign(fd)) {
msg = "cannot make listening socket transparent";
err |= ERR_ALERT;
}
return 1;
}
-REGISTER_BUILD_OPTS("Built with transparent proxy support using:"
-#if defined(IP_TRANSPARENT)
- " IP_TRANSPARENT"
-#endif
-#if defined(IPV6_TRANSPARENT)
- " IPV6_TRANSPARENT"
-#endif
-#if defined(IP_FREEBIND)
- " IP_FREEBIND"
-#endif
-#if defined(IP_BINDANY)
- " IP_BINDANY"
-#endif
-#if defined(IPV6_BINDANY)
- " IPV6_BINDANY"
-#endif
-#if defined(SO_BINDANY)
- " SO_BINDANY"
-#endif
- "");
-
/*
* Local variables:
if (listener->options & LI_O_FOREIGN) {
switch (addr_inet.ss_family) {
case AF_INET:
- 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
-#if defined(IP_BINDANY)
- && (setsockopt(fd, IPPROTO_IP, IP_BINDANY, &one, sizeof(one)) == -1)
-#endif
-#if defined(SO_BINDANY)
- && (setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, sizeof(one)) == -1)
-#endif
- ) {
+ if (!sock_inet4_make_foreign(fd)) {
msg = "cannot make listening socket transparent";
err |= ERR_ALERT;
}
break;
case AF_INET6:
- if (1
-#if defined(IPV6_TRANSPARENT) && defined(SOL_IPV6)
- && (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == -1)
-#endif
-#if defined(IP_FREEBIND)
- && (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)
-#endif
-#if defined(IPV6_BINDANY)
- && (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &one, sizeof(one)) == -1)
-#endif
-#if defined(SO_BINDANY)
- && (setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, sizeof(one)) == -1)
-#endif
- ) {
+ if (!sock_inet6_make_foreign(fd)) {
msg = "cannot make listening socket transparent";
err |= ERR_ALERT;
}
#include <netinet/in.h>
#include <haproxy/api.h>
+#include <haproxy/global.h>
#include <haproxy/sock_inet.h>
#include <haproxy/tools.h>
return 0;
}
+/* Attempt all known socket options to prepare an AF_INET4 socket to be bound
+ * to a foreign address. The socket must already exist and must not be bound.
+ * 1 is returned on success, 0 on failure. The caller must check the address
+ * family before calling this function.
+ */
+int sock_inet4_make_foreign(int fd)
+{
+ return
+#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
+#if defined(IP_BINDANY)
+ setsockopt(fd, IPPROTO_IP, IP_BINDANY, &one, sizeof(one)) == 0 ||
+#endif
+#if defined(SO_BINDANY)
+ setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, sizeof(one)) == 0 ||
+#endif
+ 0;
+}
+
+/* Attempt all known socket options to prepare an AF_INET6 socket to be bound
+ * to a foreign address. The socket must already exist and must not be bound.
+ * 1 is returned on success, 0 on failure. The caller must check the address
+ * family before calling this function.
+ */
+int sock_inet6_make_foreign(int fd)
+{
+ return
+#if defined(IPV6_TRANSPARENT) && defined(SOL_IPV6)
+ setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == 0 ||
+#endif
+#if defined(IP_FREEBIND)
+ setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0 ||
+#endif
+#if defined(IPV6_BINDANY)
+ setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &one, sizeof(one)) == 0 ||
+#endif
+#if defined(SO_BINDANY)
+ setsockopt(fd, SOL_SOCKET, SO_BINDANY, &one, sizeof(one)) == 0 ||
+#endif
+ 0;
+}
+
static void sock_inet_prepare()
{
int fd, val;
}
INITCALL0(STG_PREPARE, sock_inet_prepare);
+
+
+REGISTER_BUILD_OPTS("Built with transparent proxy support using:"
+#if defined(IP_TRANSPARENT)
+ " IP_TRANSPARENT"
+#endif
+#if defined(IPV6_TRANSPARENT)
+ " IPV6_TRANSPARENT"
+#endif
+#if defined(IP_FREEBIND)
+ " IP_FREEBIND"
+#endif
+#if defined(IP_BINDANY)
+ " IP_BINDANY"
+#endif
+#if defined(IPV6_BINDANY)
+ " IPV6_BINDANY"
+#endif
+#if defined(SO_BINDANY)
+ " SO_BINDANY"
+#endif
+ "");