Hello community,

here is the log from the commit of package nginx for openSUSE:Factory checked 
in at 2019-12-02 11:33:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/nginx (Old)
 and      /work/SRC/openSUSE:Factory/.nginx.new.4691 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "nginx"

Mon Dec  2 11:33:28 2019 rev:43 rq:752658 version:1.17.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/nginx/nginx.changes      2019-10-28 
17:00:28.797766053 +0100
+++ /work/SRC/openSUSE:Factory/.nginx.new.4691/nginx.changes    2019-12-02 
11:38:04.206457257 +0100
@@ -1,0 +2,10 @@
+Sat Nov 23 20:12:57 UTC 2019 - Marcus Rueckert <[email protected]>
+
+- Update to 1.17.6
+  - Feature: the $proxy_protocol_server_addr and
+    $proxy_protocol_server_port variables.
+  - Feature: the "limit_conn_dry_run" directive.
+  - Feature: the $limit_req_status and $limit_conn_status
+    variables.
+
+-------------------------------------------------------------------

Old:
----
  nginx-1.17.5.tar.gz
  nginx-1.17.5.tar.gz.asc

New:
----
  nginx-1.17.6.tar.gz
  nginx-1.17.6.tar.gz.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ nginx.spec ++++++
--- /var/tmp/diff_new_pack.CYJgCo/_old  2019-12-02 11:38:04.814457385 +0100
+++ /var/tmp/diff_new_pack.CYJgCo/_new  2019-12-02 11:38:04.818457385 +0100
@@ -70,7 +70,7 @@
 %define ngx_doc_dir    %{_datadir}/doc/packages/%{name}
 #
 Name:           nginx
-Version:        1.17.5
+Version:        1.17.6
 Release:        0
 %define ngx_fancyindex_version 0.4.2
 %define ngx_fancyindex_module_path ngx-fancyindex-%{ngx_fancyindex_version}

++++++ nginx-1.17.5.tar.gz -> nginx-1.17.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/CHANGES new/nginx-1.17.6/CHANGES
--- old/nginx-1.17.5/CHANGES    2019-10-22 17:16:13.000000000 +0200
+++ new/nginx-1.17.6/CHANGES    2019-11-19 15:19:02.000000000 +0100
@@ -1,4 +1,14 @@
 
+Changes with nginx 1.17.6                                        19 Nov 2019
+
+    *) Feature: the $proxy_protocol_server_addr and
+       $proxy_protocol_server_port variables.
+
+    *) Feature: the "limit_conn_dry_run" directive.
+
+    *) Feature: the $limit_req_status and $limit_conn_status variables.
+
+
 Changes with nginx 1.17.5                                        22 Oct 2019
 
     *) Feature: now nginx uses ioctl(FIONREAD), if available, to avoid
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/CHANGES.ru new/nginx-1.17.6/CHANGES.ru
--- old/nginx-1.17.5/CHANGES.ru 2019-10-22 17:16:11.000000000 +0200
+++ new/nginx-1.17.6/CHANGES.ru 2019-11-19 15:19:01.000000000 +0100
@@ -1,4 +1,14 @@
 
+Изменения в nginx 1.17.6                                          19.11.2019
+
+    *) Добавление: переменные $proxy_protocol_server_addr и
+       $proxy_protocol_server_port.
+
+    *) Добавление: директива limit_conn_dry_run.
+
+    *) Добавление: переменные $limit_req_status и $limit_conn_status.
+
+
 Изменения в nginx 1.17.5                                          22.10.2019
 
     *) Добавление: теперь nginx использует вызов ioctl(FIONREAD), если он
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/core/nginx.h 
new/nginx-1.17.6/src/core/nginx.h
--- old/nginx-1.17.5/src/core/nginx.h   2019-10-22 17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/core/nginx.h   2019-11-19 15:18:58.000000000 +0100
@@ -9,8 +9,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version      1017005
-#define NGINX_VERSION      "1.17.5"
+#define nginx_version      1017006
+#define NGINX_VERSION      "1.17.6"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #ifdef NGX_BUILD
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/core/ngx_connection.h 
new/nginx-1.17.6/src/core/ngx_connection.h
--- old/nginx-1.17.5/src/core/ngx_connection.h  2019-10-22 17:16:08.000000000 
+0200
+++ new/nginx-1.17.6/src/core/ngx_connection.h  2019-11-19 15:18:58.000000000 
+0100
@@ -147,8 +147,7 @@
     socklen_t           socklen;
     ngx_str_t           addr_text;
 
-    ngx_str_t           proxy_protocol_addr;
-    in_port_t           proxy_protocol_port;
+    ngx_proxy_protocol_t  *proxy_protocol;
 
 #if (NGX_SSL || NGX_COMPAT)
     ngx_ssl_connection_t  *ssl;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/core/ngx_core.h 
new/nginx-1.17.6/src/core/ngx_core.h
--- old/nginx-1.17.5/src/core/ngx_core.h        2019-10-22 17:16:08.000000000 
+0200
+++ new/nginx-1.17.6/src/core/ngx_core.h        2019-11-19 15:18:58.000000000 
+0100
@@ -26,6 +26,7 @@
 typedef struct ngx_connection_s      ngx_connection_t;
 typedef struct ngx_thread_task_s     ngx_thread_task_t;
 typedef struct ngx_ssl_s             ngx_ssl_t;
+typedef struct ngx_proxy_protocol_s  ngx_proxy_protocol_t;
 typedef struct ngx_ssl_connection_s  ngx_ssl_connection_t;
 typedef struct ngx_udp_connection_s  ngx_udp_connection_t;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/core/ngx_proxy_protocol.c 
new/nginx-1.17.6/src/core/ngx_proxy_protocol.c
--- old/nginx-1.17.5/src/core/ngx_proxy_protocol.c      2019-10-22 
17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/core/ngx_proxy_protocol.c      2019-11-19 
15:18:58.000000000 +0100
@@ -40,6 +40,10 @@
 } ngx_proxy_protocol_inet6_addrs_t;
 
 
+static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,
+    u_char *last, ngx_str_t *addr);
+static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,
+    in_port_t *port, u_char sep);
 static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
     u_char *last);
 
@@ -47,9 +51,9 @@
 u_char *
 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
 {
-    size_t     len;
-    u_char     ch, *p, *addr, *port;
-    ngx_int_t  n;
+    size_t                 len;
+    u_char                *p;
+    ngx_proxy_protocol_t  *pp;
 
     static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
 
@@ -83,11 +87,77 @@
     }
 
     p += 5;
