summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornginx <nginx@nginx.org>2015-06-16 15:24:45 +0000
committerJon Kolb <kolbyjack@gmail.com>2015-06-16 15:24:45 +0000
commitf01c6309faeddd6cb719419376cb61c4da08b3e6 (patch)
tree1ca626f034ba419c612bf14664aac08192eecd32
parent2db2346e9858b0e2bc441fe293f1581a1b3371ae (diff)
downloadnginx-1.9.tar.gz
Changes with nginx 1.9.2 16 Jun 2015v1.9.2nginx-1.9
*) Feature: the "backlog" parameter of the "listen" directives of the mail proxy and stream modules. *) Feature: the "allow" and "deny" directives in the stream module. *) Feature: the "proxy_bind" directive in the stream module. *) Feature: the "proxy_protocol" directive in the stream module. *) Feature: the -T switch. *) Feature: the REQUEST_SCHEME parameter added to the fastcgi.conf, fastcgi_params, scgi_params, and uwsgi_params standard configuration files. *) Bugfix: the "reuseport" parameter of the "listen" directive of the stream module did not work. *) Bugfix: OCSP stapling might return an expired OCSP response in some cases.
-rw-r--r--CHANGES40
-rw-r--r--CHANGES.ru31
-rw-r--r--auto/cc/gcc2
-rw-r--r--auto/install4
-rw-r--r--auto/lib/openssl/conf48
-rw-r--r--auto/make8
-rw-r--r--auto/modules5
-rw-r--r--auto/options4
-rw-r--r--auto/sources6
-rw-r--r--conf/fastcgi.conf1
-rw-r--r--conf/fastcgi_params1
-rw-r--r--conf/scgi_params1
-rw-r--r--conf/uwsgi_params1
-rw-r--r--man/nginx.88
-rw-r--r--src/core/nginx.c30
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_conf_file.c47
-rw-r--r--src/core/ngx_conf_file.h7
-rw-r--r--src/core/ngx_core.h1
-rw-r--r--src/core/ngx_cycle.c8
-rw-r--r--src/core/ngx_cycle.h2
-rw-r--r--src/core/ngx_log.h15
-rw-r--r--src/core/ngx_parse_time.c (renamed from src/http/ngx_http_parse_time.c)3
-rw-r--r--src/core/ngx_parse_time.h22
-rw-r--r--src/core/ngx_proxy_protocol.c51
-rw-r--r--src/core/ngx_proxy_protocol.h4
-rw-r--r--src/event/ngx_event.c3
-rw-r--r--src/event/ngx_event_openssl_stapling.c68
-rw-r--r--src/event/ngx_event_pipe.c2
-rw-r--r--src/http/modules/ngx_http_dav_module.c2
-rw-r--r--src/http/modules/ngx_http_headers_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_not_modified_filter_module.c4
-rw-r--r--src/http/modules/ngx_http_range_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_upstream_keepalive_module.c81
-rw-r--r--src/http/ngx_http.h5
-rw-r--r--src/http/ngx_http_core_module.c4
-rw-r--r--src/http/ngx_http_request.c4
-rw-r--r--src/http/ngx_http_spdy.c2
-rw-r--r--src/http/ngx_http_upstream.c6
-rw-r--r--src/mail/ngx_mail.c71
-rw-r--r--src/mail/ngx_mail.h34
-rw-r--r--src/mail/ngx_mail_core_module.c28
-rw-r--r--src/os/unix/ngx_files.h1
-rw-r--r--src/stream/ngx_stream.c89
-rw-r--r--src/stream/ngx_stream.h38
-rw-r--r--src/stream/ngx_stream_access_module.c451
-rw-r--r--src/stream/ngx_stream_core_module.c30
-rw-r--r--src/stream/ngx_stream_handler.c37
-rw-r--r--src/stream/ngx_stream_proxy_module.c178
-rw-r--r--src/stream/ngx_stream_ssl_module.c2
-rw-r--r--src/stream/ngx_stream_upstream.c2
-rw-r--r--src/stream/ngx_stream_upstream.h2
-rw-r--r--src/stream/ngx_stream_upstream_hash_module.c2
-rw-r--r--src/stream/ngx_stream_upstream_least_conn_module.c2
-rw-r--r--src/stream/ngx_stream_upstream_zone_module.c2
55 files changed, 1256 insertions, 252 deletions
diff --git a/CHANGES b/CHANGES
index abb5e2959..f4d77d79c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,28 @@
+Changes with nginx 1.9.2 16 Jun 2015
+
+ *) Feature: the "backlog" parameter of the "listen" directives of the
+ mail proxy and stream modules.
+
+ *) Feature: the "allow" and "deny" directives in the stream module.
+
+ *) Feature: the "proxy_bind" directive in the stream module.
+
+ *) Feature: the "proxy_protocol" directive in the stream module.
+
+ *) Feature: the -T switch.
+
+ *) Feature: the REQUEST_SCHEME parameter added to the fastcgi.conf,
+ fastcgi_params, scgi_params, and uwsgi_params standard configuration
+ files.
+
+ *) Bugfix: the "reuseport" parameter of the "listen" directive of the
+ stream module did not work.
+
+ *) Bugfix: OCSP stapling might return an expired OCSP response in some
+ cases.
+
+
Changes with nginx 1.9.1 26 May 2015
*) Change: now SSLv3 protocol is disabled by default.
@@ -1467,7 +1491,7 @@ Changes with nginx 1.1.11 12 Dec 2011
Changes with nginx 1.1.10 30 Nov 2011
- *) Bugfix: a segmentation fault occured in a worker process if AIO was
+ *) Bugfix: a segmentation fault occurred in a worker process if AIO was
used on Linux; the bug had appeared in 1.1.9.
@@ -1744,7 +1768,7 @@ Changes with nginx 1.1.0 01 Aug 2011
and proxies to an HTTPS backend.
Thanks to Maxim Dounin.
- *) Bugfix: in parameter validaiton of a "proxy_pass" directive with
+ *) Bugfix: in parameter validation of a "proxy_pass" directive with
variables.
Thanks to Lanshun Zhou.
@@ -4509,7 +4533,7 @@ Changes with nginx 0.5.22 29 May 2007
Changes with nginx 0.5.21 28 May 2007
*) Bugfix: if server has more than about ten locations, then regex
- locations might be choosen not in that order as they were specified.
+ locations might be chosen not in that order as they were specified.
*) Bugfix: a worker process may got caught in an endless loop on 64-bit
platform, if the 33-rd or next in succession backend has failed.
@@ -4595,7 +4619,7 @@ Changes with nginx 0.5.17 02 Apr 2007
*) Bugfix: in the HTTPS protocol in the "proxy_pass" directive.
- *) Bugfix: in some cases non-cachable variables (such as $uri variable)
+ *) Bugfix: in some cases non-cacheable variables (such as $uri variable)
returned old cached value.
@@ -4620,7 +4644,7 @@ Changes with nginx 0.5.16 26 Mar 2007
Changes with nginx 0.5.15 19 Mar 2007
*) Feature: the mail proxy supports authenticated SMTP proxying and the
- "smtp_auth", "smtp_capablities", and "xclient" directives.
+ "smtp_auth", "smtp_capabilities", and "xclient" directives.
Thanks to Anton Yuzhaninov and Maxim Dounin.
*) Feature: now the keep-alive connections are closed just after
@@ -5721,7 +5745,7 @@ Changes with nginx 0.3.21 16 Jan 2006
*) Feature: the ngx_http_perl_module.
- *) Change: the "valid_referers" directive allows the referreres without
+ *) Change: the "valid_referers" directive allows the referrers without
URI part.
@@ -5821,7 +5845,7 @@ Changes with nginx 0.3.15 07 Dec 2005
*) Feature: the "so_keepalive" directive in IMAP/POP3 proxy.
*) Bugfix: if there are unclosed connection nginx now calls abort() only
- on gracefull quit and active "debug_points" directive.
+ on graceful quit and active "debug_points" directive.
Changes with nginx 0.3.14 05 Dec 2005
@@ -6362,7 +6386,7 @@ Changes with nginx 0.1.37 23 Jun 2005
*) Bugfix: the responses may be transferred not completely, if many
parts or the big parts were included by SSI.
- *) Bugfix: if all backends had returned the 404 reponse and the
+ *) Bugfix: if all backends had returned the 404 response and the
"http_404" parameter of the "proxy_next_upstream" or
"fastcgi_next_upstream" directives was used, then nginx started to
request all backends again.
diff --git a/CHANGES.ru b/CHANGES.ru
index b70c132a4..ac40495b9 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,28 @@
+Изменения в nginx 1.9.2 16.06.2015
+
+ *) Добавление: параметр backlog директивы listen в почтовом
+ прокси-сервере и модуле stream.
+
+ *) Добавление: директивы allow и deny в модуле stream.
+
+ *) Добавление: директива proxy_bind в модуле stream.
+
+ *) Добавление: директива proxy_protocol в модуле stream.
+
+ *) Добавление: ключ -T.
+
+ *) Добавление: параметр REQUEST_SCHEME добавлен в стандартные
+ конфигурационные файлы fastcgi.conf, fastcgi_params, scgi_params и
+ uwsgi_params.
+
+ *) Исправление: параметр reuseport директивы listen в модуле stream не
+ работал.
+
+ *) Исправление: OCSP stapling в некоторых случаях мог вернуть устаревший
+ OCSP-ответ.
+
+
Изменения в nginx 1.9.1 26.05.2015
*) Изменение: теперь протокол SSLv3 по умолчанию запрещён.
@@ -83,7 +107,7 @@
прокси-сервере.
Спасибо Sven Peter, Franck Levionnois и Filipe Da Silva.
- *) Добавление: уменьшение времени запуска при использовании дирекивы
+ *) Добавление: уменьшение времени запуска при использовании директивы
"hash ... consistent" в блоке upstream.
Спасибо Wai Keen Woon.
@@ -4721,7 +4745,8 @@
Изменения в nginx 0.5.15 19.03.2007
*) Добавление: почтовый прокси-сервер поддерживает аутентифицированное
- SMTP-проксирование и директивы smtp_auth, smtp_capablities и xclient.
+ SMTP-проксирование и директивы smtp_auth, smtp_capabilities и
+ xclient.
Спасибо Антону Южанинову и Максиму Дунину.
*) Добавление: теперь keep-alive соединения закрываются сразу же по
@@ -5926,7 +5951,7 @@
*) Добавление: директива so_keepalive в IMAP/POP3 прокси.
*) Исправление: nginx теперь вызывает abort() при обнаружении незакрытых
- соединений только при планом выходе и включённой директиве
+ соединений только при плавном выходе и включённой директиве
debug_points.
diff --git a/auto/cc/gcc b/auto/cc/gcc
index 727f11e1d..c9101fea1 100644
--- a/auto/cc/gcc
+++ b/auto/cc/gcc
@@ -153,7 +153,7 @@ CFLAGS="$CFLAGS -Wall -Wpointer-arith"
case "$NGX_GCC_VER" in
- 3.* | 4.* )
+ [3-5].*)
# we have a lot of the unused function arguments
CFLAGS="$CFLAGS -Wno-unused-parameter"
# 4.2.1 shows the warning in wrong places
diff --git a/auto/install b/auto/install
index 254f9bce6..f7f686c1a 100644
--- a/auto/install
+++ b/auto/install
@@ -20,10 +20,6 @@ case ".$NGX_SBIN_PATH" in
./*)
;;
- .)
- NGX_SBIN_PATH=$NGX_PREFIX/sbin/nginx
- ;;
-
*)
NGX_SBIN_PATH=$NGX_PREFIX/$NGX_SBIN_PATH
;;
diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf
index a65815f63..bca205061 100644
--- a/auto/lib/openssl/conf
+++ b/auto/lib/openssl/conf
@@ -55,6 +55,54 @@ else
ngx_feature_test="SSL_library_init()"
. auto/feature
+ if [ $ngx_found = no ]; then
+
+ # FreeBSD port
+
+ ngx_feature="OpenSSL library in /usr/local/"
+ ngx_feature_path="/usr/local/include"
+
+ if [ $NGX_RPATH = YES ]; then
+ ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lssl -lcrypto"
+ else
+ ngx_feature_libs="-L/usr/local/lib -lssl -lcrypto"
+ fi
+
+ . auto/feature
+ fi
+
+ if [ $ngx_found = no ]; then
+
+ # NetBSD port
+
+ ngx_feature="OpenSSL library in /usr/pkg/"
+ ngx_feature_path="/usr/pkg/include"
+
+ if [ $NGX_RPATH = YES ]; then
+ ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lssl -lcrypto"
+ else
+ ngx_feature_libs="-L/usr/pkg/lib -lssl -lcrypto"
+ fi
+
+ . auto/feature
+ fi
+
+ if [ $ngx_found = no ]; then
+
+ # MacPorts
+
+ ngx_feature="OpenSSL library in /opt/local/"
+ ngx_feature_path="/opt/local/include"
+
+ if [ $NGX_RPATH = YES ]; then
+ ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lssl -lcrypto"
+ else
+ ngx_feature_libs="-L/opt/local/lib -lssl -lcrypto"
+ fi
+
+ . auto/feature
+ fi
+
if [ $ngx_found = yes ]; then
have=NGX_SSL . auto/have
CORE_LIBS="$CORE_LIBS $ngx_feature_libs $NGX_LIBDL"
diff --git a/auto/make b/auto/make
index 98c2e3b58..78d0422ce 100644
--- a/auto/make
+++ b/auto/make
@@ -50,7 +50,7 @@ END
ngx_all_srcs="$CORE_SRCS"
-# the core dependences and include paths
+# the core dependencies and include paths
ngx_deps=`echo $CORE_DEPS $NGX_AUTO_CONFIG_H $NGX_PCH \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \
@@ -70,7 +70,7 @@ CORE_INCS = $ngx_include_opt$ngx_incs
END
-# the http dependences and include paths
+# the http dependencies and include paths
if [ $HTTP = YES ]; then
@@ -96,7 +96,7 @@ END
fi
-# the mail dependences and include paths
+# the mail dependencies and include paths
if [ $MAIL = YES ]; then
@@ -122,7 +122,7 @@ END
fi
-# the stream dependences and include paths
+# the stream dependencies and include paths
if [ $STREAM = YES ]; then
diff --git a/auto/modules b/auto/modules
index de3dc4a64..82b8bca33 100644
--- a/auto/modules
+++ b/auto/modules
@@ -514,6 +514,11 @@ if [ $STREAM = YES ]; then
STREAM_SRCS="$STREAM_SRCS $STREAM_SSL_SRCS"
fi
+ if [ $STREAM_ACCESS = YES ]; then
+ modules="$modules $STREAM_ACCESS_MODULE"
+ STREAM_SRCS="$STREAM_SRCS $STREAM_ACCESS_SRCS"
+ fi
+
if [ $STREAM_UPSTREAM_HASH = YES ]; then
modules="$modules $STREAM_UPSTREAM_HASH_MODULE"
STREAM_SRCS="$STREAM_SRCS $STREAM_UPSTREAM_HASH_SRCS"
diff --git a/auto/options b/auto/options
index e3a7edead..febbc2783 100644
--- a/auto/options
+++ b/auto/options
@@ -113,6 +113,7 @@ MAIL_SMTP=YES
STREAM=NO
STREAM_SSL=NO
+STREAM_ACCESS=YES
STREAM_UPSTREAM_HASH=YES
STREAM_UPSTREAM_LEAST_CONN=YES
STREAM_UPSTREAM_ZONE=YES
@@ -282,6 +283,7 @@ use the \"--with-mail_ssl_module\" option instead"
--with-stream) STREAM=YES ;;
--with-stream_ssl_module) STREAM_SSL=YES ;;
+ --without-stream_access_module) STREAM_ACCESS=NO ;;
--without-stream_upstream_hash_module)
STREAM_UPSTREAM_HASH=NO ;;
--without-stream_upstream_least_conn_module)
@@ -450,6 +452,7 @@ cat << END
--with-stream enable TCP proxy module
--with-stream_ssl_module enable ngx_stream_ssl_module
+ --without-stream_access_module disable ngx_stream_access_module
--without-stream_upstream_hash_module
disable ngx_stream_upstream_hash_module
--without-stream_upstream_least_conn_module
@@ -522,6 +525,7 @@ if [ ".$NGX_PLATFORM" = ".win32" ]; then
fi
+NGX_SBIN_PATH=${NGX_SBIN_PATH:-sbin/nginx}
NGX_CONF_PATH=${NGX_CONF_PATH:-conf/nginx.conf}
NGX_CONF_PREFIX=`dirname $NGX_CONF_PATH`
NGX_PID_PATH=${NGX_PID_PATH:-logs/nginx.pid}
diff --git a/auto/sources b/auto/sources
index 156db56fa..44fba5159 100644
--- a/auto/sources
+++ b/auto/sources
@@ -19,6 +19,7 @@ CORE_DEPS="src/core/nginx.h \
src/core/ngx_queue.h \
src/core/ngx_string.h \
src/core/ngx_parse.h \
+ src/core/ngx_parse_time.h \
src/core/ngx_inet.h \
src/core/ngx_file.h \
src/core/ngx_crc.h \
@@ -53,6 +54,7 @@ CORE_SRCS="src/core/nginx.c \
src/core/ngx_output_chain.c \
src/core/ngx_string.c \
src/core/ngx_parse.c \
+ src/core/ngx_parse_time.c \
src/core/ngx_inet.c \
src/core/ngx_file.c \
src/core/ngx_crc32.c \
@@ -303,7 +305,6 @@ HTTP_SRCS="src/http/ngx_http.c \
src/http/ngx_http_script.c \
src/http/ngx_http_upstream.c \
src/http/ngx_http_upstream_round_robin.c \
- src/http/ngx_http_parse_time.c \
src/http/modules/ngx_http_static_module.c \
src/http/modules/ngx_http_index_module.c \
src/http/modules/ngx_http_chunked_filter_module.c \
@@ -567,6 +568,9 @@ STREAM_SSL_MODULE="ngx_stream_ssl_module"
STREAM_SSL_DEPS="src/stream/ngx_stream_ssl_module.h"
STREAM_SSL_SRCS="src/stream/ngx_stream_ssl_module.c"
+STREAM_ACCESS_MODULE=ngx_stream_access_module
+STREAM_ACCESS_SRCS=src/stream/ngx_stream_access_module.c
+
STREAM_UPSTREAM_HASH_MODULE=ngx_stream_upstream_hash_module
STREAM_UPSTREAM_HASH_SRCS=src/stream/ngx_stream_upstream_hash_module.c
diff --git a/conf/fastcgi.conf b/conf/fastcgi.conf
index ac9ff9204..091738c60 100644
--- a/conf/fastcgi.conf
+++ b/conf/fastcgi.conf
@@ -10,6 +10,7 @@ fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
+fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
diff --git a/conf/fastcgi_params b/conf/fastcgi_params
index 71e2c2e3b..28decb955 100644
--- a/conf/fastcgi_params
+++ b/conf/fastcgi_params
@@ -9,6 +9,7 @@ fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
+fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
diff --git a/conf/scgi_params b/conf/scgi_params
index 47348ca38..6d4ce4f3e 100644
--- a/conf/scgi_params
+++ b/conf/scgi_params
@@ -8,6 +8,7 @@ scgi_param DOCUMENT_URI $document_uri;
scgi_param DOCUMENT_ROOT $document_root;
scgi_param SCGI 1;
scgi_param SERVER_PROTOCOL $server_protocol;
+scgi_param REQUEST_SCHEME $scheme;
scgi_param HTTPS $https if_not_empty;
scgi_param REMOTE_ADDR $remote_addr;
diff --git a/conf/uwsgi_params b/conf/uwsgi_params
index f539451b6..09c732cd6 100644
--- a/conf/uwsgi_params
+++ b/conf/uwsgi_params
@@ -8,6 +8,7 @@ uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
+uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
diff --git a/man/nginx.8 b/man/nginx.8
index f119a2327..1f4dc893b 100644
--- a/man/nginx.8
+++ b/man/nginx.8
@@ -25,7 +25,7 @@
.\" SUCH DAMAGE.
.\"
.\"
-.Dd March 6, 2012
+.Dd June 16, 2015
.Dt NGINX 8
.Os
.Sh NAME
@@ -33,7 +33,7 @@
.Nd "HTTP and reverse proxy server, mail proxy server"
.Sh SYNOPSIS
.Nm
-.Op Fl ?hqtVv
+.Op Fl ?hqTtVv
.Op Fl c Ar file
.Op Fl g Ar directives
.Op Fl p Ar prefix
@@ -87,6 +87,10 @@ Do not run, just test the configuration file.
.Nm
checks the configuration file syntax and then tries to open files
referenced in the configuration file.
+.It Fl T
+Same as
+.Fl t ,
+but additionally dump configuration files to standard output.
.It Fl V
Print the
.Nm
diff --git a/src/core/nginx.c b/src/core/nginx.c
index 231a3daf5..3213527ec 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -176,9 +176,11 @@ static char **ngx_os_environ;
int ngx_cdecl
main(int argc, char *const *argv)
{
- ngx_int_t i;
+ ngx_buf_t *b;
ngx_log_t *log;
+ ngx_uint_t i;
ngx_cycle_t *cycle, init_cycle;
+ ngx_conf_dump_t *cd;
ngx_core_conf_t *ccf;
ngx_debug_init();
@@ -196,7 +198,7 @@ main(int argc, char *const *argv)
if (ngx_show_help) {
ngx_write_stderr(
- "Usage: nginx [-?hvVtq] [-s signal] [-c filename] "
+ "Usage: nginx [-?hvVtTq] [-s signal] [-c filename] "
"[-p prefix] [-g directives]" NGX_LINEFEED
NGX_LINEFEED
"Options:" NGX_LINEFEED
@@ -205,6 +207,8 @@ main(int argc, char *const *argv)
" -V : show version and configure options then exit"
NGX_LINEFEED
" -t : test configuration and exit" NGX_LINEFEED
+ " -T : test configuration, dump it and exit"
+ NGX_LINEFEED
" -q : suppress non-error messages "
"during configuration testing" NGX_LINEFEED
" -s signal : send signal to a master process: "
@@ -333,6 +337,23 @@ main(int argc, char *const *argv)
cycle->conf_file.data);
}
+ if (ngx_dump_config) {
+ cd = cycle->config_dump.elts;
+
+ for (i = 0; i < cycle->config_dump.nelts; i++) {
+
+ ngx_write_stdout("# configuration file ");
+ (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
+ cd[i].name.len);
+ ngx_write_stdout(":" NGX_LINEFEED);
+
+ b = cd[i].buffer;
+
+ (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
+ ngx_write_stdout(NGX_LINEFEED);
+ }
+ }
+
return 0;
}
@@ -689,6 +710,11 @@ ngx_get_options(int argc, char *const *argv)
ngx_test_config = 1;
break;
+ case 'T':
+ ngx_test_config = 1;
+ ngx_dump_config = 1;
+ break;
+
case 'q':
ngx_quiet_mode = 1;
break;
diff --git a/src/core/nginx.h b/src/core/nginx.h
index ec818e042..4c9cf35cb 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1009001
-#define NGINX_VERSION "1.9.1"
+#define nginx_version 1009002
+#define NGINX_VERSION "1.9.2"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index ec3c1fae1..1c3238cf3 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -101,10 +101,13 @@ char *
ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
{
char *rv;
+ u_char *p;
+ off_t size;
ngx_fd_t fd;
ngx_int_t rc;
- ngx_buf_t buf;
+ ngx_buf_t buf, *tbuf;
ngx_conf_file_t *prev, conf_file;
+ ngx_conf_dump_t *cd;
enum {
parse_file = 0,
parse_block,
@@ -158,6 +161,39 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
type = parse_file;
+ if (ngx_dump_config
+#if (NGX_DEBUG)
+ || 1
+#endif
+ )
+ {
+ p = ngx_pstrdup(cf->cycle->pool, filename);
+ if (p == NULL) {
+ goto failed;
+ }
+
+ size = ngx_file_size(&cf->conf_file->file.info);
+
+ tbuf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size);
+ if (tbuf == NULL) {
+ goto failed;
+ }
+
+ cd = ngx_array_push(&cf->cycle->config_dump);
+ if (cd == NULL) {
+ goto failed;
+ }
+
+ cd->name.len = filename->len;
+ cd->name.data = p;
+ cd->buffer = tbuf;
+
+ cf->conf_file->dump = tbuf;
+
+ } else {
+ cf->conf_file->dump = NULL;
+ }
+
} else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
type = parse_block;
@@ -437,7 +473,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
ngx_uint_t found, need_space, last_space, sharp_comment, variable;
ngx_uint_t quoted, s_quoted, d_quoted, start_line;
ngx_str_t *word;
- ngx_buf_t *b;
+ ngx_buf_t *b, *dump;
found = 0;
need_space = 0;
@@ -450,6 +486,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
cf->args->nelts = 0;
b = cf->conf_file->buffer;
+ dump = cf->conf_file->dump;
start = b->pos;
start_line = cf->conf_file->line;
@@ -531,6 +568,10 @@ ngx_conf_read_token(ngx_conf_t *cf)
b->pos = b->start + len;
b->last = b->pos + n;
start = b->start;
+
+ if (dump) {
+ dump->last = ngx_cpymem(dump->last, b->pos, size);
+ }
}
ch = *b->pos++;
@@ -680,7 +721,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
return NGX_ERROR;
}
- word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);
+ word->data = ngx_pnalloc(cf->pool, b->pos - 1 - start + 1);
if (word->data == NULL) {
return NGX_ERROR;
}
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index d73a6c8bf..ee4430674 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -146,10 +146,17 @@ typedef struct {
typedef struct {
ngx_file_t file;
ngx_buf_t *buffer;
+ ngx_buf_t *dump;
ngx_uint_t line;
} ngx_conf_file_t;
+typedef struct {
+ ngx_str_t name;
+ ngx_buf_t *buffer;
+} ngx_conf_dump_t;
+
+
typedef char *(*ngx_conf_handler_pt)(ngx_conf_t *cf,
ngx_command_t *dummy, void *conf);
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index a279c81d6..6b317056a 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -54,6 +54,7 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
#include <ngx_process.h>
#include <ngx_user.h>
#include <ngx_parse.h>
+#include <ngx_parse_time.h>
#include <ngx_log.h>
#include <ngx_alloc.h>
#include <ngx_palloc.h>
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index b358f3dbe..ad4bf9254 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -24,6 +24,7 @@ static ngx_pool_t *ngx_temp_pool;
static ngx_event_t ngx_cleaner_event;
ngx_uint_t ngx_test_config;
+ngx_uint_t ngx_dump_config;
ngx_uint_t ngx_quiet_mode;
@@ -124,6 +125,13 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
cycle->paths.pool = pool;
+ if (ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t))
+ != NGX_OK)
+ {
+ ngx_destroy_pool(pool);
+ return NULL;
+ }
+
if (old_cycle->open_files.part.nelts) {
n = old_cycle->open_files.part.nelts;
for (part = old_cycle->open_files.part.next; part; part = part->next) {
diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h
index c601ea133..b77c1093f 100644
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -52,6 +52,7 @@ struct ngx_cycle_s {
ngx_array_t listening;
ngx_array_t paths;
+ ngx_array_t config_dump;
ngx_list_t open_files;
ngx_list_t shared_memory;
@@ -124,6 +125,7 @@ extern volatile ngx_cycle_t *ngx_cycle;
extern ngx_array_t ngx_old_cycles;
extern ngx_module_t ngx_core_module;
extern ngx_uint_t ngx_test_config;
+extern ngx_uint_t ngx_dump_config;
extern ngx_uint_t ngx_quiet_mode;
diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h
index cb80b5f83..618d3ad62 100644
--- a/src/core/ngx_log.h
+++ b/src/core/ngx_log.h
@@ -111,7 +111,7 @@ void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
/*********************************/
-#else /* NO VARIADIC MACROS */
+#else /* no variadic macros */
#define NGX_HAVE_VARIADIC_MACROS 0
@@ -123,7 +123,7 @@ void ngx_cdecl ngx_log_debug_core(ngx_log_t *log, ngx_err_t err,
const char *fmt, ...);
-#endif /* VARIADIC MACROS */
+#endif /* variadic macros */
/*********************************/
@@ -166,7 +166,7 @@ void ngx_cdecl ngx_log_debug_core(ngx_log_t *log, ngx_err_t err,
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
-#else /* NO VARIADIC MACROS */
+#else /* no variadic macros */
#define ngx_log_debug0(level, log, err, fmt) \
if ((log)->log_level & level) \
@@ -211,7 +211,7 @@ void ngx_cdecl ngx_log_debug_core(ngx_log_t *log, ngx_err_t err,
#endif
-#else /* NO NGX_DEBUG */
+#else /* !NGX_DEBUG */
#define ngx_log_debug0(level, log, err, fmt)
#define ngx_log_debug1(level, log, err, fmt, arg1)
@@ -255,6 +255,13 @@ ngx_write_stderr(char *text)
}
+static ngx_inline void
+ngx_write_stdout(char *text)
+{
+ (void) ngx_write_fd(ngx_stdout, text, ngx_strlen(text));
+}
+
+
extern ngx_module_t ngx_errlog_module;
extern ngx_uint_t ngx_use_stderr;
diff --git a/src/http/ngx_http_parse_time.c b/src/core/ngx_parse_time.c
index 985af3172..831cc71bf 100644
--- a/src/http/ngx_http_parse_time.c
+++ b/src/core/ngx_parse_time.c
@@ -7,13 +7,12 @@
#include <ngx_config.h>
#include <ngx_core.h>
-#include <ngx_http.h>
static ngx_uint_t mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
time_t
-ngx_http_parse_time(u_char *value, size_t len)
+ngx_parse_http_time(u_char *value, size_t len)
{
u_char *p, *end;
ngx_int_t month;
diff --git a/src/core/ngx_parse_time.h b/src/core/ngx_parse_time.h
new file mode 100644
index 000000000..aa542ebf5
--- /dev/null
+++ b/src/core/ngx_parse_time.h
@@ -0,0 +1,22 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#ifndef _NGX_PARSE_TIME_H_INCLUDED_
+#define _NGX_PARSE_TIME_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+time_t ngx_parse_http_time(u_char *value, size_t len);
+
+/* compatibility */
+#define ngx_http_parse_time(value, len) ngx_parse_http_time(value, len)
+
+
+#endif /* _NGX_PARSE_TIME_H_INCLUDED_ */
diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c
index 59ef010fc..f347e7f43 100644
--- a/src/core/ngx_proxy_protocol.c
+++ b/src/core/ngx_proxy_protocol.c
@@ -10,7 +10,7 @@
u_char *
-ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last)
+ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
{
size_t len;
u_char ch, *p, *addr;
@@ -89,3 +89,52 @@ invalid:
return NULL;
}
+
+
+u_char *
+ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
+{
+ ngx_uint_t port, lport;
+
+ if (last - buf < NGX_PROXY_PROTOCOL_MAX_HEADER) {
+ return NULL;
+ }
+
+ if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
+ return NULL;
+ }
+
+ switch (c->sockaddr->sa_family) {
+
+ case AF_INET:
+ buf = ngx_cpymem(buf, "PROXY TCP4 ", sizeof("PROXY TCP4 ") - 1);
+
+ port = ntohs(((struct sockaddr_in *) c->sockaddr)->sin_port);
+ lport = ntohs(((struct sockaddr_in *) c->local_sockaddr)->sin_port);
+
+ break;
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ buf = ngx_cpymem(buf, "PROXY TCP6 ", sizeof("PROXY TCP6 ") - 1);
+
+ port = ntohs(((struct sockaddr_in6 *) c->sockaddr)->sin6_port);
+ lport = ntohs(((struct sockaddr_in6 *) c->local_sockaddr)->sin6_port);
+
+ break;
+#endif
+
+ default:
+ return ngx_cpymem(buf, "PROXY UNKNOWN" CRLF,
+ sizeof("PROXY UNKNOWN" CRLF) - 1);
+ }
+
+ buf += ngx_sock_ntop(c->sockaddr, c->socklen, buf, last - buf, 0);
+
+ *buf++ = ' ';
+
+ buf += ngx_sock_ntop(c->local_sockaddr, c->local_socklen, buf, last - buf,
+ 0);
+
+ return ngx_slprintf(buf, last, " %ui %ui" CRLF, port, lport);
+}
diff --git a/src/core/ngx_proxy_protocol.h b/src/core/ngx_proxy_protocol.h
index 4f3912512..fb848f683 100644
--- a/src/core/ngx_proxy_protocol.h
+++ b/src/core/ngx_proxy_protocol.h
@@ -16,7 +16,9 @@
#define NGX_PROXY_PROTOCOL_MAX_HEADER 107
-u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf,
+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,
u_char *last);
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index 34a07e4dc..b8e06077e 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -927,8 +927,9 @@ ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
*cf = pcf;
- if (rv != NGX_CONF_OK)
+ if (rv != NGX_CONF_OK) {
return rv;
+ }
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c
index c39598ff5..03ff54043 100644
--- a/src/event/ngx_event_openssl_stapling.c
+++ b/src/event/ngx_event_openssl_stapling.c
@@ -32,6 +32,7 @@ typedef struct {
X509 *issuer;
time_t valid;
+ time_t refresh;
unsigned verify:1;
unsigned loading:1;
@@ -93,6 +94,8 @@ static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
+static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
+
static void ngx_ssl_stapling_cleanup(void *data);
static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void);
@@ -462,7 +465,9 @@ ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
staple = data;
rc = SSL_TLSEXT_ERR_NOACK;
- if (staple->staple.len) {
+ if (staple->staple.len
+ && staple->valid >= ngx_time())
+ {
/* we have to copy ocsp response as OpenSSL will free it by itself */
p = OPENSSL_malloc(staple->staple.len);
@@ -490,7 +495,7 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
ngx_ssl_ocsp_ctx_t *ctx;
if (staple->host.len == 0
- || staple->loading || staple->valid >= ngx_time())
+ || staple->loading || staple->refresh >= ngx_time())
{
return;
}
@@ -532,6 +537,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
u_char *p;
int n;
size_t len;
+ time_t now, valid;
ngx_str_t response;
X509_STORE *store;
STACK_OF(X509) *chain;
@@ -542,6 +548,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
staple = ctx->data;
+ now = ngx_time();
ocsp = NULL;
basic = NULL;
id = NULL;
@@ -629,17 +636,28 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
goto error;
}
+ valid = ngx_ssl_stapling_time(nextupdate);
+ if (valid == (time_t) NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
+ "invalid nextUpdate time in certificate status");
+ goto error;
+ }
+
OCSP_CERTID_free(id);
OCSP_BASICRESP_free(basic);
OCSP_RESPONSE_free(ocsp);
+ id = NULL;
+ basic = NULL;
+ ocsp = NULL;
+
/* copy the response to memory not in ctx->pool */
response.len = len;
response.data = ngx_alloc(response.len, ctx->log);
if (response.data == NULL) {
- goto done;
+ goto error;
}
ngx_memcpy(response.data, ctx->response->pos, response.len);
@@ -653,11 +671,15 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
}
staple->staple = response;
+ staple->valid = valid;
-done:
+ /*
+ * refresh before the response expires,
+ * but not earlier than in 5 minutes, and at least in an hour
+ */
staple->loading = 0;
- staple->valid = ngx_time() + 3600; /* ssl_stapling_valid */
+ staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300);
ngx_ssl_ocsp_done(ctx);
return;
@@ -665,7 +687,7 @@ done:
error:
staple->loading = 0;
- staple->valid = ngx_time() + 300; /* ssl_stapling_err_valid */
+ staple->refresh = now + 300;
if (id) {
OCSP_CERTID_free(id);
@@ -683,6 +705,40 @@ error:
}
+static time_t
+ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
+{
+ u_char *value;
+ size_t len;
+ time_t time;
+ BIO *bio;
+
+ /*
+ * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME
+ * into time_t. To do this, we use ASN1_GENERALIZEDTIME_print(),
+ * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
+ * "Feb 3 00:55:52 2015 GMT"), and parse the result.
+ */
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL) {
+ return NGX_ERROR;
+ }
+
+ /* fake weekday prepended to match C asctime() format */
+
+ BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
+ ASN1_GENERALIZEDTIME_print(bio, asn1time);
+ len = BIO_get_mem_data(bio, &value);
+
+ time = ngx_parse_http_time(value, len);
+
+ BIO_free(bio);
+
+ return time;
+}
+
+
static void
ngx_ssl_stapling_cleanup(void *data)
{
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
index 8ba247f4a..2d0e7d35e 100644
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -22,8 +22,8 @@ static ngx_int_t ngx_event_pipe_drain_chains(ngx_event_pipe_t *p);
ngx_int_t
ngx_event_pipe(ngx_event_pipe_t *p, ngx_int_t do_write)
{
- u_int flags;
ngx_int_t rc;
+ ngx_uint_t flags;
ngx_event_t *rev, *wev;
for ( ;; ) {
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index 529aba533..b9fadd001 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -255,7 +255,7 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
ext.log = r->connection->log;
if (r->headers_in.date) {
- date = ngx_http_parse_time(r->headers_in.date->value.data,
+ date = ngx_parse_http_time(r->headers_in.date->value.data,
r->headers_in.date->value.len);
if (date != NGX_ERROR) {
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index a356814e4..985e5b335 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -498,7 +498,7 @@ ngx_http_set_last_modified(ngx_http_request_t *r, ngx_http_header_val_t *hv,
}
r->headers_out.last_modified_time =
- (value->len) ? ngx_http_parse_time(value->data, value->len) : -1;
+ (value->len) ? ngx_parse_http_time(value->data, value->len) : -1;
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_not_modified_filter_module.c b/src/http/modules/ngx_http_not_modified_filter_module.c
index acc94ded3..032ba96fd 100644
--- a/src/http/modules/ngx_http_not_modified_filter_module.c
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c
@@ -118,7 +118,7 @@ ngx_http_test_if_unmodified(ngx_http_request_t *r)
return 0;
}
- iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data,
+ iums = ngx_parse_http_time(r->headers_in.if_unmodified_since->value.data,
r->headers_in.if_unmodified_since->value.len);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -148,7 +148,7 @@ ngx_http_test_if_modified(ngx_http_request_t *r)
return 1;
}
- ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
+ ims = ngx_parse_http_time(r->headers_in.if_modified_since->value.data,
r->headers_in.if_modified_since->value.len);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index bb9a42c54..952da7553 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -204,7 +204,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
goto next_filter;
}
- if_range_time = ngx_http_parse_time(if_range->data, if_range->len);
+ if_range_time = ngx_parse_http_time(if_range->data, if_range->len);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http ir:%d lm:%d",
diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c
index 4e005fc0e..768881ee4 100644
--- a/src/http/modules/ngx_http_upstream_keepalive_module.c
+++ b/src/http/modules/ngx_http_upstream_keepalive_module.c
@@ -25,6 +25,18 @@ typedef struct {
typedef struct {
ngx_http_upstream_keepalive_srv_conf_t *conf;
+ ngx_queue_t queue;
+ ngx_connection_t *connection;
+
+ socklen_t socklen;
+ u_char sockaddr[NGX_SOCKADDRLEN];
+
+} ngx_http_upstream_keepalive_cache_t;
+
+
+typedef struct {
+ ngx_http_upstream_keepalive_srv_conf_t *conf;
+
ngx_http_upstream_t *upstream;
void *data;
@@ -40,18 +52,6 @@ typedef struct {
} ngx_http_upstream_keepalive_peer_data_t;
-typedef struct {
- ngx_http_upstream_keepalive_srv_conf_t *conf;
-
- ngx_queue_t queue;
- ngx_connection_t *connection;
-
- socklen_t socklen;
- u_char sockaddr[NGX_SOCKADDRLEN];
-
-} ngx_http_upstream_keepalive_cache_t;
-
-
static ngx_int_t ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
ngx_http_upstream_srv_conf_t *us);
static ngx_int_t ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc,
@@ -63,7 +63,6 @@ static void ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev);
static void ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev);
static void ngx_http_upstream_keepalive_close(ngx_connection_t *c);
-
#if (NGX_HTTP_SSL)
static ngx_int_t ngx_http_upstream_keepalive_set_session(
ngx_peer_connection_t *pc, void *data);
@@ -244,24 +243,28 @@ ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
ngx_queue_remove(q);
ngx_queue_insert_head(&kp->conf->free, q);
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get keepalive peer: using connection %p", c);
-
- c->idle = 0;
- c->sent = 0;
- c->log = pc->log;
- c->read->log = pc->log;
- c->write->log = pc->log;
- c->pool->log = pc->log;
-
- pc->connection = c;
- pc->cached = 1;
-
- return NGX_DONE;
+ goto found;
}
}
return NGX_OK;
+
+found:
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
+ "get keepalive peer: using connection %p", c);
+
+ c->idle = 0;
+ c->sent = 0;
+ c->log = pc->log;
+ c->read->log = pc->log;
+ c->write->log = pc->log;
+ c->pool->log = pc->log;
+
+ pc->connection = c;
+ pc->cached = 1;
+
+ return NGX_DONE;
}
@@ -322,9 +325,10 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
}
- item->connection = c;
ngx_queue_insert_head(&kp->conf->cache, q);
+ item->connection = c;
+
pc->connection = NULL;
if (c->read->timer_set) {
@@ -470,10 +474,9 @@ ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf)
*
* conf->original_init_upstream = NULL;
* conf->original_init_peer = NULL;
+ * conf->max_cached = 0;
*/
- conf->max_cached = 1;
-
return conf;
}
@@ -487,18 +490,10 @@ ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_int_t n;
ngx_str_t *value;
- uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
-
- if (kcf->original_init_upstream) {
+ if (kcf->max_cached) {
return "is duplicate";
}
- kcf->original_init_upstream = uscf->peer.init_upstream
- ? uscf->peer.init_upstream
- : ngx_http_upstream_init_round_robin;
-
- uscf->peer.init_upstream = ngx_http_upstream_init_keepalive;
-
/* read options */
value = cf->args->elts;
@@ -514,5 +509,13 @@ ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
kcf->max_cached = n;
+ uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
+
+ kcf->original_init_upstream = uscf->peer.init_upstream
+ ? uscf->peer.init_upstream
+ : ngx_http_upstream_init_round_robin;
+
+ uscf->peer.init_upstream = ngx_http_upstream_init_keepalive;
+
return NGX_CONF_OK;
}
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index b1e5fae6a..844f50249 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -148,11 +148,6 @@ ngx_int_t ngx_http_filter_finalize_request(ngx_http_request_t *r,
void ngx_http_clean_header(ngx_http_request_t *r);
-time_t ngx_http_parse_time(u_char *value, size_t len);
-size_t ngx_http_get_time(char *buf, time_t t);
-
-
-
ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r);
void ngx_http_discarded_request_body_handler(ngx_http_request_t *r);
void ngx_http_block_reading(ngx_http_request_t *r);
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index f5255265e..d423d8b80 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -2195,7 +2195,7 @@ ngx_http_gzip_ok(ngx_http_request_t *r)
return NGX_DECLINED;
}
- expires = ngx_http_parse_time(e->value.data, e->value.len);
+ expires = ngx_parse_http_time(e->value.data, e->value.len);
if (expires == NGX_ERROR) {
return NGX_DECLINED;
}
@@ -2203,7 +2203,7 @@ ngx_http_gzip_ok(ngx_http_request_t *r)
d = r->headers_out.date;
if (d) {
- date = ngx_http_parse_time(d->value.data, d->value.len);
+ date = ngx_parse_http_time(d->value.data, d->value.len);
if (date == NGX_ERROR) {
return NGX_DECLINED;
}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 2669b522c..cd5f30230 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -467,7 +467,7 @@ ngx_http_wait_request_handler(ngx_event_t *rev)
if (hc->proxy_protocol) {
hc->proxy_protocol = 0;
- p = ngx_proxy_protocol_parse(c, b->pos, b->last);
+ p = ngx_proxy_protocol_read(c, b->pos, b->last);
if (p == NULL) {
ngx_http_close_connection(c);
@@ -675,7 +675,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
if (hc->proxy_protocol) {
hc->proxy_protocol = 0;
- p = ngx_proxy_protocol_parse(c, buf, buf + n);
+ p = ngx_proxy_protocol_read(c, buf, buf + n);
if (p == NULL) {
ngx_http_close_connection(c);
diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c
index 6bb79b88b..21c5217ca 100644
--- a/src/http/ngx_http_spdy.c
+++ b/src/http/ngx_http_spdy.c
@@ -866,7 +866,7 @@ ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc, u_char *pos,
log = sc->connection->log;
log->action = "reading PROXY protocol";
- pos = ngx_proxy_protocol_parse(sc->connection, pos, end);
+ pos = ngx_proxy_protocol_read(sc->connection, pos, end);
log->action = "processing SPDY";
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 47b574e84..4b0332a42 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -3731,7 +3731,7 @@ ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (u->headers_in.last_modified) {
- lm = ngx_http_parse_time(u->headers_in.last_modified->value.data,
+ lm = ngx_parse_http_time(u->headers_in.last_modified->value.data,
u->headers_in.last_modified->value.len);
if (lm != NGX_ERROR) {
@@ -4128,7 +4128,7 @@ ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
#if (NGX_HTTP_CACHE)
if (u->cacheable) {
- u->headers_in.last_modified_time = ngx_http_parse_time(h->value.data,
+ u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data,
h->value.len);
}
@@ -4292,7 +4292,7 @@ ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
return NGX_OK;
}
- expires = ngx_http_parse_time(h->value.data, h->value.len);
+ expires = ngx_parse_http_time(h->value.data, h->value.len);
if (expires == NGX_ERROR || expires < ngx_time()) {
u->cacheable = 0;
diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c
index f10f08c5f..38664bc87 100644
--- a/src/mail/ngx_mail.c
+++ b/src/mail/ngx_mail.c
@@ -238,13 +238,13 @@ ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
struct sockaddr_in6 *sin6;
#endif
- sa = (struct sockaddr *) &listen->sockaddr;
+ sa = &listen->u.sockaddr;
switch (sa->sa_family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
- sin6 = (struct sockaddr_in6 *) sa;
+ sin6 = &listen->u.sockaddr_in6;
p = sin6->sin6_port;
break;
#endif
@@ -256,7 +256,7 @@ ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
#endif
default: /* AF_INET */
- sin = (struct sockaddr_in *) sa;
+ sin = &listen->u.sockaddr_in;
p = sin->sin_port;
break;
}
@@ -296,23 +296,7 @@ found:
return NGX_ERROR;
}
- addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
- addr->socklen = listen->socklen;
- addr->ctx = listen->ctx;
- addr->bind = listen->bind;
- addr->wildcard = listen->wildcard;
- addr->so_keepalive = listen->so_keepalive;
-#if (NGX_HAVE_KEEPALIVE_TUNABLE)
- addr->tcp_keepidle = listen->tcp_keepidle;
- addr->tcp_keepintvl = listen->tcp_keepintvl;
- addr->tcp_keepcnt = listen->tcp_keepcnt;
-#endif
-#if (NGX_MAIL_SSL)
- addr->ssl = listen->ssl;
-#endif
-#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
- addr->ipv6only = listen->ipv6only;
-#endif
+ addr->opt = *listen;
return NGX_OK;
}
@@ -342,8 +326,8 @@ ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
* to the "*:port" only and ignore the other bindings
*/
- if (addr[last - 1].wildcard) {
- addr[last - 1].bind = 1;
+ if (addr[last - 1].opt.wildcard) {
+ addr[last - 1].opt.bind = 1;
bind_wildcard = 1;
} else {
@@ -354,12 +338,13 @@ ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
while (i < last) {
- if (bind_wildcard && !addr[i].bind) {
+ if (bind_wildcard && !addr[i].opt.bind) {
i++;
continue;
}
- ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen);
+ ls = ngx_create_listening(cf, &addr[i].opt.u.sockaddr,
+ addr[i].opt.socklen);
if (ls == NULL) {
return NGX_CONF_ERROR;
}
@@ -368,21 +353,23 @@ ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
ls->handler = ngx_mail_init_connection;
ls->pool_size = 256;
- cscf = addr->ctx->srv_conf[ngx_mail_core_module.ctx_index];
+ cscf = addr->opt.ctx->srv_conf[ngx_mail_core_module.ctx_index];
ls->logp = cscf->error_log;
ls->log.data = &ls->addr_text;
ls->log.handler = ngx_accept_log_error;
- ls->keepalive = addr[i].so_keepalive;
+ ls->backlog = addr[i].opt.backlog;
+
+ ls->keepalive = addr[i].opt.so_keepalive;
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
- ls->keepidle = addr[i].tcp_keepidle;
- ls->keepintvl = addr[i].tcp_keepintvl;
- ls->keepcnt = addr[i].tcp_keepcnt;
+ ls->keepidle = addr[i].opt.tcp_keepidle;
+ ls->keepintvl = addr[i].opt.tcp_keepintvl;
+ ls->keepcnt = addr[i].opt.tcp_keepcnt;
#endif
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
- ls->ipv6only = addr[i].ipv6only;
+ ls->ipv6only = addr[i].opt.ipv6only;
#endif
mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t));
@@ -439,15 +426,15 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
for (i = 0; i < mport->naddrs; i++) {
- sin = (struct sockaddr_in *) addr[i].sockaddr;
+ sin = &addr[i].opt.u.sockaddr_in;
addrs[i].addr = sin->sin_addr.s_addr;
- addrs[i].conf.ctx = addr[i].ctx;
+ addrs[i].conf.ctx = addr[i].opt.ctx;
#if (NGX_MAIL_SSL)
- addrs[i].conf.ssl = addr[i].ssl;
+ addrs[i].conf.ssl = addr[i].opt.ssl;
#endif
- len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf,
+ len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf,
NGX_SOCKADDR_STRLEN, 1);
p = ngx_pnalloc(cf->pool, len);
@@ -488,15 +475,15 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
for (i = 0; i < mport->naddrs; i++) {
- sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
+ sin6 = &addr[i].opt.u.sockaddr_in6;
addrs6[i].addr6 = sin6->sin6_addr;
- addrs6[i].conf.ctx = addr[i].ctx;
+ addrs6[i].conf.ctx = addr[i].opt.ctx;
#if (NGX_MAIL_SSL)
- addrs6[i].conf.ssl = addr[i].ssl;
+ addrs6[i].conf.ssl = addr[i].opt.ssl;
#endif
- len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf,
+ len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf,
NGX_SOCKADDR_STRLEN, 1);
p = ngx_pnalloc(cf->pool, len);
@@ -524,22 +511,22 @@ ngx_mail_cmp_conf_addrs(const void *one, const void *two)
first = (ngx_mail_conf_addr_t *) one;
second = (ngx_mail_conf_addr_t *) two;
- if (first->wildcard) {
+ if (first->opt.wildcard) {
/* a wildcard must be the last resort, shift it to the end */
return 1;
}
- if (second->wildcard) {
+ if (second->opt.wildcard) {
/* a wildcard must be the last resort, shift it to the end */
return -1;
}
- if (first->bind && !second->bind) {
+ if (first->opt.bind && !second->opt.bind) {
/* shift explicit bind()ed addresses to the start */
return -1;
}
- if (!first->bind && second->bind) {
+ if (!first->opt.bind && second->opt.bind) {
/* shift explicit bind()ed addresses to the start */
return 1;
}
diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h
index dd8a23abb..07d0cb60c 100644
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -27,7 +27,18 @@ typedef struct {
typedef struct {
- u_char sockaddr[NGX_SOCKADDRLEN];
+ union {
+ struct sockaddr sockaddr;
+ struct sockaddr_in sockaddr_in;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 sockaddr_in6;
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ struct sockaddr_un sockaddr_un;
+#endif
+ u_char sockaddr_data[NGX_SOCKADDRLEN];
+ } u;
+
socklen_t socklen;
/* server ctx */
@@ -47,6 +58,7 @@ typedef struct {
int tcp_keepintvl;
int tcp_keepcnt;
#endif
+ int backlog;
} ngx_mail_listen_t;
@@ -89,25 +101,7 @@ typedef struct {
typedef struct {
- struct sockaddr *sockaddr;
- socklen_t socklen;
-
- ngx_mail_conf_ctx_t *ctx;
-
- unsigned bind:1;
- unsigned wildcard:1;
-#if (NGX_MAIL_SSL)
- unsigned ssl:1;
-#endif
-#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
- unsigned ipv6only:1;
-#endif
- unsigned so_keepalive:2;
-#if (NGX_HAVE_KEEPALIVE_TUNABLE)
- int tcp_keepidle;
- int tcp_keepintvl;
- int tcp_keepcnt;
-#endif
+ ngx_mail_listen_t opt;
} ngx_mail_conf_addr_t;
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
index ab455b8d9..271afc473 100644
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -325,7 +325,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
for (i = 0; i < cmcf->listen.nelts; i++) {
- sa = (struct sockaddr *) ls[i].sockaddr;
+ sa = &ls[i].u.sockaddr;
if (sa->sa_family != u.family) {
continue;
@@ -337,7 +337,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
case AF_INET6:
off = offsetof(struct sockaddr_in6, sin6_addr);
len = 16;
- sin6 = (struct sockaddr_in6 *) sa;
+ sin6 = &ls[i].u.sockaddr_in6;
port = ntohs(sin6->sin6_port);
break;
#endif
@@ -353,12 +353,14 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
default: /* AF_INET */
off = offsetof(struct sockaddr_in, sin_addr);
len = 4;
- sin = (struct sockaddr_in *) sa;
+ sin = &ls[i].u.sockaddr_in;
port = ntohs(sin->sin_port);
break;
}
- if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) {
+ if (ngx_memcmp(ls[i].u.sockaddr_data + off, u.sockaddr + off, len)
+ != 0)
+ {
continue;
}
@@ -378,9 +380,10 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_memzero(ls, sizeof(ngx_mail_listen_t));
- ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
+ ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen);
ls->socklen = u.socklen;
+ ls->backlog = NGX_LISTEN_BACKLOG;
ls->wildcard = u.wildcard;
ls->ctx = cf->ctx;
@@ -416,12 +419,25 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue;
}
+ if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
+ ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
+ ls->bind = 1;
+
+ if (ls->backlog == NGX_ERROR || ls->backlog == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid backlog \"%V\"", &value[i]);
+ return NGX_CONF_ERROR;
+ }
+
+ continue;
+ }
+
if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
struct sockaddr *sa;
u_char buf[NGX_SOCKADDR_STRLEN];
- sa = (struct sockaddr *) ls->sockaddr;
+ sa = &ls->u.sockaddr;
if (sa->sa_family == AF_INET6) {
diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h
index b6990bc6e..6081b003f 100644
--- a/src/os/unix/ngx_files.h
+++ b/src/os/unix/ngx_files.h
@@ -368,6 +368,7 @@ size_t ngx_fs_bsize(u_char *name);
#endif
+#define ngx_stdout STDOUT_FILENO
#define ngx_stderr STDERR_FILENO
#define ngx_set_stderr(fd) dup2(fd, STDERR_FILENO)
#define ngx_set_stderr_n "dup2(STDERR_FILENO)"
diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c
index 1c5e7a87c..3dce35ab7 100644
--- a/src/stream/ngx_stream.c
+++ b/src/stream/ngx_stream.c
@@ -204,6 +204,20 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
+ for (m = 0; ngx_modules[m]; m++) {
+ if (ngx_modules[m]->type != NGX_STREAM_MODULE) {
+ continue;
+ }
+
+ module = ngx_modules[m]->ctx;
+
+ if (module->postconfiguration) {
+ if (module->postconfiguration(cf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+ }
+
*cf = pcf;
@@ -239,13 +253,13 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
struct sockaddr_in6 *sin6;
#endif
- sa = (struct sockaddr *) &listen->sockaddr;
+ sa = &listen->u.sockaddr;
switch (sa->sa_family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
- sin6 = (struct sockaddr_in6 *) sa;
+ sin6 = &listen->u.sockaddr_in6;
p = sin6->sin6_port;
break;
#endif
@@ -257,7 +271,7 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
#endif
default: /* AF_INET */
- sin = (struct sockaddr_in *) sa;
+ sin = &listen->u.sockaddr_in;
p = sin->sin_port;
break;
}
@@ -297,23 +311,7 @@ found:
return NGX_ERROR;
}
- addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
- addr->socklen = listen->socklen;
- addr->ctx = listen->ctx;
- addr->bind = listen->bind;
- addr->wildcard = listen->wildcard;
- addr->so_keepalive = listen->so_keepalive;
-#if (NGX_HAVE_KEEPALIVE_TUNABLE)
- addr->tcp_keepidle = listen->tcp_keepidle;
- addr->tcp_keepintvl = listen->tcp_keepintvl;
- addr->tcp_keepcnt = listen->tcp_keepcnt;
-#endif
-#if (NGX_STREAM_SSL)
- addr->ssl = listen->ssl;
-#endif
-#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
- addr->ipv6only = listen->ipv6only;
-#endif
+ addr->opt = *listen;
return NGX_OK;
}
@@ -343,8 +341,8 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
* to the "*:port" only and ignore the other bindings
*/
- if (addr[last - 1].wildcard) {
- addr[last - 1].bind = 1;
+ if (addr[last - 1].opt.wildcard) {
+ addr[last - 1].opt.bind = 1;
bind_wildcard = 1;
} else {
@@ -355,12 +353,13 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
while (i < last) {
- if (bind_wildcard && !addr[i].bind) {
+ if (bind_wildcard && !addr[i].opt.bind) {
i++;
continue;
}
- ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen);
+ ls = ngx_create_listening(cf, &addr[i].opt.u.sockaddr,
+ addr[i].opt.socklen);
if (ls == NULL) {
return NGX_CONF_ERROR;
}
@@ -369,21 +368,27 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
ls->handler = ngx_stream_init_connection;
ls->pool_size = 256;
- cscf = addr->ctx->srv_conf[ngx_stream_core_module.ctx_index];
+ cscf = addr->opt.ctx->srv_conf[ngx_stream_core_module.ctx_index];
ls->logp = cscf->error_log;
ls->log.data = &ls->addr_text;
ls->log.handler = ngx_accept_log_error;
- ls->keepalive = addr[i].so_keepalive;
+ ls->backlog = addr[i].opt.backlog;
+
+ ls->keepalive = addr[i].opt.so_keepalive;
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
- ls->keepidle = addr[i].tcp_keepidle;
- ls->keepintvl = addr[i].tcp_keepintvl;
- ls->keepcnt = addr[i].tcp_keepcnt;
+ ls->keepidle = addr[i].opt.tcp_keepidle;
+ ls->keepintvl = addr[i].opt.tcp_keepintvl;
+ ls->keepcnt = addr[i].opt.tcp_keepcnt;
#endif
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
- ls->ipv6only = addr[i].ipv6only;
+ ls->ipv6only = addr[i].opt.ipv6only;
+#endif
+
+#if (NGX_HAVE_REUSEPORT)
+ ls->reuseport = addr[i].opt.reuseport;
#endif
stport = ngx_palloc(cf->pool, sizeof(ngx_stream_port_t));
@@ -444,15 +449,15 @@ ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport,
for (i = 0; i < stport->naddrs; i++) {
- sin = (struct sockaddr_in *) addr[i].sockaddr;
+ sin = &addr[i].opt.u.sockaddr_in;
addrs[i].addr = sin->sin_addr.s_addr;
- addrs[i].conf.ctx = addr[i].ctx;
+ addrs[i].conf.ctx = addr[i].opt.ctx;
#if (NGX_STREAM_SSL)
- addrs[i].conf.ssl = addr[i].ssl;
+ addrs[i].conf.ssl = addr[i].opt.ssl;
#endif
- len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf,
+ len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf,
NGX_SOCKADDR_STRLEN, 1);
p = ngx_pnalloc(cf->pool, len);
@@ -493,15 +498,15 @@ ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport,
for (i = 0; i < stport->naddrs; i++) {
- sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
+ sin6 = &addr[i].opt.u.sockaddr_in6;
addrs6[i].addr6 = sin6->sin6_addr;
- addrs6[i].conf.ctx = addr[i].ctx;
+ addrs6[i].conf.ctx = addr[i].opt.ctx;
#if (NGX_STREAM_SSL)
- addrs6[i].conf.ssl = addr[i].ssl;
+ addrs6[i].conf.ssl = addr[i].opt.ssl;
#endif
- len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf,
+ len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf,
NGX_SOCKADDR_STRLEN, 1);
p = ngx_pnalloc(cf->pool, len);
@@ -529,22 +534,22 @@ ngx_stream_cmp_conf_addrs(const void *one, const void *two)
first = (ngx_stream_conf_addr_t *) one;
second = (ngx_stream_conf_addr_t *) two;
- if (first->wildcard) {
+ if (first->opt.wildcard) {
/* a wildcard must be the last resort, shift it to the end */
return 1;
}
- if (second->wildcard) {
+ if (second->opt.wildcard) {
/* a wildcard must be the last resort, shift it to the end */
return -1;
}
- if (first->bind && !second->bind) {
+ if (first->opt.bind && !second->opt.bind) {
/* shift explicit bind()ed addresses to the start */
return -1;
}
- if (!first->bind && second->bind) {
+ if (!first->opt.bind && second->opt.bind) {
/* shift explicit bind()ed addresses to the start */
return 1;
}
diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h
index a10f68fff..b0eb7d4e5 100644
--- a/src/stream/ngx_stream.h
+++ b/src/stream/ngx_stream.h
@@ -31,7 +31,18 @@ typedef struct {
typedef struct {
- u_char sockaddr[NGX_SOCKADDRLEN];
+ union {
+ struct sockaddr sockaddr;
+ struct sockaddr_in sockaddr_in;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 sockaddr_in6;
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ struct sockaddr_un sockaddr_un;
+#endif
+ u_char sockaddr_data[NGX_SOCKADDRLEN];
+ } u;
+
socklen_t socklen;
/* server ctx */
@@ -54,6 +65,7 @@ typedef struct {
int tcp_keepintvl;
int tcp_keepcnt;
#endif
+ int backlog;
} ngx_stream_listen_t;
@@ -96,31 +108,17 @@ typedef struct {
typedef struct {
- struct sockaddr *sockaddr;
- socklen_t socklen;
+ ngx_stream_listen_t opt;
+} ngx_stream_conf_addr_t;
- ngx_stream_conf_ctx_t *ctx;
- unsigned bind:1;
- unsigned wildcard:1;
-#if (NGX_STREAM_SSL)
- unsigned ssl:1;
-#endif
-#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
- unsigned ipv6only:1;
-#endif
- unsigned so_keepalive:2;
-#if (NGX_HAVE_KEEPALIVE_TUNABLE)
- int tcp_keepidle;
- int tcp_keepintvl;
- int tcp_keepcnt;
-#endif
-} ngx_stream_conf_addr_t;
+typedef ngx_int_t (*ngx_stream_access_pt)(ngx_stream_session_t *s);
typedef struct {
ngx_array_t servers; /* ngx_stream_core_srv_conf_t */
ngx_array_t listen; /* ngx_stream_listen_t */
+ ngx_stream_access_pt access_handler;
} ngx_stream_core_main_conf_t;
@@ -154,6 +152,8 @@ struct ngx_stream_session_s {
typedef struct {
+ ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
+
void *(*create_main_conf)(ngx_conf_t *cf);
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
diff --git a/src/stream/ngx_stream_access_module.c b/src/stream/ngx_stream_access_module.c
new file mode 100644
index 000000000..64869d230
--- /dev/null
+++ b/src/stream/ngx_stream_access_module.c
@@ -0,0 +1,451 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_stream.h>
+
+
+typedef struct {
+ in_addr_t mask;
+ in_addr_t addr;
+ ngx_uint_t deny; /* unsigned deny:1; */
+} ngx_stream_access_rule_t;
+
+#if (NGX_HAVE_INET6)
+
+typedef struct {
+ struct in6_addr addr;
+ struct in6_addr mask;
+ ngx_uint_t deny; /* unsigned deny:1; */
+} ngx_stream_access_rule6_t;
+
+#endif
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+typedef struct {
+ ngx_uint_t deny; /* unsigned deny:1; */
+} ngx_stream_access_rule_un_t;
+
+#endif
+
+typedef struct {
+ ngx_array_t *rules; /* array of ngx_stream_access_rule_t */
+#if (NGX_HAVE_INET6)
+ ngx_array_t *rules6; /* array of ngx_stream_access_rule6_t */
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ ngx_array_t *rules_un; /* array of ngx_stream_access_rule_un_t */
+#endif
+} ngx_stream_access_srv_conf_t;
+
+
+static ngx_int_t ngx_stream_access_handler(ngx_stream_session_t *s);
+static ngx_int_t ngx_stream_access_inet(ngx_stream_session_t *s,
+ ngx_stream_access_srv_conf_t *ascf, in_addr_t addr);
+#if (NGX_HAVE_INET6)
+static ngx_int_t ngx_stream_access_inet6(ngx_stream_session_t *s,
+ ngx_stream_access_srv_conf_t *ascf, u_char *p);
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+static ngx_int_t ngx_stream_access_unix(ngx_stream_session_t *s,
+ ngx_stream_access_srv_conf_t *ascf);
+#endif
+static ngx_int_t ngx_stream_access_found(ngx_stream_session_t *s,
+ ngx_uint_t deny);
+static char *ngx_stream_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+static void *ngx_stream_access_create_srv_conf(ngx_conf_t *cf);
+static char *ngx_stream_access_merge_srv_conf(ngx_conf_t *cf,
+ void *parent, void *child);
+static ngx_int_t ngx_stream_access_init(ngx_conf_t *cf);
+
+
+static ngx_command_t ngx_stream_access_commands[] = {
+
+ { ngx_string("allow"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_stream_access_rule,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("deny"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_stream_access_rule,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ 0,
+ NULL },
+
+ ngx_null_command
+};
+
+
+
+static ngx_stream_module_t ngx_stream_access_module_ctx = {
+ ngx_stream_access_init, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ ngx_stream_access_create_srv_conf, /* create server configuration */
+ ngx_stream_access_merge_srv_conf /* merge server configuration */
+};
+
+
+ngx_module_t ngx_stream_access_module = {
+ NGX_MODULE_V1,
+ &ngx_stream_access_module_ctx, /* module context */
+ ngx_stream_access_commands, /* module directives */
+ NGX_STREAM_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+
+
+static ngx_int_t
+ngx_stream_access_handler(ngx_stream_session_t *s)
+{
+ struct sockaddr_in *sin;
+ ngx_stream_access_srv_conf_t *ascf;
+#if (NGX_HAVE_INET6)
+ u_char *p;
+ in_addr_t addr;
+ struct sockaddr_in6 *sin6;
+#endif
+
+ ascf = ngx_stream_get_module_srv_conf(s, ngx_stream_access_module);
+
+ switch (s->connection->sockaddr->sa_family) {
+
+ case AF_INET:
+ if (ascf->rules) {
+ sin = (struct sockaddr_in *) s->connection->sockaddr;
+ return ngx_stream_access_inet(s, ascf, sin->sin_addr.s_addr);
+ }
+ break;
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) s->connection->sockaddr;
+ p = sin6->sin6_addr.s6_addr;
+
+ if (ascf->rules && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ addr = p[12] << 24;
+ addr += p[13] << 16;
+ addr += p[14] << 8;
+ addr += p[15];
+ return ngx_stream_access_inet(s, ascf, htonl(addr));
+ }
+
+ if (ascf->rules6) {
+ return ngx_stream_access_inet6(s, ascf, p);
+ }
+
+ break;
+
+#endif
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ case AF_UNIX:
+ if (ascf->rules_un) {
+ return ngx_stream_access_unix(s, ascf);
+ }
+
+ break;
+
+#endif
+ }
+
+ return NGX_DECLINED;
+}
+
+
+static ngx_int_t
+ngx_stream_access_inet(ngx_stream_session_t *s,
+ ngx_stream_access_srv_conf_t *ascf, in_addr_t addr)
+{
+ ngx_uint_t i;
+ ngx_stream_access_rule_t *rule;
+
+ rule = ascf->rules->elts;
+ for (i = 0; i < ascf->rules->nelts; i++) {
+
+ ngx_log_debug3(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
+ "access: %08XD %08XD %08XD",
+ addr, rule[i].mask, rule[i].addr);
+
+ if ((addr & rule[i].mask) == rule[i].addr) {
+ return ngx_stream_access_found(s, rule[i].deny);
+ }
+ }
+
+ return NGX_DECLINED;
+}
+
+
+#if (NGX_HAVE_INET6)
+
+static ngx_int_t
+ngx_stream_access_inet6(ngx_stream_session_t *s,
+ ngx_stream_access_srv_conf_t *ascf, u_char *p)
+{
+ ngx_uint_t n;
+ ngx_uint_t i;
+ ngx_stream_access_rule6_t *rule6;
+
+ rule6 = ascf->rules6->elts;
+ for (i = 0; i < ascf->rules6->nelts; i++) {
+
+#if (NGX_DEBUG)
+ {
+ size_t cl, ml, al;
+ u_char ct[NGX_INET6_ADDRSTRLEN];
+ u_char mt[NGX_INET6_ADDRSTRLEN];
+ u_char at[NGX_INET6_ADDRSTRLEN];
+
+ cl = ngx_inet6_ntop(p, ct, NGX_INET6_ADDRSTRLEN);
+ ml = ngx_inet6_ntop(rule6[i].mask.s6_addr, mt, NGX_INET6_ADDRSTRLEN);
+ al = ngx_inet6_ntop(rule6[i].addr.s6_addr, at, NGX_INET6_ADDRSTRLEN);
+
+ ngx_log_debug6(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
+ "access: %*s %*s %*s", cl, ct, ml, mt, al, at);
+ }
+#endif
+
+ for (n = 0; n < 16; n++) {
+ if ((p[n] & rule6[i].mask.s6_addr[n]) != rule6[i].addr.s6_addr[n]) {
+ goto next;
+ }
+ }
+
+ return ngx_stream_access_found(s, rule6[i].deny);
+
+ next:
+ continue;
+ }
+
+ return NGX_DECLINED;
+}
+
+#endif
+
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+static ngx_int_t
+ngx_stream_access_unix(ngx_stream_session_t *s,
+ ngx_stream_access_srv_conf_t *ascf)
+{
+ ngx_uint_t i;
+ ngx_stream_access_rule_un_t *rule_un;
+
+ rule_un = ascf->rules_un->elts;
+ for (i = 0; i < ascf->rules_un->nelts; i++) {
+
+ /* TODO: check path */
+ if (1) {
+ return ngx_stream_access_found(s, rule_un[i].deny);
+ }
+ }
+
+ return NGX_DECLINED;
+}
+
+#endif
+
+
+static ngx_int_t
+ngx_stream_access_found(ngx_stream_session_t *s, ngx_uint_t deny)
+{
+ if (deny) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "access forbidden by rule");
+ return NGX_ABORT;
+ }
+
+ return NGX_OK;
+}
+
+
+static char *
+ngx_stream_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_stream_access_srv_conf_t *ascf = conf;
+
+ ngx_int_t rc;
+ ngx_uint_t all;
+ ngx_str_t *value;
+ ngx_cidr_t cidr;
+ ngx_stream_access_rule_t *rule;
+#if (NGX_HAVE_INET6)
+ ngx_stream_access_rule6_t *rule6;
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ ngx_stream_access_rule_un_t *rule_un;
+#endif
+
+ ngx_memzero(&cidr, sizeof(ngx_cidr_t));
+
+ value = cf->args->elts;
+
+ all = (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0);
+
+ if (!all) {
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ if (value[1].len == 5 && ngx_strcmp(value[1].data, "unix:") == 0) {
+ cidr.family = AF_UNIX;
+ rc = NGX_OK;
+
+ } else {
+ rc = ngx_ptocidr(&value[1], &cidr);
+ }
+
+#else
+ rc = ngx_ptocidr(&value[1], &cidr);
+#endif
+
+ if (rc == NGX_ERROR) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid parameter \"%V\"", &value[1]);
+ return NGX_CONF_ERROR;
+ }
+
+ if (rc == NGX_DONE) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "low address bits of %V are meaningless", &value[1]);
+ }
+ }
+
+ if (cidr.family == AF_INET || all) {
+
+ if (ascf->rules == NULL) {
+ ascf->rules = ngx_array_create(cf->pool, 4,
+ sizeof(ngx_stream_access_rule_t));
+ if (ascf->rules == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ rule = ngx_array_push(ascf->rules);
+ if (rule == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ rule->mask = cidr.u.in.mask;
+ rule->addr = cidr.u.in.addr;
+ rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
+ }
+
+#if (NGX_HAVE_INET6)
+ if (cidr.family == AF_INET6 || all) {
+
+ if (ascf->rules6 == NULL) {
+ ascf->rules6 = ngx_array_create(cf->pool, 4,
+ sizeof(ngx_stream_access_rule6_t));
+ if (ascf->rules6 == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ rule6 = ngx_array_push(ascf->rules6);
+ if (rule6 == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ rule6->mask = cidr.u.in6.mask;
+ rule6->addr = cidr.u.in6.addr;
+ rule6->deny = (value[0].data[0] == 'd') ? 1 : 0;
+ }
+#endif
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+ if (cidr.family == AF_UNIX || all) {
+
+ if (ascf->rules_un == NULL) {
+ ascf->rules_un = ngx_array_create(cf->pool, 1,
+ sizeof(ngx_stream_access_rule_un_t));
+ if (ascf->rules_un == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ rule_un = ngx_array_push(ascf->rules_un);
+ if (rule_un == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ rule_un->deny = (value[0].data[0] == 'd') ? 1 : 0;
+ }
+#endif
+
+ return NGX_CONF_OK;
+}
+
+
+static void *
+ngx_stream_access_create_srv_conf(ngx_conf_t *cf)
+{
+ ngx_stream_access_srv_conf_t *conf;
+
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_access_srv_conf_t));
+ if (conf == NULL) {
+ return NULL;
+ }
+
+ return conf;
+}
+
+
+static char *
+ngx_stream_access_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+ ngx_stream_access_srv_conf_t *prev = parent;
+ ngx_stream_access_srv_conf_t *conf = child;
+
+ if (conf->rules == NULL
+#if (NGX_HAVE_INET6)
+ && conf->rules6 == NULL
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ && conf->rules_un == NULL
+#endif
+ ) {
+ conf->rules = prev->rules;
+#if (NGX_HAVE_INET6)
+ conf->rules6 = prev->rules6;
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ conf->rules_un = prev->rules_un;
+#endif
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_stream_access_init(ngx_conf_t *cf)
+{
+ ngx_stream_core_main_conf_t *cmcf;
+
+ cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
+ cmcf->access_handler = ngx_stream_access_handler;
+
+ return NGX_OK;
+}
diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c
index c8d8e66bc..246f55c45 100644
--- a/src/stream/ngx_stream_core_module.c
+++ b/src/stream/ngx_stream_core_module.c
@@ -50,6 +50,8 @@ static ngx_command_t ngx_stream_core_commands[] = {
static ngx_stream_module_t ngx_stream_core_module_ctx = {
+ NULL, /* postconfiguration */
+
ngx_stream_core_create_main_conf, /* create main configuration */
NULL, /* init main configuration */
@@ -272,7 +274,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
for (i = 0; i < cmcf->listen.nelts; i++) {
- sa = (struct sockaddr *) ls[i].sockaddr;
+ sa = &ls[i].u.sockaddr;
if (sa->sa_family != u.family) {
continue;
@@ -284,7 +286,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
case AF_INET6:
off = offsetof(struct sockaddr_in6, sin6_addr);
len = 16;
- sin6 = (struct sockaddr_in6 *) sa;
+ sin6 = &ls[i].u.sockaddr_in6;
port = sin6->sin6_port;
break;
#endif
@@ -300,12 +302,14 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
default: /* AF_INET */
off = offsetof(struct sockaddr_in, sin_addr);
len = 4;
- sin = (struct sockaddr_in *) sa;
+ sin = &ls[i].u.sockaddr_in;
port = sin->sin_port;
break;
}
- if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) {
+ if (ngx_memcmp(ls[i].u.sockaddr_data + off, u.sockaddr + off, len)
+ != 0)
+ {
continue;
}
@@ -325,9 +329,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_memzero(ls, sizeof(ngx_stream_listen_t));
- ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
+ ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen);
ls->socklen = u.socklen;
+ ls->backlog = NGX_LISTEN_BACKLOG;
ls->wildcard = u.wildcard;
ls->ctx = cf->ctx;
@@ -342,12 +347,25 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue;
}
+ if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
+ ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
+ ls->bind = 1;
+
+ if (ls->backlog == NGX_ERROR || ls->backlog == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid backlog \"%V\"", &value[i]);
+ return NGX_CONF_ERROR;
+ }
+
+ continue;
+ }
+
if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
struct sockaddr *sa;
u_char buf[NGX_SOCKADDR_STRLEN];
- sa = (struct sockaddr *) ls->sockaddr;
+ sa = &ls->u.sockaddr;
if (sa->sa_family == AF_INET6) {
diff --git a/src/stream/ngx_stream_handler.c b/src/stream/ngx_stream_handler.c
index 2be5183c1..e4538b241 100644
--- a/src/stream/ngx_stream_handler.c
+++ b/src/stream/ngx_stream_handler.c
@@ -23,20 +23,22 @@ static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c);
void
ngx_stream_init_connection(ngx_connection_t *c)
{
- u_char text[NGX_SOCKADDR_STRLEN];
- size_t len;
- ngx_uint_t i;
- struct sockaddr *sa;
- ngx_stream_port_t *port;
- struct sockaddr_in *sin;
- ngx_stream_in_addr_t *addr;
- ngx_stream_session_t *s;
- ngx_stream_addr_conf_t *addr_conf;
+ u_char text[NGX_SOCKADDR_STRLEN];
+ size_t len;
+ ngx_int_t rc;
+ ngx_uint_t i;
+ struct sockaddr *sa;
+ ngx_stream_port_t *port;
+ struct sockaddr_in *sin;
+ ngx_stream_in_addr_t *addr;
+ ngx_stream_session_t *s;
+ ngx_stream_addr_conf_t *addr_conf;
#if (NGX_HAVE_INET6)
- struct sockaddr_in6 *sin6;
- ngx_stream_in6_addr_t *addr6;
+ struct sockaddr_in6 *sin6;
+ ngx_stream_in6_addr_t *addr6;
#endif
- ngx_stream_core_srv_conf_t *cscf;
+ ngx_stream_core_srv_conf_t *cscf;
+ ngx_stream_core_main_conf_t *cmcf;
/* find the server configuration for the address:port */
@@ -143,6 +145,17 @@ ngx_stream_init_connection(ngx_connection_t *c)
c->log->action = "initializing connection";
c->log_error = NGX_ERROR_INFO;
+ cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
+
+ if (cmcf->access_handler) {
+ rc = cmcf->access_handler(s);
+
+ if (rc != NGX_OK && rc != NGX_DECLINED) {
+ ngx_stream_close_connection(c);
+ return;
+ }
+ }
+
#if (NGX_STREAM_SSL)
{
ngx_stream_ssl_conf_t *sslcf;
diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c
index a34b7ceb9..8c88505db 100644
--- a/src/stream/ngx_stream_proxy_module.c
+++ b/src/stream/ngx_stream_proxy_module.c
@@ -21,6 +21,8 @@ typedef struct {
size_t upstream_buf_size;
ngx_uint_t next_upstream_tries;
ngx_flag_t next_upstream;
+ ngx_flag_t proxy_protocol;
+ ngx_addr_t *local;
#if (NGX_STREAM_SSL)
ngx_flag_t ssl_enable;
@@ -64,6 +66,9 @@ static char *ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent,
void *child);
static char *ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+static ngx_int_t ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s);
#if (NGX_STREAM_SSL)
@@ -97,6 +102,13 @@ static ngx_command_t ngx_stream_proxy_commands[] = {
0,
NULL },
+ { ngx_string("proxy_bind"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_stream_proxy_bind,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("proxy_connect_timeout"),
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@@ -146,6 +158,13 @@ static ngx_command_t ngx_stream_proxy_commands[] = {
offsetof(ngx_stream_proxy_srv_conf_t, next_upstream_timeout),
NULL },
+ { ngx_string("proxy_protocol"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol),
+ NULL },
+
#if (NGX_STREAM_SSL)
{ ngx_string("proxy_ssl"),
@@ -246,6 +265,8 @@ static ngx_command_t ngx_stream_proxy_commands[] = {
static ngx_stream_module_t ngx_stream_proxy_module_ctx = {
+ NULL, /* postconfiguration */
+
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -299,6 +320,8 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s)
u->peer.log = c->log;
u->peer.log_error = NGX_ERROR_ERR;
+ u->peer.local = pscf->local;
+
uscf = pscf->upstream;
if (uscf->peer.init(s, uscf) != NGX_OK) {
@@ -314,6 +337,8 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s)
u->peer.tries = pscf->next_upstream_tries;
}
+ u->proxy_protocol = pscf->proxy_protocol;
+
p = ngx_pnalloc(c->pool, pscf->downstream_buf_size);
if (p == NULL) {
ngx_stream_proxy_finalize(s, NGX_ERROR);
@@ -328,6 +353,29 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s)
c->write->handler = ngx_stream_proxy_downstream_handler;
c->read->handler = ngx_stream_proxy_downstream_handler;
+ if (u->proxy_protocol
+#if (NGX_STREAM_SSL)
+ && pscf->ssl == NULL
+#endif
+ && pscf->downstream_buf_size >= NGX_PROXY_PROTOCOL_MAX_HEADER
+ )
+ {
+ /* optimization for a typical case */
+
+ ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
+ "stream proxy send PROXY protocol header");
+
+ p = ngx_proxy_protocol_write(c, u->downstream_buf.last,
+ u->downstream_buf.end);
+ if (p == NULL) {
+ ngx_stream_proxy_finalize(s, NGX_ERROR);
+ return;
+ }
+
+ u->downstream_buf.last = p;
+ u->proxy_protocol = 0;
+ }
+
if (ngx_stream_proxy_process(s, 0, 0) != NGX_OK) {
return;
}
@@ -403,10 +451,18 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
ngx_stream_upstream_t *u;
ngx_stream_proxy_srv_conf_t *pscf;
- pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
-
u = s->upstream;
+ if (u->proxy_protocol) {
+ if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) {
+ return;
+ }
+
+ u->proxy_protocol = 0;
+ }
+
+ pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
+
pc = u->peer.connection;
#if (NGX_STREAM_SSL)
@@ -460,6 +516,76 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
}
+static ngx_int_t
+ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s)
+{
+ u_char *p;
+ ssize_t n, size;
+ ngx_connection_t *c, *pc;
+ ngx_stream_upstream_t *u;
+ ngx_stream_proxy_srv_conf_t *pscf;
+ u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
+
+ c = s->connection;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
+ "stream proxy send PROXY protocol header");
+
+ p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER);
+ if (p == NULL) {
+ ngx_stream_proxy_finalize(s, NGX_ERROR);
+ return NGX_ERROR;
+ }
+
+ u = s->upstream;
+
+ pc = u->peer.connection;
+
+ size = p - buf;
+
+ n = pc->send(pc, buf, size);
+
+ if (n == NGX_AGAIN) {
+ if (ngx_handle_write_event(pc->write, 0) != NGX_OK) {
+ ngx_stream_proxy_finalize(s, NGX_ERROR);
+ return NGX_ERROR;
+ }
+
+ pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
+
+ ngx_add_timer(pc->write, pscf->timeout);
+
+ pc->write->handler = ngx_stream_proxy_connect_handler;
+
+ return NGX_AGAIN;
+ }
+
+ if (n == NGX_ERROR) {
+ ngx_stream_proxy_finalize(s, NGX_DECLINED);
+ return NGX_ERROR;
+ }
+
+ if (n != size) {
+
+ /*
+ * PROXY protocol specification:
+ * The sender must always ensure that the header
+ * is sent at once, so that the transport layer
+ * maintains atomicity along the path to the receiver.
+ */
+
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
+ "could not send PROXY protocol header at once");
+
+ ngx_stream_proxy_finalize(s, NGX_DECLINED);
+
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
#if (NGX_STREAM_SSL)
static char *
@@ -1091,6 +1217,8 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
conf->upstream_buf_size = NGX_CONF_UNSET_SIZE;
conf->next_upstream_tries = NGX_CONF_UNSET_UINT;
conf->next_upstream = NGX_CONF_UNSET;
+ conf->proxy_protocol = NGX_CONF_UNSET;
+ conf->local = NGX_CONF_UNSET_PTR;
#if (NGX_STREAM_SSL)
conf->ssl_enable = NGX_CONF_UNSET;
@@ -1131,6 +1259,10 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, 1);
+ ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0);
+
+ ngx_conf_merge_ptr_value(conf->local, prev->local, NULL);
+
#if (NGX_STREAM_SSL)
ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0);
@@ -1288,3 +1420,45 @@ ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK;
}
+
+
+static char *
+ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_stream_proxy_srv_conf_t *pscf = conf;
+
+ ngx_int_t rc;
+ ngx_str_t *value;
+
+ if (pscf->local != NGX_CONF_UNSET_PTR) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ if (ngx_strcmp(value[1].data, "off") == 0) {
+ pscf->local = NULL;
+ return NGX_CONF_OK;
+ }
+
+ pscf->local = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
+ if (pscf->local == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ rc = ngx_parse_addr(cf->pool, pscf->local, value[1].data, value[1].len);
+
+ switch (rc) {
+ case NGX_OK:
+ pscf->local->name = value[1];
+ return NGX_CONF_OK;
+
+ case NGX_DECLINED:
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid address \"%V\"", &value[1]);
+ /* fall through */
+
+ default:
+ return NGX_CONF_ERROR;
+ }
+}
diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c
index 4b27a1e3e..97a0fa972 100644
--- a/src/stream/ngx_stream_ssl_module.c
+++ b/src/stream/ngx_stream_ssl_module.c
@@ -132,6 +132,8 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
static ngx_stream_module_t ngx_stream_ssl_module_ctx = {
+ NULL, /* postconfiguration */
+
NULL, /* create main configuration */
NULL, /* init main configuration */
diff --git a/src/stream/ngx_stream_upstream.c b/src/stream/ngx_stream_upstream.c
index a991f8a9f..f21e17d76 100644
--- a/src/stream/ngx_stream_upstream.c
+++ b/src/stream/ngx_stream_upstream.c
@@ -39,6 +39,8 @@ static ngx_command_t ngx_stream_upstream_commands[] = {
static ngx_stream_module_t ngx_stream_upstream_module_ctx = {
+ NULL, /* postconfiguration */
+
ngx_stream_upstream_create_main_conf, /* create main configuration */
ngx_stream_upstream_init_main_conf, /* init main configuration */
diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h
index 83353edca..56325da02 100644
--- a/src/stream/ngx_stream_upstream.h
+++ b/src/stream/ngx_stream_upstream.h
@@ -86,6 +86,8 @@ typedef struct {
#if (NGX_STREAM_SSL)
ngx_str_t ssl_name;
#endif
+ ngx_uint_t proxy_protocol;
+ /* unsigned proxy_protocol:1; */
} ngx_stream_upstream_t;
diff --git a/src/stream/ngx_stream_upstream_hash_module.c b/src/stream/ngx_stream_upstream_hash_module.c
index 88e74145f..56ff7d6e9 100644
--- a/src/stream/ngx_stream_upstream_hash_module.c
+++ b/src/stream/ngx_stream_upstream_hash_module.c
@@ -76,6 +76,8 @@ static ngx_command_t ngx_stream_upstream_hash_commands[] = {
static ngx_stream_module_t ngx_stream_upstream_hash_module_ctx = {
+ NULL, /* postconfiguration */
+
NULL, /* create main configuration */
NULL, /* init main configuration */
diff --git a/src/stream/ngx_stream_upstream_least_conn_module.c b/src/stream/ngx_stream_upstream_least_conn_module.c
index eae4b177d..677da4549 100644
--- a/src/stream/ngx_stream_upstream_least_conn_module.c
+++ b/src/stream/ngx_stream_upstream_least_conn_module.c
@@ -32,6 +32,8 @@ static ngx_command_t ngx_stream_upstream_least_conn_commands[] = {
static ngx_stream_module_t ngx_stream_upstream_least_conn_module_ctx = {
+ NULL, /* postconfiguration */
+
NULL, /* create main configuration */
NULL, /* init main configuration */
diff --git a/src/stream/ngx_stream_upstream_zone_module.c b/src/stream/ngx_stream_upstream_zone_module.c
index 95a778f10..6025aee7d 100644
--- a/src/stream/ngx_stream_upstream_zone_module.c
+++ b/src/stream/ngx_stream_upstream_zone_module.c
@@ -32,6 +32,8 @@ static ngx_command_t ngx_stream_upstream_zone_commands[] = {
static ngx_stream_module_t ngx_stream_upstream_zone_module_ctx = {
+ NULL, /* postconfiguration */
+
NULL, /* create main configuration */
NULL, /* init main configuration */