aboutsummaryrefslogtreecommitdiff
path: root/src/event/ngx_event_connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/event/ngx_event_connect.c')
-rw-r--r--src/event/ngx_event_connect.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c
index 8aca86252..5de991e07 100644
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -11,6 +11,12 @@
#include <ngx_event_connect.h>
+#if (NGX_HAVE_TRANSPARENT_PROXY)
+static ngx_int_t ngx_event_connect_set_transparent(ngx_peer_connection_t *pc,
+ ngx_socket_t s);
+#endif
+
+
ngx_int_t
ngx_event_connect_peer(ngx_peer_connection_t *pc)
{
@@ -72,6 +78,15 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
}
if (pc->local) {
+
+#if (NGX_HAVE_TRANSPARENT_PROXY)
+ if (pc->transparent) {
+ if (ngx_event_connect_set_transparent(pc, s) != NGX_OK) {
+ goto failed;
+ }
+ }
+#endif
+
if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {
ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno,
"bind(%V) failed", &pc->local->name);
@@ -249,6 +264,94 @@ failed:
}
+#if (NGX_HAVE_TRANSPARENT_PROXY)
+
+static ngx_int_t
+ngx_event_connect_set_transparent(ngx_peer_connection_t *pc, ngx_socket_t s)
+{
+ int value;
+
+ value = 1;
+
+#if defined(SO_BINDANY)
+
+ if (setsockopt(s, SOL_SOCKET, SO_BINDANY,
+ (const void *) &value, sizeof(int)) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ "setsockopt(SO_BINDANY) failed");
+ return NGX_ERROR;
+ }
+
+#else
+
+ switch (pc->local->sockaddr->sa_family) {
+
+ case AF_INET:
+
+#if defined(IP_TRANSPARENT)
+
+ if (setsockopt(s, IPPROTO_IP, IP_TRANSPARENT,
+ (const void *) &value, sizeof(int)) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ "setsockopt(IP_TRANSPARENT) failed");
+ return NGX_ERROR;
+ }
+
+#elif defined(IP_BINDANY)
+
+ if (setsockopt(s, IPPROTO_IP, IP_BINDANY,
+ (const void *) &value, sizeof(int)) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ "setsockopt(IP_BINDANY) failed");
+ return NGX_ERROR;
+ }
+
+#endif
+
+ break;
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+
+#if defined(IPV6_TRANSPARENT)
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_TRANSPARENT,
+ (const void *) &value, sizeof(int)) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ "setsockopt(IPV6_TRANSPARENT) failed");
+ return NGX_ERROR;
+ }
+
+#elif defined(IPV6_BINDANY)
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY,
+ (const void *) &value, sizeof(int)) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ "setsockopt(IPV6_BINDANY) failed");
+ return NGX_ERROR;
+ }
+
+#endif
+ break;
+
+#endif /* NGX_HAVE_INET6 */
+
+ }
+
+#endif /* SO_BINDANY */
+
+ return NGX_OK;
+}
+
+#endif
+
+
ngx_int_t
ngx_event_get_peer(ngx_peer_connection_t *pc, void *data)
{