-    addr = p;
+
+    pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
+    if (pp == NULL) {
+        return NULL;
+    }
+
+    p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr);
+    if (p == NULL) {
+        goto invalid;
+    }
+
+    p = ngx_proxy_protocol_read_addr(c, p, last, &pp->dst_addr);
+    if (p == NULL) {
+        goto invalid;
+    }
+
+    p = ngx_proxy_protocol_read_port(p, last, &pp->src_port, ' ');
+    if (p == NULL) {
+        goto invalid;
+    }
+
+    p = ngx_proxy_protocol_read_port(p, last, &pp->dst_port, CR);
+    if (p == NULL) {
+        goto invalid;
+    }
+
+    if (p == last) {
+        goto invalid;
+    }
+
+    if (*p++ != LF) {
+        goto invalid;
+    }
+
+    ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
+                   "PROXY protocol src: %V %d, dst: %V %d",
+                   &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
+
+    c->proxy_protocol = pp;
+
+    return p;
+
+skip:
+
+    for ( /* void */ ; p < last - 1; p++) {
+        if (p[0] == CR && p[1] == LF) {
+            return p + 2;
+        }
+    }
+
+invalid:
+
+    ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                  "broken header: \"%*s\"", (size_t) (last - buf), buf);
+
+    return NULL;
+}
+
+
+static u_char *
+ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, u_char *last,
+    ngx_str_t *addr)
+{
+    size_t  len;
+    u_char  ch, *pos;
+
+    pos = p;
 
     for ( ;; ) {
         if (p == last) {
-            goto invalid;
+            return NULL;
         }
 
         ch = *p++;
@@ -101,70 +171,54 @@
             && (ch < 'A' || ch > 'F')
             && (ch < '0' || ch > '9'))
         {
-            goto invalid;
+            return NULL;
         }
     }
 
-    len = p - addr - 1;
-    c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len);
+    len = p - pos - 1;
 
-    if (c->proxy_protocol_addr.data == NULL) {
+    addr->data = ngx_pnalloc(c->pool, len);
+    if (addr->data == NULL) {
         return NULL;
     }
 
-    ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
-    c->proxy_protocol_addr.len = len;
+    ngx_memcpy(addr->data, pos, len);
+    addr->len = len;
 
-    for ( ;; ) {
-        if (p == last) {
-            goto invalid;
-        }
+    return p;
+}
 
-        if (*p++ == ' ') {
-            break;
-        }
-    }
 
-    port = p;
+static u_char *
+ngx_proxy_protocol_read_port(u_char *p, u_char *last, in_port_t *port,
+    u_char sep)
+{
+    size_t      len;
+    u_char     *pos;
+    ngx_int_t   n;
+
+    pos = p;
 
     for ( ;; ) {
         if (p == last) {
-            goto invalid;
+            return NULL;
         }
 
-        if (*p++ == ' ') {
+        if (*p++ == sep) {
             break;
         }
     }
 
-    len = p - port - 1;
-
-    n = ngx_atoi(port, len);
+    len = p - pos - 1;
 
+    n = ngx_atoi(pos, len);
     if (n < 0 || n > 65535) {
-        goto invalid;
-    }
-
-    c->proxy_protocol_port = (in_port_t) n;
-
-    ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
-                   "PROXY protocol address: %V %d", &c->proxy_protocol_addr,
-                   c->proxy_protocol_port);
-
-skip:
-
-    for ( /* void */ ; p < last - 1; p++) {
-        if (p[0] == CR && p[1] == LF) {
-            return p + 2;
-        }
+        return NULL;
     }
 
-invalid:
-
-    ngx_log_error(NGX_LOG_ERR, c->log, 0,
-                  "broken header: \"%*s\"", (size_t) (last - buf), buf);
+    *port = (in_port_t) n;
 
-    return NULL;
+    return p;
 }
 
 
@@ -219,7 +273,8 @@
     size_t                              len;
     socklen_t                           socklen;
     ngx_uint_t                          version, command, family, transport;
-    ngx_sockaddr_t                      sockaddr;
+    ngx_sockaddr_t                      src_sockaddr, dst_sockaddr;
+    ngx_proxy_protocol_t               *pp;
     ngx_proxy_protocol_header_t        *header;
     ngx_proxy_protocol_inet_addrs_t    *in;
 #if (NGX_HAVE_INET6)
@@ -266,6 +321,11 @@
         return end;
     }
 
+    pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
+    if (pp == NULL) {
+        return NULL;
+    }
+
     family = header->family_transport >> 4;
 
     switch (family) {
@@ -278,11 +338,16 @@
 
         in = (ngx_proxy_protocol_inet_addrs_t *) buf;
 
-        sockaddr.sockaddr_in.sin_family = AF_INET;
-        sockaddr.sockaddr_in.sin_port = 0;
-        memcpy(&sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
+        src_sockaddr.sockaddr_in.sin_family = AF_INET;
+        src_sockaddr.sockaddr_in.sin_port = 0;
+        memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
+
+        dst_sockaddr.sockaddr_in.sin_family = AF_INET;
+        dst_sockaddr.sockaddr_in.sin_port = 0;
+        memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);
 
-        c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(in->src_port);
+        pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
+        pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);
 
         socklen = sizeof(struct sockaddr_in);
 
@@ -300,11 +365,16 @@
 
         in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf;
 
-        sockaddr.sockaddr_in6.sin6_family = AF_INET6;
-        sockaddr.sockaddr_in6.sin6_port = 0;
-        memcpy(&sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
+        src_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
+        src_sockaddr.sockaddr_in6.sin6_port = 0;
+        memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
+
+        dst_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
+        dst_sockaddr.sockaddr_in6.sin6_port = 0;
+        memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);
 
-        c->proxy_protocol_port = 
ngx_proxy_protocol_parse_uint16(in6->src_port);
+        pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
+        pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);
 
         socklen = sizeof(struct sockaddr_in6);
 
@@ -321,23 +391,32 @@
         return end;
     }
 
-    c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
-    if (c->proxy_protocol_addr.data == NULL) {
+    pp->src_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
+    if (pp->src_addr.data == NULL) {
+        return NULL;
+    }
+
+    pp->src_addr.len = ngx_sock_ntop(&src_sockaddr.sockaddr, socklen,
+                                     pp->src_addr.data, NGX_SOCKADDR_STRLEN, 
0);
+
+    pp->dst_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
+    if (pp->dst_addr.data == NULL) {
         return NULL;
     }
 
-    c->proxy_protocol_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen,
-                                               c->proxy_protocol_addr.data,
-                                               NGX_SOCKADDR_STRLEN, 0);
-
-    ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
-                   "PROXY protocol v2 address: %V %d", &c->proxy_protocol_addr,
-                   c->proxy_protocol_port);
+    pp->dst_addr.len = ngx_sock_ntop(&dst_sockaddr.sockaddr, socklen,
+                                     pp->dst_addr.data, NGX_SOCKADDR_STRLEN, 
0);
+
+    ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
+                   "PROXY protocol v2 src: %V %d, dst: %V %d",
+                   &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
 
     if (buf < end) {
         ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
                        "PROXY protocol v2 %z bytes of tlv ignored", end - buf);
     }
 
