From fea078d000e18a9fc59767c845ff954e8f21d32e Mon Sep 17 00:00:00 2001
From: Miao Wang <shankerwangmiao@gmail.com>
Date: Fri, 20 Jul 2018 22:46:03 +0800
Subject: [PATCH] Add IP_TRANSPARENT support

---
 auto/unix                       | 11 +++++++++++
 src/core/ngx_connection.c       | 19 +++++++++++++++++++
 src/core/ngx_connection.h       |  4 ++++
 src/event/ngx_event_accept.c    | 13 +++++++++++++
 src/http/ngx_http.c             |  5 +++++
 src/http/ngx_http_core_module.c | 12 ++++++++++++
 src/http/ngx_http_core_module.h |  3 +++
 7 files changed, 67 insertions(+)

diff --git a/auto/unix b/auto/unix
index 43d3b25..2b229f7 100644
--- a/auto/unix
+++ b/auto/unix
@@ -312,6 +312,17 @@ ngx_feature_test="cpu_set_t mask;
 . auto/feature
 
 
+ngx_feature="IP_TRANSPARENT"
+ngx_feature_name="NGX_HAVE_TRANSPARENT"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/socket.h>
+                  #include <netinet/in.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="setsockopt(0, SOL_IP, IP_TRANSPARENT, NULL, 0)"
+. auto/feature
+
+
 ngx_feature="SO_SETFIB"
 ngx_feature_name="NGX_HAVE_SETFIB"
 ngx_feature_run=no
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 3368253..55661e3 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -560,6 +560,25 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
             }
 #endif
 
+#if (NGX_HAVE_TRANSPARENT && defined IP_TRANSPARENT)
+
+	    if (ls[i].transparent) {
+	        int  transparent;
+
+		transparent = (ls[i].transparent == 1);
+
+		if (setsockopt(s, SOL_IP, IP_TRANSPARENT,
+                               (const void *) &transparent, sizeof(int))
+                    == -1)
+		{
+		    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                                  "setsockopt(IP_TRANSPARENT) for %V failed, "
+				  "ignored",
+                                  &ls[i].addr_text);
+		}
+	    }
+#endif
+
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
 
             if (ls[i].sockaddr->sa_family == AF_INET6) {
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index 5405962..9055f96 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -90,6 +90,10 @@ struct ngx_listening_s {
     int                 fastopen;
 #endif
 
+#if (NGX_HAVE_TRANSPARENT && defined IP_TRANSPARENT)
+    unsigned            transparent:1;
+#endif
+
 };
 
 
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index 4364240..2b0ae95 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -212,8 +212,21 @@ ngx_event_accept(ngx_event_t *ev)
 
         c->socklen = socklen;
         c->listening = ls;
+#if (NGX_HAVE_TRANSPARENT && defined IP_TRANSPARENT)
+        if(ls->transparent) {
+            c->local_sockaddr = NULL;
+            c->local_socklen = 0;
+            if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
+                ngx_close_accepted_connection(c);
+                return;
+            }
+        }else{
+#endif
         c->local_sockaddr = ls->sockaddr;
         c->local_socklen = ls->socklen;
+#if (NGX_HAVE_TRANSPARENT && defined IP_TRANSPARENT)
+        }
+#endif
 
 #if (NGX_HAVE_UNIX_DOMAIN)
         if (c->sockaddr->sa_family == AF_UNIX) {
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 5e20226..b274e91 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1738,6 +1738,11 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
     ls->sndbuf = addr->opt.sndbuf;
 
     ls->keepalive = addr->opt.so_keepalive;
+
+#if (NGX_HAVE_TRANSPARENT && defined IP_TRANSPARENT)
+    ls->transparent = addr->opt.transparent;
+#endif
+
 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
     ls->keepidle = addr->opt.tcp_keepidle;
     ls->keepintvl = addr->opt.tcp_keepintvl;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index c57ec00..97d9a48 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -3913,6 +3913,18 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
             continue;
         }
 
+	if (ngx_strcmp(value[n].data, "transparent") == 0) {
+#if (NGX_HAVE_TRANSPARENT && defined IP_TRANSPARENT)
+	    lsopt.transparent = 1;
+#else
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+	                       "transparent mode is not supported "
+			       "on this platform, ignored",
+			       &value[n]);
+#endif
+	    continue;
+	}
+
         if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) {
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
             struct sockaddr  *sa;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 4c6da7c..a77e609 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -81,6 +81,9 @@ typedef struct {
     unsigned                   reuseport:1;
     unsigned                   so_keepalive:2;
     unsigned                   proxy_protocol:1;
+#if (NGX_HAVE_TRANSPARENT && defined IP_TRANSPARENT)
+    unsigned                   transparent:1;
+#endif
 
     int                        backlog;
     int                        rcvbuf;
-- 
2.7.4