+    c->proxy_protocol = pp;
+
     return end;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/core/ngx_proxy_protocol.h 
new/nginx-1.17.6/src/core/ngx_proxy_protocol.h
--- old/nginx-1.17.5/src/core/ngx_proxy_protocol.h      2019-10-22 
17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/core/ngx_proxy_protocol.h      2019-11-19 
15:18:58.000000000 +0100
@@ -16,6 +16,14 @@
 #define NGX_PROXY_PROTOCOL_MAX_HEADER  107
 
 
+struct ngx_proxy_protocol_s {
+    ngx_str_t           src_addr;
+    ngx_str_t           dst_addr;
+    in_port_t           src_port;
+    in_port_t           dst_port;
+};
+
+
 u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
     u_char *last);
 u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/nginx-1.17.5/src/http/modules/ngx_http_limit_conn_module.c 
new/nginx-1.17.6/src/http/modules/ngx_http_limit_conn_module.c
--- old/nginx-1.17.5/src/http/modules/ngx_http_limit_conn_module.c      
2019-10-22 17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/http/modules/ngx_http_limit_conn_module.c      
2019-11-19 15:18:58.000000000 +0100
@@ -10,36 +10,49 @@
 #include <ngx_http.h>
 
 
+#define NGX_HTTP_LIMIT_CONN_PASSED            1
+#define NGX_HTTP_LIMIT_CONN_REJECTED          2
+#define NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN  3
+
+
 typedef struct {
-    u_char                     color;
-    u_char                     len;
-    u_short                    conn;
-    u_char                     data[1];
+    u_char                        color;
+    u_char                        len;
+    u_short                       conn;
+    u_char                        data[1];
 } ngx_http_limit_conn_node_t;
 
 
 typedef struct {
-    ngx_shm_zone_t            *shm_zone;
-    ngx_rbtree_node_t         *node;
+    ngx_shm_zone_t               *shm_zone;
+    ngx_rbtree_node_t            *node;
 } ngx_http_limit_conn_cleanup_t;
 
 
 typedef struct {
-    ngx_rbtree_t              *rbtree;
-    ngx_http_complex_value_t   key;
+    ngx_rbtree_t                  rbtree;
+    ngx_rbtree_node_t             sentinel;
+} ngx_http_limit_conn_shctx_t;
+
+
+typedef struct {
+    ngx_http_limit_conn_shctx_t  *sh;
+    ngx_slab_pool_t              *shpool;
+    ngx_http_complex_value_t      key;
 } ngx_http_limit_conn_ctx_t;
 
 
 typedef struct {
-    ngx_shm_zone_t            *shm_zone;
-    ngx_uint_t                 conn;
+    ngx_shm_zone_t               *shm_zone;
+    ngx_uint_t                    conn;
 } ngx_http_limit_conn_limit_t;
 
 
 typedef struct {
-    ngx_array_t                limits;
-    ngx_uint_t                 log_level;
-    ngx_uint_t                 status_code;
+    ngx_array_t                   limits;
+    ngx_uint_t                    log_level;
+    ngx_uint_t                    status_code;
+    ngx_flag_t                    dry_run;
 } ngx_http_limit_conn_conf_t;
 
 
@@ -48,6 +61,8 @@
 static void ngx_http_limit_conn_cleanup(void *data);
 static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool);
 
+static ngx_int_t ngx_http_limit_conn_status_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 static void *ngx_http_limit_conn_create_conf(ngx_conf_t *cf);
 static char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent,
     void *child);
@@ -55,6 +70,7 @@
     void *conf);
 static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+static ngx_int_t ngx_http_limit_conn_add_variables(ngx_conf_t *cf);
 static ngx_int_t ngx_http_limit_conn_init(ngx_conf_t *cf);
 
 
@@ -102,12 +118,19 @@
       offsetof(ngx_http_limit_conn_conf_t, status_code),
       &ngx_http_limit_conn_status_bounds },
 
+    { ngx_string("limit_conn_dry_run"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_limit_conn_conf_t, dry_run),
+      NULL },
+
       ngx_null_command
 };
 
 
 static ngx_http_module_t  ngx_http_limit_conn_module_ctx = {
-    NULL,                                  /* preconfiguration */
+    ngx_http_limit_conn_add_variables,     /* preconfiguration */
     ngx_http_limit_conn_init,              /* postconfiguration */
 
     NULL,                                  /* create main configuration */
@@ -137,6 +160,22 @@
 };
 
 
+static ngx_http_variable_t  ngx_http_limit_conn_vars[] = {
+
+    { ngx_string("limit_conn_status"), NULL,
+      ngx_http_limit_conn_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
+      ngx_http_null_variable
+};
+
+
+static ngx_str_t  ngx_http_limit_conn_status[] = {
+    ngx_string("PASSED"),
+    ngx_string("REJECTED"),
+    ngx_string("REJECTED_DRY_RUN")
+};
+
+
 static ngx_int_t
 ngx_http_limit_conn_handler(ngx_http_request_t *r)
 {
@@ -144,7 +183,6 @@
     uint32_t                        hash;
     ngx_str_t                       key;
     ngx_uint_t                      i;
-    ngx_slab_pool_t                *shpool;
     ngx_rbtree_node_t              *node;
     ngx_pool_cleanup_t             *cln;
     ngx_http_limit_conn_ctx_t      *ctx;
@@ -153,7 +191,7 @@
     ngx_http_limit_conn_limit_t    *limits;
     ngx_http_limit_conn_cleanup_t  *lccln;
 
-    if (r->main->limit_conn_set) {
+    if (r->main->limit_conn_status) {
         return NGX_DECLINED;
     }
 
@@ -179,15 +217,13 @@
             continue;
         }
 
-        r->main->limit_conn_set = 1;
+        r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_PASSED;
 
         hash = ngx_crc32_short(key.data, key.len);
 
-        shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr;
-
-        ngx_shmtx_lock(&shpool->mutex);
+        ngx_shmtx_lock(&ctx->shpool->mutex);
 
-        node = ngx_http_limit_conn_lookup(ctx->rbtree, &key, hash);
+        node = ngx_http_limit_conn_lookup(&ctx->sh->rbtree, &key, hash);
 
         if (node == NULL) {
 
@@ -195,11 +231,20 @@
                 + offsetof(ngx_http_limit_conn_node_t, data)
                 + key.len;
 
-            node = ngx_slab_alloc_locked(shpool, n);
+            node = ngx_slab_alloc_locked(ctx->shpool, n);
 
             if (node == NULL) {
-                ngx_shmtx_unlock(&shpool->mutex);
+                ngx_shmtx_unlock(&ctx->shpool->mutex);
                 ngx_http_limit_conn_cleanup_all(r->pool);
+
+                if (lccf->dry_run) {
+                    r->main->limit_conn_status =
+                                          NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN;
+                    return NGX_DECLINED;
+                }
+
+                r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_REJECTED;
+
                 return lccf->status_code;
             }
 
@@ -210,7 +255,7 @@
             lc->conn = 1;
             ngx_memcpy(lc->data, key.data, key.len);
 
-            ngx_rbtree_insert(ctx->rbtree, node);
+            ngx_rbtree_insert(&ctx->sh->rbtree, node);
 
         } else {
 
@@ -218,13 +263,23 @@
 
             if ((ngx_uint_t) lc->conn >= limits[i].conn) {
 
-                ngx_shmtx_unlock(&shpool->mutex);
+                ngx_shmtx_unlock(&ctx->shpool->mutex);
 
                 ngx_log_error(lccf->log_level, r->connection->log, 0,
-                              "limiting connections by zone \"%V\"",
+                              "limiting connections%s by zone \"%V\"",
+                              lccf->dry_run ? ", dry run," : "",
                               &limits[i].shm_zone->shm.name);
 
                 ngx_http_limit_conn_cleanup_all(r->pool);
+
+                if (lccf->dry_run) {
+                    r->main->limit_conn_status =
+                                          NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN;
+                    return NGX_DECLINED;
+                }
+
+                r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_REJECTED;
+
                 return lccf->status_code;
             }
 
@@ -234,7 +289,7 @@
         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "limit conn: %08Xi %d", node->key, lc->conn);
 
-        ngx_shmtx_unlock(&shpool->mutex);
+        ngx_shmtx_unlock(&ctx->shpool->mutex);
 
         cln = ngx_pool_cleanup_add(r->pool,
                                    sizeof(ngx_http_limit_conn_cleanup_t));
@@ -338,17 +393,15 @@
 {
     ngx_http_limit_conn_cleanup_t  *lccln = data;
 
-    ngx_slab_pool_t             *shpool;
     ngx_rbtree_node_t           *node;
     ngx_http_limit_conn_ctx_t   *ctx;
     ngx_http_limit_conn_node_t  *lc;
 
     ctx = lccln->shm_zone->data;
-    shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
     node = lccln->node;
     lc = (ngx_http_limit_conn_node_t *) &node->color;
 
-    ngx_shmtx_lock(&shpool->mutex);
+    ngx_shmtx_lock(&ctx->shpool->mutex);
 
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0,
                    "limit conn cleanup: %08Xi %d", node->key, lc->conn);
@@ -356,11 +409,11 @@
     lc->conn--;
 
     if (lc->conn == 0) {
-        ngx_rbtree_delete(ctx->rbtree, node);
-        ngx_slab_free_locked(shpool, node);
+        ngx_rbtree_delete(&ctx->sh->rbtree, node);
+        ngx_slab_free_locked(ctx->shpool, node);
     }
 
-    ngx_shmtx_unlock(&shpool->mutex);
+    ngx_shmtx_unlock(&ctx->shpool->mutex);
 }
 
 
@@ -386,8 +439,6 @@
     ngx_http_limit_conn_ctx_t  *octx = data;
 
     size_t                      len;
-    ngx_slab_pool_t            *shpool;
-    ngx_rbtree_node_t          *sentinel;
     ngx_http_limit_conn_ctx_t  *ctx;
 
     ctx = shm_zone->data;
@@ -406,48 +457,63 @@
             return NGX_ERROR;
         }
 
-        ctx->rbtree = octx->rbtree;
+        ctx->sh = octx->sh;
+        ctx->shpool = octx->shpool;
 
         return NGX_OK;
     }
 
-    shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
+    ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
     if (shm_zone->shm.exists) {
-        ctx->rbtree = shpool->data;
+        ctx->sh = ctx->shpool->data;
 
         return NGX_OK;
     }
 
-    ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
-    if (ctx->rbtree == NULL) {
+    ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_conn_shctx_t));
+    if (ctx->sh == NULL) {
         return NGX_ERROR;
     }
 
-    shpool->data = ctx->rbtree;
+    ctx->shpool->data = ctx->sh;
 
-    sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
-    if (sentinel == NULL) {
-        return NGX_ERROR;
-    }
-
-    ngx_rbtree_init(ctx->rbtree, sentinel,
+    ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel,
                     ngx_http_limit_conn_rbtree_insert_value);
 
     len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len;
 
-    shpool->log_ctx = ngx_slab_alloc(shpool, len);
-    if (shpool->log_ctx == NULL) {
+    ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len);
+    if (ctx->shpool->log_ctx == NULL) {
         return NGX_ERROR;
     }
 
-    ngx_sprintf(shpool->log_ctx, " in limit_conn_zone \"%V\"%Z",
+    ngx_sprintf(ctx->shpool->log_ctx, " in limit_conn_zone \"%V\"%Z",
                 &shm_zone->shm.name);
 
     return NGX_OK;
 }
 
 
+static ngx_int_t
+ngx_http_limit_conn_status_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    if (r->main->limit_conn_status == 0) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+    v->len = ngx_http_limit_conn_status[r->main->limit_conn_status - 1].len;
+    v->data = ngx_http_limit_conn_status[r->main->limit_conn_status - 1].data;
+
+    return NGX_OK;
+}
+
+
 static void *
 ngx_http_limit_conn_create_conf(ngx_conf_t *cf)
 {
@@ -466,6 +532,7 @@
 
     conf->log_level = NGX_CONF_UNSET_UINT;
     conf->status_code = NGX_CONF_UNSET_UINT;
+    conf->dry_run = NGX_CONF_UNSET;
 
     return conf;
 }
@@ -485,6 +552,8 @@
     ngx_conf_merge_uint_value(conf->status_code, prev->status_code,
                               NGX_HTTP_SERVICE_UNAVAILABLE);
 
+    ngx_conf_merge_value(conf->dry_run, prev->dry_run, 0);
+
     return NGX_CONF_OK;
 }
 
@@ -651,6 +720,25 @@
 }
 
 
+static ngx_int_t
+ngx_http_limit_conn_add_variables(ngx_conf_t *cf)
+{
+    ngx_http_variable_t  *var, *v;
+
+    for (v = ngx_http_limit_conn_vars; v->name.len; v++) {
+        var = ngx_http_add_variable(cf, &v->name, v->flags);
+        if (var == NULL) {
+            return NGX_ERROR;
+        }
+
+        var->get_handler = v->get_handler;
+        var->data = v->data;
+    }
+
+    return NGX_OK;
+}
+
+
 static ngx_int_t
 ngx_http_limit_conn_init(ngx_conf_t *cf)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/nginx-1.17.5/src/http/modules/ngx_http_limit_req_module.c 
new/nginx-1.17.6/src/http/modules/ngx_http_limit_req_module.c
--- old/nginx-1.17.5/src/http/modules/ngx_http_limit_req_module.c       
2019-10-22 17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/http/modules/ngx_http_limit_req_module.c       
2019-11-19 15:18:58.000000000 +0100
@@ -10,6 +10,13 @@
 #include <ngx_http.h>
 
 
+#define NGX_HTTP_LIMIT_REQ_PASSED            1
+#define NGX_HTTP_LIMIT_REQ_DELAYED           2
+#define NGX_HTTP_LIMIT_REQ_REJECTED          3
+#define NGX_HTTP_LIMIT_REQ_DELAYED_DRY_RUN   4
+#define NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN  5
+
+
 typedef struct {
     u_char                       color;
     u_char                       dummy;
@@ -65,6 +72,8 @@
 static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
     ngx_uint_t n);
 
+static ngx_int_t ngx_http_limit_req_status_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 static void *ngx_http_limit_req_create_conf(ngx_conf_t *cf);
 static char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent,
     void *child);
@@ -72,6 +81,7 @@
     void *conf);
 static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+static ngx_int_t ngx_http_limit_req_add_variables(ngx_conf_t *cf);
 static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf);
 
 
@@ -131,7 +141,7 @@
 
 
 static ngx_http_module_t  ngx_http_limit_req_module_ctx = {
-    NULL,                                  /* preconfiguration */
+    ngx_http_limit_req_add_variables,      /* preconfiguration */
     ngx_http_limit_req_init,               /* postconfiguration */
 
     NULL,                                  /* create main configuration */
@@ -161,6 +171,24 @@
 };
 
 
+static ngx_http_variable_t  ngx_http_limit_req_vars[] = {
+
+    { ngx_string("limit_req_status"), NULL,
+      ngx_http_limit_req_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
+      ngx_http_null_variable
+};
+
+
+static ngx_str_t  ngx_http_limit_req_status[] = {
+    ngx_string("PASSED"),
+    ngx_string("DELAYED"),
+    ngx_string("REJECTED"),
+    ngx_string("DELAYED_DRY_RUN"),
+    ngx_string("REJECTED_DRY_RUN")
+};
+
+
 static ngx_int_t
 ngx_http_limit_req_handler(ngx_http_request_t *r)
 {
@@ -173,7 +201,7 @@
     ngx_http_limit_req_conf_t   *lrcf;
     ngx_http_limit_req_limit_t  *limit, *limits;
 
-    if (r->main->limit_req_set) {
+    if (r->main->limit_req_status) {
         return NGX_DECLINED;
     }
 
@@ -232,8 +260,6 @@
         return NGX_DECLINED;
     }
 
-    r->main->limit_req_set = 1;
-
     if (rc == NGX_BUSY || rc == NGX_ERROR) {
 
         if (rc == NGX_BUSY) {
@@ -261,9 +287,12 @@
         }
 
         if (lrcf->dry_run) {
+            r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN;
             return NGX_DECLINED;
         }
 
+        r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED;
+
         return lrcf->status_code;
     }
 
@@ -276,6 +305,7 @@
     delay = ngx_http_limit_req_account(limits, n, &excess, &limit);
 
     if (!delay) {
+        r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_PASSED;
         return NGX_DECLINED;
     }
 
@@ -285,9 +315,12 @@
                   excess / 1000, excess % 1000, &limit->shm_zone->shm.name);
 
     if (lrcf->dry_run) {
+        r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_DELAYED_DRY_RUN;
         return NGX_DECLINED;
     }
 
+    r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_DELAYED;
+
     if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
@@ -711,6 +744,25 @@
 }
 
 
+static ngx_int_t
+ngx_http_limit_req_status_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    if (r->main->limit_req_status == 0) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+    v->len = ngx_http_limit_req_status[r->main->limit_req_status - 1].len;
+    v->data = ngx_http_limit_req_status[r->main->limit_req_status - 1].data;
+
+    return NGX_OK;
+}
+
+
 static void *
 ngx_http_limit_req_create_conf(ngx_conf_t *cf)
 {
@@ -995,6 +1047,25 @@
 }
 
 
+static ngx_int_t
+ngx_http_limit_req_add_variables(ngx_conf_t *cf)
+{
+    ngx_http_variable_t  *var, *v;
+
+    for (v = ngx_http_limit_req_vars; v->name.len; v++) {
+        var = ngx_http_add_variable(cf, &v->name, v->flags);
+        if (var == NULL) {
+            return NGX_ERROR;
+        }
+
+        var->get_handler = v->get_handler;
+        var->data = v->data;
+    }
+
+    return NGX_OK;
+}
+
+
 static ngx_int_t
 ngx_http_limit_req_init(ngx_conf_t *cf)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/nginx-1.17.5/src/http/modules/ngx_http_realip_module.c 
new/nginx-1.17.6/src/http/modules/ngx_http_realip_module.c
--- old/nginx-1.17.5/src/http/modules/ngx_http_realip_module.c  2019-10-22 
17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/http/modules/ngx_http_realip_module.c  2019-11-19 
15:18:58.000000000 +0100
@@ -180,12 +180,11 @@
 
     case NGX_HTTP_REALIP_PROXY:
 
-        value = &r->connection->proxy_protocol_addr;
-
-        if (value->len == 0) {
+        if (r->connection->proxy_protocol == NULL) {
             return NGX_DECLINED;
         }
 
+        value = &r->connection->proxy_protocol->src_addr;
         xfwd = NULL;
 
         break;
@@ -238,7 +237,7 @@
         != NGX_DECLINED)
     {
         if (rlcf->type == NGX_HTTP_REALIP_PROXY) {
-            ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port);
+            ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port);
         }
 
         return ngx_http_realip_set_addr(r, &addr);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/http/ngx_http_request.h 
new/nginx-1.17.6/src/http/ngx_http_request.h
--- old/nginx-1.17.5/src/http/ngx_http_request.h        2019-10-22 
17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/http/ngx_http_request.h        2019-11-19 
15:18:58.000000000 +0100
@@ -510,10 +510,10 @@
     /*
      * instead of using the request context data in
      * ngx_http_limit_conn_module and ngx_http_limit_req_module
-     * we use the single bits in the request structure
+     * we use the bit fields in the request structure
      */
-    unsigned                          limit_conn_set:1;
-    unsigned                          limit_req_set:1;
+    unsigned                          limit_conn_status:2;
+    unsigned                          limit_req_status:3;
 
     unsigned                          limit_rate_set:1;
     unsigned                          limit_rate_after_set:1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/http/ngx_http_variables.c 
new/nginx-1.17.6/src/http/ngx_http_variables.c
--- old/nginx-1.17.5/src/http/ngx_http_variables.c      2019-10-22 
17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/http/ngx_http_variables.c      2019-11-19 
15:18:58.000000000 +0100
@@ -199,10 +199,20 @@
     { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 
},
 
     { ngx_string("proxy_protocol_addr"), NULL,
-      ngx_http_variable_proxy_protocol_addr, 0, 0, 0 },
+      ngx_http_variable_proxy_protocol_addr,
+      offsetof(ngx_proxy_protocol_t, src_addr), 0, 0 },
 
     { ngx_string("proxy_protocol_port"), NULL,
-      ngx_http_variable_proxy_protocol_port, 0, 0, 0 },
+      ngx_http_variable_proxy_protocol_port,
+      offsetof(ngx_proxy_protocol_t, src_port), 0, 0 },
+
+    { ngx_string("proxy_protocol_server_addr"), NULL,
+      ngx_http_variable_proxy_protocol_addr,
+      offsetof(ngx_proxy_protocol_t, dst_addr), 0, 0 },
+
+    { ngx_string("proxy_protocol_server_port"), NULL,
+      ngx_http_variable_proxy_protocol_port,
+      offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },
 
     { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 
},
 
@@ -1293,11 +1303,22 @@
 ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    v->len = r->connection->proxy_protocol_addr.len;
+    ngx_str_t             *addr;
+    ngx_proxy_protocol_t  *pp;
+
+    pp = r->connection->proxy_protocol;
+    if (pp == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    addr = (ngx_str_t *) ((char *) pp + data);
+
+    v->len = addr->len;
     v->valid = 1;
     v->no_cacheable = 0;
     v->not_found = 0;
-    v->data = r->connection->proxy_protocol_addr.data;
+    v->data = addr->data;
 
     return NGX_OK;
 }
@@ -1307,7 +1328,14 @@
 ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    ngx_uint_t  port;
+    ngx_uint_t             port;
+    ngx_proxy_protocol_t  *pp;
+
+    pp = r->connection->proxy_protocol;
+    if (pp == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
 
     v->len = 0;
     v->valid = 1;
@@ -1319,7 +1347,7 @@
         return NGX_ERROR;
     }
 
-    port = r->connection->proxy_protocol_port;
+    port = *(in_port_t *) ((char *) pp + data);
 
     if (port > 0 && port < 65536) {
         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/stream/ngx_stream.h 
new/nginx-1.17.6/src/stream/ngx_stream.h
--- old/nginx-1.17.5/src/stream/ngx_stream.h    2019-10-22 17:16:08.000000000 
+0200
+++ new/nginx-1.17.6/src/stream/ngx_stream.h    2019-11-19 15:18:58.000000000 
+0100
@@ -226,6 +226,8 @@
     unsigned                       stat_processing:1;
 
     unsigned                       health_check:1;
+
+    unsigned                       limit_conn_status:2;
 };
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/nginx-1.17.5/src/stream/ngx_stream_limit_conn_module.c 
new/nginx-1.17.6/src/stream/ngx_stream_limit_conn_module.c
--- old/nginx-1.17.5/src/stream/ngx_stream_limit_conn_module.c  2019-10-22 
17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/stream/ngx_stream_limit_conn_module.c  2019-11-19 
15:18:58.000000000 +0100
@@ -10,35 +10,48 @@
 #include <ngx_stream.h>
 
 
+#define NGX_STREAM_LIMIT_CONN_PASSED            1
+#define NGX_STREAM_LIMIT_CONN_REJECTED          2
+#define NGX_STREAM_LIMIT_CONN_REJECTED_DRY_RUN  3
+
+
 typedef struct {
-    u_char                       color;
-    u_char                       len;
-    u_short                      conn;
-    u_char                       data[1];
+    u_char                          color;
+    u_char                          len;
+    u_short                         conn;
+    u_char                          data[1];
 } ngx_stream_limit_conn_node_t;
 
 
 typedef struct {
-    ngx_shm_zone_t              *shm_zone;
-    ngx_rbtree_node_t           *node;
+    ngx_shm_zone_t                 *shm_zone;
+    ngx_rbtree_node_t              *node;
 } ngx_stream_limit_conn_cleanup_t;
 
 
 typedef struct {
-    ngx_rbtree_t                *rbtree;
-    ngx_stream_complex_value_t   key;
+    ngx_rbtree_t                    rbtree;
+    ngx_rbtree_node_t               sentinel;
+} ngx_stream_limit_conn_shctx_t;
+
+
+typedef struct {
+    ngx_stream_limit_conn_shctx_t  *sh;
+    ngx_slab_pool_t                *shpool;
+    ngx_stream_complex_value_t      key;
 } ngx_stream_limit_conn_ctx_t;
 
 
 typedef struct {
-    ngx_shm_zone_t              *shm_zone;
-    ngx_uint_t                   conn;
+    ngx_shm_zone_t                 *shm_zone;
+    ngx_uint_t                      conn;
 } ngx_stream_limit_conn_limit_t;
 
 
 typedef struct {
-    ngx_array_t                  limits;
-    ngx_uint_t                   log_level;
+    ngx_array_t                     limits;
+    ngx_uint_t                      log_level;
+    ngx_flag_t                      dry_run;
 } ngx_stream_limit_conn_conf_t;
 
 
@@ -47,6 +60,8 @@
 static void ngx_stream_limit_conn_cleanup(void *data);
 static ngx_inline void ngx_stream_limit_conn_cleanup_all(ngx_pool_t *pool);
 
+static ngx_int_t ngx_stream_limit_conn_status_variable(ngx_stream_session_t *s,
+    ngx_stream_variable_value_t *v, uintptr_t data);
 static void *ngx_stream_limit_conn_create_conf(ngx_conf_t *cf);
 static char *ngx_stream_limit_conn_merge_conf(ngx_conf_t *cf, void *parent,
     void *child);
@@ -54,6 +69,7 @@
     void *conf);
 static char *ngx_stream_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+static ngx_int_t ngx_stream_limit_conn_add_variables(ngx_conf_t *cf);
 static ngx_int_t ngx_stream_limit_conn_init(ngx_conf_t *cf);
 
 
@@ -89,12 +105,19 @@
       offsetof(ngx_stream_limit_conn_conf_t, log_level),
       &ngx_stream_limit_conn_log_levels },
 
+    { ngx_string("limit_conn_dry_run"),
+      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_STREAM_SRV_CONF_OFFSET,
+      offsetof(ngx_stream_limit_conn_conf_t, dry_run),
+      NULL },
+
       ngx_null_command
 };
 
 
 static ngx_stream_module_t  ngx_stream_limit_conn_module_ctx = {
-    NULL,                                  /* preconfiguration */
+    ngx_stream_limit_conn_add_variables,   /* preconfiguration */
     ngx_stream_limit_conn_init,            /* postconfiguration */
 
     NULL,                                  /* create main configuration */
@@ -121,6 +144,22 @@
 };
 
 
+static ngx_stream_variable_t  ngx_stream_limit_conn_vars[] = {
+
+    { ngx_string("limit_conn_status"), NULL,
+      ngx_stream_limit_conn_status_variable, 0, NGX_STREAM_VAR_NOCACHEABLE, 0 
},
+
+      ngx_stream_null_variable
+};
+
+
+static ngx_str_t  ngx_stream_limit_conn_status[] = {
+    ngx_string("PASSED"),
+    ngx_string("REJECTED"),
+    ngx_string("REJECTED_DRY_RUN")
+};
+
+
 static ngx_int_t
 ngx_stream_limit_conn_handler(ngx_stream_session_t *s)
 {
@@ -128,7 +167,6 @@
     uint32_t                          hash;
     ngx_str_t                         key;
     ngx_uint_t                        i;
-    ngx_slab_pool_t                  *shpool;
     ngx_rbtree_node_t                *node;
     ngx_pool_cleanup_t               *cln;
     ngx_stream_limit_conn_ctx_t      *ctx;
@@ -159,13 +197,13 @@
             continue;
         }
 
-        hash = ngx_crc32_short(key.data, key.len);
+        s->limit_conn_status = NGX_STREAM_LIMIT_CONN_PASSED;
 
-        shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr;
+        hash = ngx_crc32_short(key.data, key.len);
 
-        ngx_shmtx_lock(&shpool->mutex);
+        ngx_shmtx_lock(&ctx->shpool->mutex);
 
-        node = ngx_stream_limit_conn_lookup(ctx->rbtree, &key, hash);
+        node = ngx_stream_limit_conn_lookup(&ctx->sh->rbtree, &key, hash);
 
         if (node == NULL) {
 
@@ -173,11 +211,20 @@
                 + offsetof(ngx_stream_limit_conn_node_t, data)
                 + key.len;
 
-            node = ngx_slab_alloc_locked(shpool, n);
+            node = ngx_slab_alloc_locked(ctx->shpool, n);
 
             if (node == NULL) {
-                ngx_shmtx_unlock(&shpool->mutex);
+                ngx_shmtx_unlock(&ctx->shpool->mutex);
                 ngx_stream_limit_conn_cleanup_all(s->connection->pool);
+
+                if (lccf->dry_run) {
+                    s->limit_conn_status =
+                                        NGX_STREAM_LIMIT_CONN_REJECTED_DRY_RUN;
+                    return NGX_DECLINED;
+                }
+
+                s->limit_conn_status = NGX_STREAM_LIMIT_CONN_REJECTED;
+
                 return NGX_STREAM_SERVICE_UNAVAILABLE;
             }
 
@@ -188,7 +235,7 @@
             lc->conn = 1;
             ngx_memcpy(lc->data, key.data, key.len);
 
-            ngx_rbtree_insert(ctx->rbtree, node);
+            ngx_rbtree_insert(&ctx->sh->rbtree, node);
 
         } else {
 
@@ -196,13 +243,23 @@
 
             if ((ngx_uint_t) lc->conn >= limits[i].conn) {
 
-                ngx_shmtx_unlock(&shpool->mutex);
+                ngx_shmtx_unlock(&ctx->shpool->mutex);
 
                 ngx_log_error(lccf->log_level, s->connection->log, 0,
-                              "limiting connections by zone \"%V\"",
+                              "limiting connections%s by zone \"%V\"",
+                              lccf->dry_run ? ", dry run," : "",
                               &limits[i].shm_zone->shm.name);
 
                 ngx_stream_limit_conn_cleanup_all(s->connection->pool);
+
+                if (lccf->dry_run) {
+                    s->limit_conn_status =
+                                        NGX_STREAM_LIMIT_CONN_REJECTED_DRY_RUN;
+                    return NGX_DECLINED;
+                }
+
+                s->limit_conn_status = NGX_STREAM_LIMIT_CONN_REJECTED;
+
                 return NGX_STREAM_SERVICE_UNAVAILABLE;
             }
 
@@ -212,7 +269,7 @@
         ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
                        "limit conn: %08Xi %d", node->key, lc->conn);
 
-        ngx_shmtx_unlock(&shpool->mutex);
+        ngx_shmtx_unlock(&ctx->shpool->mutex);
 
         cln = ngx_pool_cleanup_add(s->connection->pool,
                                    sizeof(ngx_stream_limit_conn_cleanup_t));
@@ -317,17 +374,15 @@
 {
     ngx_stream_limit_conn_cleanup_t  *lccln = data;
 
-    ngx_slab_pool_t               *shpool;
     ngx_rbtree_node_t             *node;
     ngx_stream_limit_conn_ctx_t   *ctx;
     ngx_stream_limit_conn_node_t  *lc;
 
     ctx = lccln->shm_zone->data;
-    shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
     node = lccln->node;
     lc = (ngx_stream_limit_conn_node_t *) &node->color;
 
-    ngx_shmtx_lock(&shpool->mutex);
+    ngx_shmtx_lock(&ctx->shpool->mutex);
 
     ngx_log_debug2(NGX_LOG_DEBUG_STREAM, lccln->shm_zone->shm.log, 0,
                    "limit conn cleanup: %08Xi %d", node->key, lc->conn);
@@ -335,11 +390,11 @@
     lc->conn--;
 
     if (lc->conn == 0) {
-        ngx_rbtree_delete(ctx->rbtree, node);
-        ngx_slab_free_locked(shpool, node);
+        ngx_rbtree_delete(&ctx->sh->rbtree, node);
+        ngx_slab_free_locked(ctx->shpool, node);
     }
 
-    ngx_shmtx_unlock(&shpool->mutex);
+    ngx_shmtx_unlock(&ctx->shpool->mutex);
 }
 
 
@@ -365,8 +420,6 @@
     ngx_stream_limit_conn_ctx_t  *octx = data;
 
     size_t                        len;
-    ngx_slab_pool_t              *shpool;
-    ngx_rbtree_node_t            *sentinel;
     ngx_stream_limit_conn_ctx_t  *ctx;
 
     ctx = shm_zone->data;
@@ -385,48 +438,64 @@
             return NGX_ERROR;
         }
 
-        ctx->rbtree = octx->rbtree;
+        ctx->sh = octx->sh;
+        ctx->shpool = octx->shpool;
 
         return NGX_OK;
     }
 
-    shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
+    ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
     if (shm_zone->shm.exists) {
-        ctx->rbtree = shpool->data;
+        ctx->sh = ctx->shpool->data;
 
         return NGX_OK;
     }
 
-    ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
-    if (ctx->rbtree == NULL) {
+    ctx->sh = ngx_slab_alloc(ctx->shpool,
+                             sizeof(ngx_stream_limit_conn_shctx_t));
+    if (ctx->sh == NULL) {
         return NGX_ERROR;
     }
 
-    shpool->data = ctx->rbtree;
+    ctx->shpool->data = ctx->sh;
 
-    sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
-    if (sentinel == NULL) {
-        return NGX_ERROR;
-    }
-
-    ngx_rbtree_init(ctx->rbtree, sentinel,
+    ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel,
                     ngx_stream_limit_conn_rbtree_insert_value);
 
     len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len;
 
-    shpool->log_ctx = ngx_slab_alloc(shpool, len);
-    if (shpool->log_ctx == NULL) {
+    ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len);
+    if (ctx->shpool->log_ctx == NULL) {
         return NGX_ERROR;
     }
 
-    ngx_sprintf(shpool->log_ctx, " in limit_conn_zone \"%V\"%Z",
+    ngx_sprintf(ctx->shpool->log_ctx, " in limit_conn_zone \"%V\"%Z",
                 &shm_zone->shm.name);
 
     return NGX_OK;
 }
 
 
+static ngx_int_t
+ngx_stream_limit_conn_status_variable(ngx_stream_session_t *s,
+    ngx_stream_variable_value_t *v, uintptr_t data)
+{
+    if (s->limit_conn_status == 0) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+    v->len = ngx_stream_limit_conn_status[s->limit_conn_status - 1].len;
+    v->data = ngx_stream_limit_conn_status[s->limit_conn_status - 1].data;
+
+    return NGX_OK;
+}
+
+
 static void *
 ngx_stream_limit_conn_create_conf(ngx_conf_t *cf)
 {
@@ -444,6 +513,7 @@
      */
 
     conf->log_level = NGX_CONF_UNSET_UINT;
+    conf->dry_run = NGX_CONF_UNSET;
 
     return conf;
 }
@@ -461,6 +531,8 @@
 
     ngx_conf_merge_uint_value(conf->log_level, prev->log_level, NGX_LOG_ERR);
 
+    ngx_conf_merge_value(conf->dry_run, prev->dry_run, 0);
+
     return NGX_CONF_OK;
 }
 
@@ -627,6 +699,25 @@
 }
 
 
+static ngx_int_t
+ngx_stream_limit_conn_add_variables(ngx_conf_t *cf)
+{
+    ngx_stream_variable_t  *var, *v;
+
+    for (v = ngx_stream_limit_conn_vars; v->name.len; v++) {
+        var = ngx_stream_add_variable(cf, &v->name, v->flags);
+        if (var == NULL) {
+            return NGX_ERROR;
+        }
+
+        var->get_handler = v->get_handler;
+        var->data = v->data;
+    }
+
+    return NGX_OK;
+}
+
+
 static ngx_int_t
 ngx_stream_limit_conn_init(ngx_conf_t *cf)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/stream/ngx_stream_realip_module.c 
new/nginx-1.17.6/src/stream/ngx_stream_realip_module.c
--- old/nginx-1.17.5/src/stream/ngx_stream_realip_module.c      2019-10-22 
17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/stream/ngx_stream_realip_module.c      2019-11-19 
15:18:58.000000000 +0100
@@ -108,7 +108,7 @@
 
     c = s->connection;
 
-    if (c->proxy_protocol_addr.len == 0) {
+    if (c->proxy_protocol == NULL) {
         return NGX_DECLINED;
     }
 
@@ -116,14 +116,14 @@
         return NGX_DECLINED;
     }
 
-    if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol_addr.data,
-                       c->proxy_protocol_addr.len)
+    if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol->src_addr.data,
+                       c->proxy_protocol->src_addr.len)
         != NGX_OK)
     {
         return NGX_DECLINED;
     }
 
-    ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port);
+    ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port);
 
     return ngx_stream_realip_set_addr(s, &addr);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nginx-1.17.5/src/stream/ngx_stream_variables.c 
new/nginx-1.17.6/src/stream/ngx_stream_variables.c
--- old/nginx-1.17.5/src/stream/ngx_stream_variables.c  2019-10-22 
17:16:08.000000000 +0200
+++ new/nginx-1.17.6/src/stream/ngx_stream_variables.c  2019-11-19 
15:18:58.000000000 +0100
@@ -64,10 +64,20 @@
       ngx_stream_variable_remote_port, 0, 0, 0 },
 
     { ngx_string("proxy_protocol_addr"), NULL,
-      ngx_stream_variable_proxy_protocol_addr, 0, 0, 0 },
+      ngx_stream_variable_proxy_protocol_addr,
+      offsetof(ngx_proxy_protocol_t, src_addr), 0, 0 },
 
     { ngx_string("proxy_protocol_port"), NULL,
-      ngx_stream_variable_proxy_protocol_port, 0, 0, 0 },
+      ngx_stream_variable_proxy_protocol_port,
+      offsetof(ngx_proxy_protocol_t, src_port), 0, 0 },
+
+    { ngx_string("proxy_protocol_server_addr"), NULL,
+      ngx_stream_variable_proxy_protocol_addr,
+      offsetof(ngx_proxy_protocol_t, dst_addr), 0, 0 },
+
+    { ngx_string("proxy_protocol_server_port"), NULL,
+      ngx_stream_variable_proxy_protocol_port,
+      offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },
 
     { ngx_string("server_addr"), NULL,
       ngx_stream_variable_server_addr, 0, 0, 0 },
@@ -557,11 +567,22 @@
 ngx_stream_variable_proxy_protocol_addr(ngx_stream_session_t *s,
     ngx_stream_variable_value_t *v, uintptr_t data)
 {
-    v->len = s->connection->proxy_protocol_addr.len;
+    ngx_str_t             *addr;
+    ngx_proxy_protocol_t  *pp;
+
+    pp = s->connection->proxy_protocol;
+    if (pp == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    addr = (ngx_str_t *) ((char *) pp + data);
+
+    v->len = addr->len;
     v->valid = 1;
     v->no_cacheable = 0;
     v->not_found = 0;
-    v->data = s->connection->proxy_protocol_addr.data;
+    v->data = addr->data;
 
     return NGX_OK;
 }
@@ -571,7 +592,14 @@
 ngx_stream_variable_proxy_protocol_port(ngx_stream_session_t *s,
     ngx_stream_variable_value_t *v, uintptr_t data)
 {
-    ngx_uint_t  port;
+    ngx_uint_t             port;
+    ngx_proxy_protocol_t  *pp;
+
+    pp = s->connection->proxy_protocol;
+    if (pp == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
 
     v->len = 0;
     v->valid = 1;
@@ -583,7 +611,7 @@
         return NGX_ERROR;
     }
 
-    port = s->connection->proxy_protocol_port;
+    port = *(in_port_t *) ((char *) pp + data);
 
     if (port > 0 && port < 65536) {
         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;



Reply via email to