New upstream version 1.20.2

This commit is contained in:
Thomas Ward 2022-04-19 09:50:28 -04:00
parent b283023b77
commit 5c35f1696f
97 changed files with 6154 additions and 1066 deletions

261
CHANGES
View file

@ -1,7 +1,264 @@
Changes with nginx 1.18.0 21 Apr 2020
Changes with nginx 1.20.2 16 Nov 2021
*) 1.18.x stable branch.
*) Feature: OpenSSL 3.0 compatibility.
*) Bugfix: SSL variables might be empty when used in logs; the bug had
appeared in 1.19.5.
*) Bugfix: keepalive connections with gRPC backends might not be closed
after receiving a GOAWAY frame.
*) Bugfix: backend SSL connections in the stream module might hang after
an SSL handshake.
*) Bugfix: SSL connections with gRPC backends might hang if select,
poll, or /dev/poll methods were used.
*) Bugfix: in the $content_length variable when using chunked transfer
encoding.
*) Bugfix: requests might hang when using HTTP/2 and the "aio_write"
directive.
Changes with nginx 1.20.1 25 May 2021
*) Security: 1-byte memory overwrite might occur during DNS server
response processing if the "resolver" directive was used, allowing an
attacker who is able to forge UDP packets from the DNS server to
cause worker process crash or, potentially, arbitrary code execution
(CVE-2021-23017).
Changes with nginx 1.20.0 20 Apr 2021
*) 1.20.x stable branch.
Changes with nginx 1.19.10 13 Apr 2021
*) Change: the default value of the "keepalive_requests" directive was
changed to 1000.
*) Feature: the "keepalive_time" directive.
*) Feature: the $connection_time variable.
*) Workaround: "gzip filter failed to use preallocated memory" alerts
appeared in logs when using zlib-ng.
Changes with nginx 1.19.9 30 Mar 2021
*) Bugfix: nginx could not be built with the mail proxy module, but
without the ngx_mail_ssl_module; the bug had appeared in 1.19.8.
*) Bugfix: "upstream sent response body larger than indicated content
length" errors might occur when working with gRPC backends; the bug
had appeared in 1.19.1.
*) Bugfix: nginx might not close a connection till keepalive timeout
expiration if the connection was closed by the client while
discarding the request body.
*) Bugfix: nginx might not detect that a connection was already closed
by the client when waiting for auth_delay or limit_req delay, or when
working with backends.
*) Bugfix: in the eventport method.
Changes with nginx 1.19.8 09 Mar 2021
*) Feature: flags in the "proxy_cookie_flags" directive can now contain
variables.
*) Feature: the "proxy_protocol" parameter of the "listen" directive,
the "proxy_protocol" and "set_real_ip_from" directives in mail proxy.
*) Bugfix: HTTP/2 connections were immediately closed when using
"keepalive_timeout 0"; the bug had appeared in 1.19.7.
*) Bugfix: some errors were logged as unknown if nginx was built with
glibc 2.32.
*) Bugfix: in the eventport method.
Changes with nginx 1.19.7 16 Feb 2021
*) Change: connections handling in HTTP/2 has been changed to better
match HTTP/1.x; the "http2_recv_timeout", "http2_idle_timeout", and
"http2_max_requests" directives have been removed, the
"keepalive_timeout" and "keepalive_requests" directives should be
used instead.
*) Change: the "http2_max_field_size" and "http2_max_header_size"
directives have been removed, the "large_client_header_buffers"
directive should be used instead.
*) Feature: now, if free worker connections are exhausted, nginx starts
closing not only keepalive connections, but also connections in
lingering close.
*) Bugfix: "zero size buf in output" alerts might appear in logs if an
upstream server returned an incorrect response during unbuffered
proxying; the bug had appeared in 1.19.1.
*) Bugfix: HEAD requests were handled incorrectly if the "return"
directive was used with the "image_filter" or "xslt_stylesheet"
directives.
*) Bugfix: in the "add_trailer" directive.
Changes with nginx 1.19.6 15 Dec 2020
*) Bugfix: "no live upstreams" errors if a "server" inside "upstream"
block was marked as "down".
*) Bugfix: a segmentation fault might occur in a worker process if HTTPS
was used; the bug had appeared in 1.19.5.
*) Bugfix: nginx returned the 400 response on requests like
"GET http://example.com?args HTTP/1.0".
*) Bugfix: in the ngx_http_flv_module and ngx_http_mp4_module.
Thanks to Chris Newton.
Changes with nginx 1.19.5 24 Nov 2020
*) Feature: the -e switch.
*) Feature: the same source files can now be specified in different
modules while building addon modules.
*) Bugfix: SSL shutdown did not work when lingering close was used.
*) Bugfix: "upstream sent frame for closed stream" errors might occur
when working with gRPC backends.
*) Bugfix: in request body filters internal API.
Changes with nginx 1.19.4 27 Oct 2020
*) Feature: the "ssl_conf_command", "proxy_ssl_conf_command",
"grpc_ssl_conf_command", and "uwsgi_ssl_conf_command" directives.
*) Feature: the "ssl_reject_handshake" directive.
*) Feature: the "proxy_smtp_auth" directive in mail proxy.
Changes with nginx 1.19.3 29 Sep 2020
*) Feature: the ngx_stream_set_module.
*) Feature: the "proxy_cookie_flags" directive.
*) Feature: the "userid_flags" directive.
*) Bugfix: the "stale-if-error" cache control extension was erroneously
applied if backend returned a response with status code 500, 502,
503, 504, 403, 404, or 429.
*) Bugfix: "[crit] cache file ... has too long header" messages might
appear in logs if caching was used and the backend returned responses
with the "Vary" header line.
*) Workaround: "[crit] SSL_write() failed" messages might appear in logs
when using OpenSSL 1.1.1.
*) Bugfix: "SSL_shutdown() failed (SSL: ... bad write retry)" messages
might appear in logs; the bug had appeared in 1.19.2.
*) Bugfix: a segmentation fault might occur in a worker process when
using HTTP/2 if errors with code 400 were redirected to a proxied
location using the "error_page" directive.
*) Bugfix: socket leak when using HTTP/2 and subrequests in the njs
module.
Changes with nginx 1.19.2 11 Aug 2020
*) Change: now nginx starts closing keepalive connections before all
free worker connections are exhausted, and logs a warning about this
to the error log.
*) Change: optimization of client request body reading when using
chunked transfer encoding.
*) Bugfix: memory leak if the "ssl_ocsp" directive was used.
*) Bugfix: "zero size buf in output" alerts might appear in logs if a
FastCGI server returned an incorrect response; the bug had appeared
in 1.19.1.
*) Bugfix: a segmentation fault might occur in a worker process if
different large_client_header_buffers sizes were used in different
virtual servers.
*) Bugfix: SSL shutdown might not work.
*) Bugfix: "SSL_shutdown() failed (SSL: ... bad write retry)" messages
might appear in logs.
*) Bugfix: in the ngx_http_slice_module.
*) Bugfix: in the ngx_http_xslt_filter_module.
Changes with nginx 1.19.1 07 Jul 2020
*) Change: the "lingering_close", "lingering_time", and
"lingering_timeout" directives now work when using HTTP/2.
*) Change: now extra data sent by a backend are always discarded.
*) Change: now after receiving a too short response from a FastCGI
server nginx tries to send the available part of the response to the
client, and then closes the client connection.
*) Change: now after receiving a response with incorrect length from a
gRPC backend nginx stops response processing with an error.
*) Feature: the "min_free" parameter of the "proxy_cache_path",
"fastcgi_cache_path", "scgi_cache_path", and "uwsgi_cache_path"
directives.
Thanks to Adam Bambuch.
*) Bugfix: nginx did not delete unix domain listen sockets during
graceful shutdown on the SIGQUIT signal.
*) Bugfix: zero length UDP datagrams were not proxied.
*) Bugfix: proxying to uwsgi backends using SSL might not work.
Thanks to Guanzhong Chen.
*) Bugfix: in error handling when using the "ssl_ocsp" directive.
*) Bugfix: on XFS and NFS file systems disk cache size might be
calculated incorrectly.
*) Bugfix: "negative size buf in writer" alerts might appear in logs if
a memcached server returned a malformed response.
Changes with nginx 1.19.0 26 May 2020
*) Feature: client certificate validation with OCSP.
*) Bugfix: "upstream sent frame for closed stream" errors might occur
when working with gRPC backends.
*) Bugfix: OCSP stapling might not work if the "resolver" directive was
not specified.
*) Bugfix: connections with incorrect HTTP/2 preface were not logged.
Changes with nginx 1.17.10 14 Apr 2020

View file

@ -1,7 +1,266 @@
Изменения в nginx 1.18.0 21.04.2020
Изменения в nginx 1.20.2 16.11.2021
*) Стабильная ветка 1.18.x.
*) Добавление: совместимость с OpenSSL 3.0.
*) Исправление: SSL-переменные могли быть пустыми при записи в лог;
ошибка появилась в 1.19.5.
*) Исправление: keepalive-соединения с gRPC-бэкендами могли не
закрываться после получения GOAWAY-фрейма.
*) Исправление: SSL-соединения к бэкендам в модуле stream могли зависать
после SSL handshake.
*) Исправление: SSL-соединения с gRPC-бэкендами могли зависать, если
использовались методы select, poll или /dev/poll.
*) Исправление: в переменной $content_length при использовании chunked
transfer encoding.
*) Исправление: при использовании HTTP/2 и директивы aio_write запросы
могли зависать.
Изменения в nginx 1.20.1 25.05.2021
*) Безопасность: при использовании директивы resolver во время обработки
ответа DNS-сервера могла происходить перезапись одного байта памяти,
что позволяло атакующему, имеющему возможность подделывать UDP-пакеты
от DNS-сервера, вызвать падение рабочего процесса или, потенциально,
выполнение произвольного кода (CVE-2021-23017).
Изменения в nginx 1.20.0 20.04.2021
*) Стабильная ветка 1.20.x.
Изменения в nginx 1.19.10 13.04.2021
*) Изменение: в директиве keepalive_requests значение по умолчанию
изменено на 1000.
*) Добавление: директива keepalive_time.
*) Добавление: переменная $connection_time.
*) Изменение: при использовании zlib-ng в логах появлялись сообщения
"gzip filter failed to use preallocated memory".
Изменения в nginx 1.19.9 30.03.2021
*) Исправление: nginx не собирался с почтовым прокси-сервером, но без
модуля ngx_mail_ssl_module; ошибка появилась в 1.19.8.
*) Исправление: при работе с gRPC-бэкендами могли возникать ошибки
"upstream sent response body larger than indicated content length";
ошибка появилась в 1.19.1.
*) Исправление: если клиент закрывал соединение в момент отбрасывания
тела запроса, nginx мог не закрыть соединение до истечения
keepalive-таймаута.
*) Исправление: при ожидании задержки limit_req или auth_delay, а также
при работе с бэкендами nginx мог не обнаружить, что соединение уже
закрыто клиентом.
*) Исправление: в методе обработки соединений eventport.
Изменения в nginx 1.19.8 09.03.2021
*) Добавление: в директиве proxy_cookie_flags теперь флаги можно
задавать с помощью переменных.
*) Добавление: параметр proxy_protocol в директиве listen, директивы
proxy_protocol и set_real_ip_from в почтовом прокси-сервере.
*) Исправление: HTTP/2-соединения сразу закрывались при использовании
"keepalive_timeout 0"; ошибка появилась в 1.19.7.
*) Исправление: некоторые ошибки логгировались как неизвестные, если
nginx был собран с glibc 2.32.
*) Исправление: в методе обработки соединений eventport.
Изменения в nginx 1.19.7 16.02.2021
*) Изменение: обработка соединений в HTTP/2 была изменена и теперь более
соответствует HTTP/1.x; директивы http2_recv_timeout,
http2_idle_timeout и http2_max_requests упразднены, вместо них
следует использовать директивы keepalive_timeout и
keepalive_requests.
*) Изменение: директивы http2_max_field_size и http2_max_header_size
упразднены, вместо них следует использовать директиву
large_client_header_buffers.
*) Добавление: теперь при исчерпании свободных соединений nginx
закрывает не только keepalive-соединения, но и соединения в lingering
close.
*) Исправление: в логах могли появляться сообщения "zero size buf in
output", если бэкенд возвращал некорректный ответ при
небуферизированном проксировании; ошибка появилась в 1.19.1.
*) Исправление: при использовании директивы return вместе с image_filter
или xslt_stylesheet HEAD-запросы обрабатывались некорректно.
*) Исправление: в директиве add_trailer.
Изменения в nginx 1.19.6 15.12.2020
*) Исправление: ошибки "no live upstreams", если server в блоке upstream
был помечен как down.
*) Исправление: при использовании HTTPS в рабочем процессе мог произойти
segmentation fault; ошибка появилась в 1.19.5.
*) Исправление: nginx возвращал ошибку 400 на запросы вида
"GET http://example.com?args HTTP/1.0".
*) Исправление: в модулях ngx_http_flv_module и ngx_http_mp4_module.
Спасибо Chris Newton.
Изменения в nginx 1.19.5 24.11.2020
*) Добавление: ключ -e.
*) Добавление: при сборке дополнительных модулей теперь можно указывать
одни и те же исходные файлы в разных модулях.
*) Исправление: SSL shutdown не работал при закрытии соединений с
ожиданием дополнительных данных (lingering close).
*) Исправление: при работе с gRPC-бэкендами могли возникать ошибки
"upstream sent frame for closed stream".
*) Исправление: во внутреннем API для обработки тела запроса.
Изменения в nginx 1.19.4 27.10.2020
*) Добавление: директивы ssl_conf_command, proxy_ssl_conf_command,
grpc_ssl_conf_command и uwsgi_ssl_conf_command.
*) Добавление: директива ssl_reject_handshake.
*) Добавление: директива proxy_smtp_auth в почтовом прокси-сервере.
Изменения в nginx 1.19.3 29.09.2020
*) Добавление: модуль ngx_stream_set_module.
*) Добавление: директива proxy_cookie_flags.
*) Добавление: директива userid_flags.
*) Исправление: расширение управления кэшированием stale-if-error
ошибочно применялось, если бэкенд возвращал ответ с кодом 500, 502,
503, 504, 403, 404 или 429.
*) Исправление: если использовалось кэширование и бэкенд возвращал
ответы с строкой заголовка Vary, в логах могли появляться сообщения
"[crit] cache file ... has too long header".
*) Изменение: при использовании OpenSSL 1.1.1 в логах могли появляться
сообщения "[crit] SSL_write() failed".
*) Исправление: в логах могли появляться сообщения "SSL_shutdown()
failed (SSL: ... bad write retry)"; ошибка появилась в 1.19.2.
*) Исправление: при использовании HTTP/2 в рабочем процессе мог
произойти segmentation fault, если ошибки с кодом 400 с помощью
директивы error_page перенаправлялись в проксируемый location.
*) Исправление: утечки сокетов при использовании HTTP/2 и подзапросов в
модуле njs.
Изменения в nginx 1.19.2 11.08.2020
*) Изменение: теперь nginx начинает закрывать keepalive-соединения, не
дожидаясь исчерпания всех свободных соединений, а также пишет об этом
предупреждение в лог ошибок.
*) Изменение: оптимизация чтения тела запроса при использовании chunked
transfer encoding.
*) Исправление: утечки памяти при использовании директивы ssl_ocsp.
*) Исправление: в логах могли появляться сообщения "zero size buf in
output", если FastCGI-сервер возвращал некорректный ответ; ошибка
появилась в 1.19.1.
*) Исправление: в рабочем процессе мог произойти segmentation fault,
если размеры large_client_header_buffers отличались в разных
виртуальных серверах.
*) Исправление: SSL shutdown мог не работать.
*) Исправление: в логах могли появляться сообщения "SSL_shutdown()
failed (SSL: ... bad write retry)".
*) Исправление: в модуле ngx_http_slice_module.
*) Исправление: в модуле ngx_http_xslt_filter_module.
Изменения в nginx 1.19.1 07.07.2020
*) Изменение: директивы lingering_close, lingering_time и
lingering_timeout теперь работают при использовании HTTP/2.
*) Изменение: теперь лишние данные, присланные бэкендом, всегда
отбрасываются.
*) Изменение: теперь при получении слишком короткого ответа от
FastCGI-сервера nginx пытается отправить клиенту доступную часть
ответа, после чего закрывает соединение с клиентом.
*) Изменение: теперь при получении ответа некорректной длины от
gRPC-бэкенда nginx прекращает обработку ответа с ошибкой.
*) Добавление: параметр min_free в директивах proxy_cache_path,
fastcgi_cache_path, scgi_cache_path и uwsgi_cache_path.
Спасибо Adam Bambuch.
*) Исправление: nginx не удалял unix domain listen-сокеты при плавном
завершении по сигналу SIGQUIT.
*) Исправление: UDP-пакеты нулевого размера не проксировались.
*) Исправление: проксирование на uwsgi-бэкенды с использованием SSL
могло не работать.
Спасибо Guanzhong Chen.
*) Исправление: в обработке ошибок при использовании директивы ssl_ocsp.
*) Исправление: при использовании файловых систем XFS и NFS размер кэша
на диске мог считаться некорректно.
*) Исправление: если сервер memcached возвращал некорректный ответ, в
логах могли появляться сообщения "negative size buf in writer".
Изменения в nginx 1.19.0 26.05.2020
*) Добавление: проверка клиентских сертификатов с помощью OCSP.
*) Исправление: при работе с gRPC-бэкендами могли возникать ошибки
"upstream sent frame for closed stream".
*) Исправление: OCSP stapling мог не работать, если не была указана
директива resolver.
*) Исправление: соединения с некорректным HTTP/2 preface не
логгировались.
Изменения в nginx 1.17.10 14.04.2020

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2019 Igor Sysoev
* Copyright (C) 2011-2019 Nginx, Inc.
* Copyright (C) 2002-2021 Igor Sysoev
* Copyright (C) 2011-2021 Nginx, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View file

@ -48,4 +48,6 @@ default: build
clean:
rm -rf Makefile $NGX_OBJS
.PHONY: default clean
END

View file

@ -215,4 +215,6 @@ upgrade:
test -f $NGX_PID_PATH.oldbin
kill -QUIT \`cat $NGX_PID_PATH.oldbin\`
.PHONY: build install modules upgrade
END

View file

@ -313,7 +313,7 @@ $ngx_obj: \$(CORE_DEPS) \$(HTTP_DEPS)$ngx_cont$ngx_src
END
fi
done
done
fi
@ -343,7 +343,7 @@ $ngx_obj: \$(CORE_DEPS) \$(MAIL_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
done
done
fi
@ -373,7 +373,7 @@ $ngx_obj: \$(CORE_DEPS) \$(STREAM_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
done
done
fi
@ -399,7 +399,7 @@ $ngx_obj: \$(CORE_DEPS) $ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
done
done
fi
@ -431,7 +431,7 @@ $ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
done
done
fi
@ -502,6 +502,7 @@ fi
for ngx_module in $DYNAMIC_MODULES
do
eval ngx_module_srcs="\$${ngx_module}_SRCS"
eval ngx_module_shrd="\$${ngx_module}_SHRD"
eval eval ngx_module_libs="\\\"\$${ngx_module}_LIBS\\\""
eval ngx_module_modules="\$${ngx_module}_MODULES"
@ -567,7 +568,7 @@ END
| sed -e "s/\(.*\.\)c/\1$ngx_objext/"`
ngx_module_objs=
for ngx_src in $ngx_module_srcs
for ngx_src in $ngx_module_srcs $ngx_module_shrd
do
case "$ngx_src" in
src/*)

View file

@ -17,7 +17,6 @@ if [ "$ngx_module_link" = DYNAMIC ]; then
done
DYNAMIC_MODULES="$DYNAMIC_MODULES $ngx_module"
eval ${ngx_module}_SRCS=\"$ngx_module_srcs\"
eval ${ngx_module}_MODULES=\"$ngx_module_name\"
@ -31,6 +30,30 @@ if [ "$ngx_module_link" = DYNAMIC ]; then
eval ${ngx_module}_ORDER=\"$ngx_module_order\"
fi
srcs=
shrd=
for src in $ngx_module_srcs
do
found=no
for old in $DYNAMIC_MODULES_SRCS
do
if [ $src = $old ]; then
found=yes
break
fi
done
if [ $found = no ]; then
srcs="$srcs $src"
else
shrd="$shrd $src"
fi
done
eval ${ngx_module}_SRCS=\"$srcs\"
eval ${ngx_module}_SHRD=\"$shrd\"
DYNAMIC_MODULES_SRCS="$DYNAMIC_MODULES_SRCS $srcs"
if test -n "$ngx_module_incs"; then
CORE_INCS="$CORE_INCS $ngx_module_incs"
fi
@ -107,7 +130,24 @@ elif [ "$ngx_module_link" = ADDON ]; then
eval ${ngx_module_type}_MODULES=\"\$${ngx_module_type}_MODULES \
$ngx_module_name\"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_module_srcs"
srcs=
for src in $ngx_module_srcs
do
found=no
for old in $NGX_ADDON_SRCS
do
if [ $src = $old ]; then
found=yes
break
fi
done
if [ $found = no ]; then
srcs="$srcs $src"
fi
done
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $srcs"
if test -n "$ngx_module_incs"; then
eval ${ngx_var}_INCS=\"\$${ngx_var}_INCS $ngx_module_incs\"

View file

@ -985,6 +985,12 @@ if [ $MAIL != NO ]; then
ngx_module_srcs=src/mail/ngx_mail_proxy_module.c
. auto/module
ngx_module_name=ngx_mail_realip_module
ngx_module_deps=
ngx_module_srcs=src/mail/ngx_mail_realip_module.c
. auto/module
fi
@ -1119,6 +1125,16 @@ if [ $STREAM != NO ]; then
. auto/module
fi
if [ $STREAM_SET = YES ]; then
ngx_module_name=ngx_stream_set_module
ngx_module_deps=
ngx_module_srcs=src/stream/ngx_stream_set_module.c
ngx_module_libs=
ngx_module_link=$STREAM_SET
. auto/module
fi
if [ $STREAM_UPSTREAM_HASH = YES ]; then
ngx_module_name=ngx_stream_upstream_hash_module
ngx_module_deps=

View file

@ -124,6 +124,7 @@ STREAM_GEOIP=NO
STREAM_MAP=YES
STREAM_SPLIT_CLIENTS=YES
STREAM_RETURN=YES
STREAM_SET=YES
STREAM_UPSTREAM_HASH=YES
STREAM_UPSTREAM_LEAST_CONN=YES
STREAM_UPSTREAM_RANDOM=YES
@ -131,8 +132,10 @@ STREAM_UPSTREAM_ZONE=YES
STREAM_SSL_PREREAD=NO
DYNAMIC_MODULES=
DYNAMIC_MODULES_SRCS=
NGX_ADDONS=
NGX_ADDON_SRCS=
NGX_ADDON_DEPS=
DYNAMIC_ADDONS=
@ -324,6 +327,7 @@ use the \"--with-mail_ssl_module\" option instead"
--without-stream_split_clients_module)
STREAM_SPLIT_CLIENTS=NO ;;
--without-stream_return_module) STREAM_RETURN=NO ;;
--without-stream_set_module) STREAM_SET=NO ;;
--without-stream_upstream_hash_module)
STREAM_UPSTREAM_HASH=NO ;;
--without-stream_upstream_least_conn_module)
@ -538,6 +542,7 @@ cat << END
--without-stream_split_clients_module
disable ngx_stream_split_clients_module
--without-stream_return_module disable ngx_stream_return_module
--without-stream_set_module disable ngx_stream_set_module
--without-stream_upstream_hash_module
disable ngx_stream_upstream_hash_module
--without-stream_upstream_least_conn_module

View file

@ -86,6 +86,31 @@ if [ $ngx_found = yes ]; then
ee.data.ptr = NULL;
epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)"
. auto/feature
# eventfd()
ngx_feature="eventfd()"
ngx_feature_name="NGX_HAVE_EVENTFD"
ngx_feature_run=no
ngx_feature_incs="#include <sys/eventfd.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="(void) eventfd(0, 0)"
. auto/feature
if [ $ngx_found = yes ]; then
have=NGX_HAVE_SYS_EVENTFD_H . auto/have
fi
if [ $ngx_found = no ]; then
ngx_feature="eventfd() (SYS_eventfd)"
ngx_feature_incs="#include <sys/syscall.h>"
ngx_feature_test="(void) SYS_eventfd"
. auto/feature
fi
fi

View file

@ -582,29 +582,6 @@ Currently file AIO is supported on FreeBSD 4.3+ and Linux 2.6.22+ only
END
exit 1
fi
else
ngx_feature="eventfd()"
ngx_feature_name="NGX_HAVE_EVENTFD"
ngx_feature_run=no
ngx_feature_incs="#include <sys/eventfd.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="(void) eventfd(0, 0)"
. auto/feature
if [ $ngx_found = yes ]; then
have=NGX_HAVE_SYS_EVENTFD_H . auto/have
fi
if [ $ngx_found = no ]; then
ngx_feature="eventfd() (SYS_eventfd)"
ngx_feature_incs="#include <sys/syscall.h>"
ngx_feature_test="(void) SYS_eventfd"
. auto/feature
fi
fi
@ -727,17 +704,33 @@ ngx_feature_test="char buf[1]; struct iovec vec[1]; ssize_t n;
. auto/feature
ngx_feature="sys_nerr"
ngx_feature_name="NGX_SYS_NERR"
ngx_feature_run=value
ngx_feature_incs='#include <errno.h>
#include <stdio.h>'
# strerrordesc_np(), introduced in glibc 2.32
ngx_feature="strerrordesc_np()"
ngx_feature_name="NGX_HAVE_STRERRORDESC_NP"
ngx_feature_run=no
ngx_feature_incs='#include <string.h>'
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='printf("%d", sys_nerr);'
ngx_feature_test="char *p; p = strerrordesc_np(0);
if (p == NULL) return 1"
. auto/feature
if [ $ngx_found = no ]; then
ngx_feature="sys_nerr"
ngx_feature_name="NGX_SYS_NERR"
ngx_feature_run=value
ngx_feature_incs='#include <errno.h>
#include <stdio.h>'
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='printf("%d", sys_nerr);'
. auto/feature
fi
if [ $ngx_found = no ]; then
# Cygiwn defines _sys_nerr
@ -753,34 +746,6 @@ if [ $ngx_found = no ]; then
fi
if [ $ngx_found = no ]; then
# Solaris has no sys_nerr
ngx_feature='maximum errno'
ngx_feature_name=NGX_SYS_NERR
ngx_feature_run=value
ngx_feature_incs='#include <errno.h>
#include <string.h>
#include <stdio.h>'
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='int n;
char *p;
for (n = 1; n < 1000; n++) {
errno = 0;
p = strerror(n);
if (errno == EINVAL
|| p == NULL
|| strncmp(p, "Unknown error", 13) == 0)
{
break;
}
}
printf("%d", n);'
. auto/feature
fi
ngx_feature="localtime_r()"
ngx_feature_name="NGX_HAVE_LOCALTIME_R"
ngx_feature_run=no

4
configure vendored
View file

@ -87,6 +87,10 @@ have=NGX_PID_PATH value="\"$NGX_PID_PATH\"" . auto/define
have=NGX_LOCK_PATH value="\"$NGX_LOCK_PATH\"" . auto/define
have=NGX_ERROR_LOG_PATH value="\"$NGX_ERROR_LOG_PATH\"" . auto/define
if [ ".$NGX_ERROR_LOG_PATH" = "." ]; then
have=NGX_ERROR_LOG_STDERR . auto/have
fi
have=NGX_HTTP_LOG_PATH value="\"$NGX_HTTP_LOG_PATH\"" . auto/define
have=NGX_HTTP_CLIENT_TEMP_PATH value="\"$NGX_HTTP_CLIENT_TEMP_PATH\""
. auto/define

View file

@ -141,6 +141,7 @@ syn keyword ngxDirective contained ancient_browser_value
syn keyword ngxDirective contained api
syn keyword ngxDirective contained auth_basic
syn keyword ngxDirective contained auth_basic_user_file
syn keyword ngxDirective contained auth_delay
syn keyword ngxDirective contained auth_http
syn keyword ngxDirective contained auth_http_header
syn keyword ngxDirective contained auth_http_pass_client_cert
@ -267,6 +268,7 @@ syn keyword ngxDirective contained grpc_socket_keepalive
syn keyword ngxDirective contained grpc_ssl_certificate
syn keyword ngxDirective contained grpc_ssl_certificate_key
syn keyword ngxDirective contained grpc_ssl_ciphers
syn keyword ngxDirective contained grpc_ssl_conf_command
syn keyword ngxDirective contained grpc_ssl_crl
syn keyword ngxDirective contained grpc_ssl_name
syn keyword ngxDirective contained grpc_ssl_password_file
@ -332,6 +334,7 @@ syn keyword ngxDirective contained ip_hash
syn keyword ngxDirective contained js_access
syn keyword ngxDirective contained js_content
syn keyword ngxDirective contained js_filter
syn keyword ngxDirective contained js_import
syn keyword ngxDirective contained js_include
syn keyword ngxDirective contained js_path
syn keyword ngxDirective contained js_preread
@ -348,6 +351,7 @@ syn keyword ngxDirective contained large_client_header_buffers
syn keyword ngxDirective contained least_conn
syn keyword ngxDirective contained least_time
syn keyword ngxDirective contained limit_conn
syn keyword ngxDirective contained limit_conn_dry_run
syn keyword ngxDirective contained limit_conn_log_level
syn keyword ngxDirective contained limit_conn_status
syn keyword ngxDirective contained limit_conn_zone
@ -444,6 +448,7 @@ syn keyword ngxDirective contained proxy_cache_use_stale
syn keyword ngxDirective contained proxy_cache_valid
syn keyword ngxDirective contained proxy_connect_timeout
syn keyword ngxDirective contained proxy_cookie_domain
syn keyword ngxDirective contained proxy_cookie_flags
syn keyword ngxDirective contained proxy_cookie_path
syn keyword ngxDirective contained proxy_download_rate
syn keyword ngxDirective contained proxy_force_ranges
@ -477,11 +482,13 @@ syn keyword ngxDirective contained proxy_send_timeout
syn keyword ngxDirective contained proxy_session_drop
syn keyword ngxDirective contained proxy_set_body
syn keyword ngxDirective contained proxy_set_header
syn keyword ngxDirective contained proxy_smtp_auth
syn keyword ngxDirective contained proxy_socket_keepalive
syn keyword ngxDirective contained proxy_ssl
syn keyword ngxDirective contained proxy_ssl_certificate
syn keyword ngxDirective contained proxy_ssl_certificate_key
syn keyword ngxDirective contained proxy_ssl_ciphers
syn keyword ngxDirective contained proxy_ssl_conf_command
syn keyword ngxDirective contained proxy_ssl_crl
syn keyword ngxDirective contained proxy_ssl_name
syn keyword ngxDirective contained proxy_ssl_password_file
@ -589,16 +596,21 @@ syn keyword ngxDirective contained ssl_certificate
syn keyword ngxDirective contained ssl_certificate_key
syn keyword ngxDirective contained ssl_ciphers
syn keyword ngxDirective contained ssl_client_certificate
syn keyword ngxDirective contained ssl_conf_command
syn keyword ngxDirective contained ssl_crl
syn keyword ngxDirective contained ssl_dhparam
syn keyword ngxDirective contained ssl_early_data
syn keyword ngxDirective contained ssl_ecdh_curve
syn keyword ngxDirective contained ssl_engine
syn keyword ngxDirective contained ssl_handshake_timeout
syn keyword ngxDirective contained ssl_ocsp
syn keyword ngxDirective contained ssl_ocsp_cache
syn keyword ngxDirective contained ssl_ocsp_responder
syn keyword ngxDirective contained ssl_password_file
syn keyword ngxDirective contained ssl_prefer_server_ciphers
syn keyword ngxDirective contained ssl_preread
syn keyword ngxDirective contained ssl_protocols
syn keyword ngxDirective contained ssl_reject_handshake
syn keyword ngxDirective contained ssl_session_cache
syn keyword ngxDirective contained ssl_session_ticket_key
syn keyword ngxDirective contained ssl_session_tickets
@ -637,6 +649,7 @@ syn keyword ngxDirective contained user
syn keyword ngxDirective contained userid
syn keyword ngxDirective contained userid_domain
syn keyword ngxDirective contained userid_expires
syn keyword ngxDirective contained userid_flags
syn keyword ngxDirective contained userid_mark
syn keyword ngxDirective contained userid_name
syn keyword ngxDirective contained userid_p3p
@ -687,6 +700,7 @@ syn keyword ngxDirective contained uwsgi_socket_keepalive
syn keyword ngxDirective contained uwsgi_ssl_certificate
syn keyword ngxDirective contained uwsgi_ssl_certificate_key
syn keyword ngxDirective contained uwsgi_ssl_ciphers
syn keyword ngxDirective contained uwsgi_ssl_conf_command
syn keyword ngxDirective contained uwsgi_ssl_crl
syn keyword ngxDirective contained uwsgi_ssl_name
syn keyword ngxDirective contained uwsgi_ssl_password_file
@ -732,6 +746,7 @@ syn keyword ngxDirective contained zone_sync_ssl
syn keyword ngxDirective contained zone_sync_ssl_certificate
syn keyword ngxDirective contained zone_sync_ssl_certificate_key
syn keyword ngxDirective contained zone_sync_ssl_ciphers
syn keyword ngxDirective contained zone_sync_ssl_conf_command
syn keyword ngxDirective contained zone_sync_ssl_crl
syn keyword ngxDirective contained zone_sync_ssl_name
syn keyword ngxDirective contained zone_sync_ssl_password_file
@ -770,6 +785,7 @@ syn keyword ngxDirectiveThirdParty contained auth_gss_authorized_principal
syn keyword ngxDirectiveThirdParty contained auth_gss_force_realm
syn keyword ngxDirectiveThirdParty contained auth_gss_format_full
syn keyword ngxDirectiveThirdParty contained auth_gss_keytab
syn keyword ngxDirectiveThirdParty contained auth_gss_map_to_local
syn keyword ngxDirectiveThirdParty contained auth_gss_realm
syn keyword ngxDirectiveThirdParty contained auth_gss_service_name
@ -791,8 +807,8 @@ syn keyword ngxDirectiveThirdParty contained auth_pam_set_pam_env
" AJP protocol proxy
" https://github.com/yaoweibin/nginx_ajp_module
syn keyword ngxDirectiveThirdParty contained ajp_buffer_size
syn keyword ngxDirectiveThirdParty contained ajp_buffers
syn keyword ngxDirectiveThirdParty contained ajp_buffer_size
syn keyword ngxDirectiveThirdParty contained ajp_busy_buffers_size
syn keyword ngxDirectiveThirdParty contained ajp_cache
syn keyword ngxDirectiveThirdParty contained ajp_cache_key
@ -818,6 +834,7 @@ syn keyword ngxDirectiveThirdParty contained ajp_pass_header
syn keyword ngxDirectiveThirdParty contained ajp_pass_request_body
syn keyword ngxDirectiveThirdParty contained ajp_pass_request_headers
syn keyword ngxDirectiveThirdParty contained ajp_read_timeout
syn keyword ngxDirectiveThirdParty contained ajp_secret
syn keyword ngxDirectiveThirdParty contained ajp_send_lowat
syn keyword ngxDirectiveThirdParty contained ajp_send_timeout
syn keyword ngxDirectiveThirdParty contained ajp_store
@ -854,8 +871,8 @@ syn keyword ngxDirectiveThirdParty contained content_handler_property
syn keyword ngxDirectiveThirdParty contained content_handler_type
syn keyword ngxDirectiveThirdParty contained handler_code
syn keyword ngxDirectiveThirdParty contained handler_name
syn keyword ngxDirectiveThirdParty contained handler_type
syn keyword ngxDirectiveThirdParty contained handlers_lazy_init
syn keyword ngxDirectiveThirdParty contained handler_type
syn keyword ngxDirectiveThirdParty contained header_filter_code
syn keyword ngxDirectiveThirdParty contained header_filter_name
syn keyword ngxDirectiveThirdParty contained header_filter_property
@ -871,6 +888,10 @@ syn keyword ngxDirectiveThirdParty contained jvm_options
syn keyword ngxDirectiveThirdParty contained jvm_path
syn keyword ngxDirectiveThirdParty contained jvm_var
syn keyword ngxDirectiveThirdParty contained jvm_workers
syn keyword ngxDirectiveThirdParty contained log_handler_code
syn keyword ngxDirectiveThirdParty contained log_handler_name
syn keyword ngxDirectiveThirdParty contained log_handler_property
syn keyword ngxDirectiveThirdParty contained log_handler_type
syn keyword ngxDirectiveThirdParty contained max_balanced_tcp_connections
syn keyword ngxDirectiveThirdParty contained rewrite_handler_code
syn keyword ngxDirectiveThirdParty contained rewrite_handler_name
@ -879,6 +900,7 @@ syn keyword ngxDirectiveThirdParty contained rewrite_handler_type
syn keyword ngxDirectiveThirdParty contained shared_map
syn keyword ngxDirectiveThirdParty contained write_page_size
" Certificate Transparency
" https://github.com/grahamedgecombe/nginx-ct
syn keyword ngxDirectiveThirdParty contained ssl_ct
@ -942,6 +964,7 @@ syn keyword ngxDirectiveThirdParty contained fancyindex_hide_symlinks
syn keyword ngxDirectiveThirdParty contained fancyindex_ignore
syn keyword ngxDirectiveThirdParty contained fancyindex_localtime
syn keyword ngxDirectiveThirdParty contained fancyindex_name_length
syn keyword ngxDirectiveThirdParty contained fancyindex_show_dotfiles
syn keyword ngxDirectiveThirdParty contained fancyindex_show_path
syn keyword ngxDirectiveThirdParty contained fancyindex_time_format
@ -991,8 +1014,8 @@ syn keyword ngxDirectiveThirdParty contained nchan_benchmark_publisher_distribut
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscriber_distribution
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscribers_per_channel
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_time
syn keyword ngxDirectiveThirdParty contained nchan_channel_event_string
syn keyword ngxDirectiveThirdParty contained nchan_channel_events_channel_id
syn keyword ngxDirectiveThirdParty contained nchan_channel_event_string
syn keyword ngxDirectiveThirdParty contained nchan_channel_group
syn keyword ngxDirectiveThirdParty contained nchan_channel_group_accounting
syn keyword ngxDirectiveThirdParty contained nchan_channel_id
@ -1000,6 +1023,10 @@ syn keyword ngxDirectiveThirdParty contained nchan_channel_id_split_delimiter
syn keyword ngxDirectiveThirdParty contained nchan_channel_timeout
syn keyword ngxDirectiveThirdParty contained nchan_deflate_message_for_websocket
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_event
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_comment
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_data
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_event
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_interval
syn keyword ngxDirectiveThirdParty contained nchan_group_location
syn keyword ngxDirectiveThirdParty contained nchan_group_max_channels
syn keyword ngxDirectiveThirdParty contained nchan_group_max_messages
@ -1047,10 +1074,10 @@ syn keyword ngxDirectiveThirdParty contained nchan_store_messages
syn keyword ngxDirectiveThirdParty contained nchan_stub_status
syn keyword ngxDirectiveThirdParty contained nchan_sub_channel_id
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_existing_channels_only
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request
syn keyword ngxDirectiveThirdParty contained nchan_subscriber
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_channel_id
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_compound_etag_message_id
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_first_message
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_http_raw_stream_separator
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_last_message_id
@ -1311,6 +1338,8 @@ syn keyword ngxDirectiveThirdParty contained body_filter_by_lua_file
syn keyword ngxDirectiveThirdParty contained content_by_lua
syn keyword ngxDirectiveThirdParty contained content_by_lua_block
syn keyword ngxDirectiveThirdParty contained content_by_lua_file
syn keyword ngxDirectiveThirdParty contained exit_worker_by_lua_block
syn keyword ngxDirectiveThirdParty contained exit_worker_by_lua_file
syn keyword ngxDirectiveThirdParty contained header_filter_by_lua
syn keyword ngxDirectiveThirdParty contained header_filter_by_lua_block
syn keyword ngxDirectiveThirdParty contained header_filter_by_lua_file
@ -1352,6 +1381,7 @@ syn keyword ngxDirectiveThirdParty contained lua_ssl_crl
syn keyword ngxDirectiveThirdParty contained lua_ssl_protocols
syn keyword ngxDirectiveThirdParty contained lua_ssl_trusted_certificate
syn keyword ngxDirectiveThirdParty contained lua_ssl_verify_depth
syn keyword ngxDirectiveThirdParty contained lua_thread_cache_max_entries
syn keyword ngxDirectiveThirdParty contained lua_transform_underscores_in_response_headers
syn keyword ngxDirectiveThirdParty contained lua_use_default_type
syn keyword ngxDirectiveThirdParty contained rewrite_by_lua
@ -1987,11 +2017,7 @@ syn keyword ngxDirectiveThirdParty contained concat_unique
" update upstreams' config by restful interface
" https://github.com/yzprofile/ngx_http_dyups_module
syn keyword ngxDirectiveThirdParty contained dyups_interface
syn keyword ngxDirectiveThirdParty contained dyups_read_msg_log
syn keyword ngxDirectiveThirdParty contained dyups_read_msg_timeout
syn keyword ngxDirectiveThirdParty contained dyups_shm_zone_size
syn keyword ngxDirectiveThirdParty contained dyups_trylock
syn keyword ngxDirectiveThirdParty contained dyups_upstream_conf
" add given content to the end of the response according to the condition specified
" https://github.com/flygoast/ngx_http_footer_if_filter
@ -2271,6 +2297,7 @@ syn keyword ngxDirectiveThirdParty contained testcookie_refresh_encrypt_cookie_i
syn keyword ngxDirectiveThirdParty contained testcookie_refresh_encrypt_cookie_key
syn keyword ngxDirectiveThirdParty contained testcookie_refresh_status
syn keyword ngxDirectiveThirdParty contained testcookie_refresh_template
syn keyword ngxDirectiveThirdParty contained testcookie_samesite
syn keyword ngxDirectiveThirdParty contained testcookie_secret
syn keyword ngxDirectiveThirdParty contained testcookie_secure_flag
syn keyword ngxDirectiveThirdParty contained testcookie_session
@ -2308,31 +2335,105 @@ syn keyword ngxDirectiveThirdParty contained user_agent
" https://github.com/flygoast/ngx_http_upstream_ketama_chash
syn keyword ngxDirectiveThirdParty contained ketama_chash
" nginx-sticky-module-ng
" https://github.com/ayty-adrianomartins/nginx-sticky-module-ng
syn keyword ngxDirectiveThirdParty contained sticky_no_fallback
" dynamic linking and call the function of your application
" https://github.com/Taymindis/nginx-link-function
syn keyword ngxDirectiveThirdParty contained ngx_link_func_add_prop
syn keyword ngxDirectiveThirdParty contained ngx_link_func_add_req_header
syn keyword ngxDirectiveThirdParty contained ngx_link_func_ca_cert
syn keyword ngxDirectiveThirdParty contained ngx_link_func_call
syn keyword ngxDirectiveThirdParty contained ngx_link_func_download_link_lib
syn keyword ngxDirectiveThirdParty contained ngx_link_func_lib
syn keyword ngxDirectiveThirdParty contained ngx_link_func_shm_size
syn keyword ngxDirectiveThirdParty contained ngx_link_func_subrequest
" purge content from FastCGI, proxy, SCGI and uWSGI caches
" https://github.com/torden/ngx_cache_purge
syn keyword ngxDirectiveThirdParty contained cache_purge_response_type
" set the flags "HttpOnly", "secure" and "SameSite" for cookies
" https://github.com/AirisX/nginx_cookie_flag_module
syn keyword ngxDirectiveThirdParty contained set_cookie_flag
" Embed websockify into Nginx (convert any tcp connection into websocket)
" https://github.com/tg123/websockify-nginx-module
syn keyword ngxDirectiveThirdParty contained websockify_buffer_size
syn keyword ngxDirectiveThirdParty contained websockify_connect_timeout
syn keyword ngxDirectiveThirdParty contained websockify_pass
syn keyword ngxDirectiveThirdParty contained websockify_read_timeout
syn keyword ngxDirectiveThirdParty contained websockify_send_timeout
" IP2Location Nginx
" https://github.com/ip2location/ip2location-nginx
syn keyword ngxDirectiveThirdParty contained ip2location_proxy
syn keyword ngxDirectiveThirdParty contained ip2location_proxy_recursive
syn keyword ngxDirectiveThirdParty contained ip2location_areacode
syn keyword ngxDirectiveThirdParty contained ip2location_city
syn keyword ngxDirectiveThirdParty contained ip2location_country_long
syn keyword ngxDirectiveThirdParty contained ip2location_country_short
syn keyword ngxDirectiveThirdParty contained ip2location_domain
syn keyword ngxDirectiveThirdParty contained ip2location_elevation
syn keyword ngxDirectiveThirdParty contained ip2location_iddcode
syn keyword ngxDirectiveThirdParty contained ip2location_isp
syn keyword ngxDirectiveThirdParty contained ip2location_latitude
syn keyword ngxDirectiveThirdParty contained ip2location_longitude
syn keyword ngxDirectiveThirdParty contained ip2location_mcc
syn keyword ngxDirectiveThirdParty contained ip2location_mnc
syn keyword ngxDirectiveThirdParty contained ip2location_mobilebrand
syn keyword ngxDirectiveThirdParty contained ip2location_netspeed
syn keyword ngxDirectiveThirdParty contained ip2location_region
syn keyword ngxDirectiveThirdParty contained ip2location_timezone
syn keyword ngxDirectiveThirdParty contained ip2location_usagetype
syn keyword ngxDirectiveThirdParty contained ip2location_weatherstationcode
syn keyword ngxDirectiveThirdParty contained ip2location_weatherstationname
syn keyword ngxDirectiveThirdParty contained ip2location_zipcode
" IP2Proxy module for Nginx
" https://github.com/ip2location/ip2proxy-nginx
syn keyword ngxDirectiveThirdParty contained ip2proxy_as
syn keyword ngxDirectiveThirdParty contained ip2proxy_asn
syn keyword ngxDirectiveThirdParty contained ip2proxy_city
syn keyword ngxDirectiveThirdParty contained ip2proxy_country_long
syn keyword ngxDirectiveThirdParty contained ip2proxy_country_short
syn keyword ngxDirectiveThirdParty contained ip2proxy_database
syn keyword ngxDirectiveThirdParty contained ip2proxy_domain
syn keyword ngxDirectiveThirdParty contained ip2proxy_isp
syn keyword ngxDirectiveThirdParty contained ip2proxy_is_proxy
syn keyword ngxDirectiveThirdParty contained ip2proxy_last_seen
syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy
syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_recursive
syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_type
syn keyword ngxDirectiveThirdParty contained ip2proxy_region
syn keyword ngxDirectiveThirdParty contained ip2proxy_threat
syn keyword ngxDirectiveThirdParty contained ip2proxy_usage_type
" highlight
hi link ngxComment Comment
hi link ngxParamComment Comment
hi link ngxListenComment Comment
hi link ngxVariable Identifier
hi link ngxVariableString PreProc
hi link ngxString String
hi link ngxListenString String
hi def link ngxComment Comment
hi def link ngxParamComment Comment
hi def link ngxListenComment Comment
hi def link ngxVariable Identifier
hi def link ngxVariableString PreProc
hi def link ngxString String
hi def link ngxListenString String
hi link ngxBoolean Boolean
hi link ngxDirectiveBlock Statement
hi link ngxDirectiveImportant Type
hi link ngxDirectiveListen Type
hi link ngxDirectiveControl Keyword
hi link ngxDirectiveError Constant
hi link ngxDirectiveDeprecated Error
hi link ngxDirective Identifier
hi link ngxDirectiveThirdParty Special
hi link ngxDirectiveThirdPartyDeprecated Error
hi def link ngxBoolean Boolean
hi def link ngxDirectiveBlock Statement
hi def link ngxDirectiveImportant Type
hi def link ngxDirectiveListen Type
hi def link ngxDirectiveControl Keyword
hi def link ngxDirectiveError Constant
hi def link ngxDirectiveDeprecated Error
hi def link ngxDirective Identifier
hi def link ngxDirectiveThirdParty Special
hi def link ngxDirectiveThirdPartyDeprecated Error
hi link ngxListenOptions Keyword
hi link ngxListenOptionsDeprecated Error
hi def link ngxListenOptions Keyword
hi def link ngxListenOptionsDeprecated Error
let b:current_syntax = "nginx"

View file

@ -25,7 +25,7 @@
.\" SUCH DAMAGE.
.\"
.\"
.Dd December 5, 2019
.Dd November 5, 2020
.Dt NGINX 8
.Os
.Sh NAME
@ -35,6 +35,7 @@
.Nm
.Op Fl ?hqTtVv
.Op Fl c Ar file
.Op Fl e Ar file
.Op Fl g Ar directives
.Op Fl p Ar prefix
.Op Fl s Ar signal
@ -54,6 +55,12 @@ Print help.
.It Fl c Ar file
Use an alternative configuration
.Ar file .
.It Fl e Ar file
Use an alternative error log
.Ar file .
Special value
.Cm stderr
indicates that the standard error output should be used.
.It Fl g Ar directives
Set global configuration directives.
See
@ -198,10 +205,10 @@ Development of
started in 2002, with the first public release on October 4, 2004.
.Sh AUTHORS
.An -nosplit
.An Igor Sysoev Aq igor@sysoev.ru .
.An Igor Sysoev Aq Mt igor@sysoev.ru .
.Pp
This manual page was originally written by
.An Sergey A. Osokin Aq osa@FreeBSD.org.ru
.An Sergey A. Osokin Aq Mt osa@FreeBSD.org.ru
as a result of compiling many
.Nm
documents from all over the world.

View file

@ -183,6 +183,7 @@ static ngx_uint_t ngx_show_help;
static ngx_uint_t ngx_show_version;
static ngx_uint_t ngx_show_configure;
static u_char *ngx_prefix;
static u_char *ngx_error_log;
static u_char *ngx_conf_file;
static u_char *ngx_conf_params;
static char *ngx_signal;
@ -230,7 +231,7 @@ main(int argc, char *const *argv)
ngx_pid = ngx_getpid();
ngx_parent = ngx_getppid();
log = ngx_log_init(ngx_prefix);
log = ngx_log_init(ngx_prefix, ngx_error_log);
if (log == NULL) {
return 1;
}
@ -393,9 +394,9 @@ ngx_show_version_info(void)
if (ngx_show_help) {
ngx_write_stderr(
"Usage: nginx [-?hvVtTq] [-s signal] [-c filename] "
"[-p prefix] [-g directives]" NGX_LINEFEED
NGX_LINEFEED
"Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]" NGX_LINEFEED
" [-e filename] [-c filename] [-g directives]"
NGX_LINEFEED NGX_LINEFEED
"Options:" NGX_LINEFEED
" -?,-h : this help" NGX_LINEFEED
" -v : show version and exit" NGX_LINEFEED
@ -413,6 +414,12 @@ ngx_show_version_info(void)
NGX_LINEFEED
#else
" -p prefix : set prefix path (default: NONE)" NGX_LINEFEED
#endif
" -e filename : set error log file (default: "
#ifdef NGX_ERROR_LOG_STDERR
"stderr)" NGX_LINEFEED
#else
NGX_ERROR_LOG_PATH ")" NGX_LINEFEED
#endif
" -c filename : set configuration file (default: " NGX_CONF_PATH
")" NGX_LINEFEED
@ -492,6 +499,7 @@ ngx_add_inherited_sockets(ngx_cycle_t *cycle)
ngx_memzero(ls, sizeof(ngx_listening_t));
ls->fd = (ngx_socket_t) s;
ls->inherited = 1;
}
}
@ -799,6 +807,24 @@ ngx_get_options(int argc, char *const *argv)
ngx_log_stderr(0, "option \"-p\" requires directory name");
return NGX_ERROR;
case 'e':
if (*p) {
ngx_error_log = p;
} else if (argv[++i]) {
ngx_error_log = (u_char *) argv[i];
} else {
ngx_log_stderr(0, "option \"-e\" requires file name");
return NGX_ERROR;
}
if (ngx_strcmp(ngx_error_log, "stderr") == 0) {
ngx_error_log = (u_char *) "";
}
goto next;
case 'c':
if (*p) {
ngx_conf_file = p;
@ -991,6 +1017,14 @@ ngx_process_options(ngx_cycle_t *cycle)
}
}
if (ngx_error_log) {
cycle->error_log.len = ngx_strlen(ngx_error_log);
cycle->error_log.data = ngx_error_log;
} else {
ngx_str_set(&cycle->error_log, NGX_ERROR_LOG_PATH);
}
if (ngx_conf_params) {
cycle->conf_param.len = ngx_strlen(ngx_conf_params);
cycle->conf_param.data = ngx_conf_params;

View file

@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
#define nginx_version 1018000
#define NGINX_VERSION "1.18.0"
#define nginx_version 1020002
#define NGINX_VERSION "1.20.2"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD

View file

@ -203,16 +203,16 @@ ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy,
while (*busy) {
cl = *busy;
if (ngx_buf_size(cl->buf) != 0) {
break;
}
if (cl->buf->tag != tag) {
*busy = cl->next;
ngx_free_chain(p, cl);
continue;
}
if (ngx_buf_size(cl->buf) != 0) {
break;
}
cl->buf->pos = cl->buf->start;
cl->buf->last = cl->buf->start;

View file

@ -125,20 +125,20 @@ typedef struct {
#define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR
#define ngx_buf_in_memory(b) (b->temporary || b->memory || b->mmap)
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !b->in_file)
#define ngx_buf_in_memory(b) ((b)->temporary || (b)->memory || (b)->mmap)
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !(b)->in_file)
#define ngx_buf_special(b) \
((b->flush || b->last_buf || b->sync) \
&& !ngx_buf_in_memory(b) && !b->in_file)
(((b)->flush || (b)->last_buf || (b)->sync) \
&& !ngx_buf_in_memory(b) && !(b)->in_file)
#define ngx_buf_sync_only(b) \
(b->sync \
&& !ngx_buf_in_memory(b) && !b->in_file && !b->flush && !b->last_buf)
((b)->sync && !ngx_buf_in_memory(b) \
&& !(b)->in_file && !(b)->flush && !(b)->last_buf)
#define ngx_buf_size(b) \
(ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \
(b->file_last - b->file_pos))
(ngx_buf_in_memory(b) ? (off_t) ((b)->last - (b)->pos): \
((b)->file_last - (b)->file_pos))
ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);
ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
@ -149,8 +149,8 @@ ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool);
#define ngx_free_chain(pool, cl) \
cl->next = pool->chain; \
pool->chain = cl
(cl)->next = (pool)->chain; \
(pool)->chain = (cl)

View file

@ -1137,7 +1137,7 @@ ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
a = (ngx_array_t **) (p + cmd->offset);
if (*a == NULL) {
if (*a == NGX_CONF_UNSET_PTR || *a == NULL) {
*a = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t));
if (*a == NULL) {
return NGX_CONF_ERROR;

View file

@ -1070,7 +1070,8 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
if (ls[i].sockaddr->sa_family == AF_UNIX
&& ngx_process <= NGX_PROCESS_MASTER
&& ngx_new_binary == 0)
&& ngx_new_binary == 0
&& (!ls[i].inherited || ngx_getppid() != ngx_parent))
{
u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
@ -1106,12 +1107,9 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
return NULL;
}
c = ngx_cycle->free_connections;
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
if (c == NULL) {
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
c = ngx_cycle->free_connections;
}
c = ngx_cycle->free_connections;
if (c == NULL) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
@ -1297,6 +1295,22 @@ ngx_drain_connections(ngx_cycle_t *cycle)
ngx_queue_t *q;
ngx_connection_t *c;
if (cycle->free_connection_n > cycle->connection_n / 16
|| cycle->reusable_connections_n == 0)
{
return;
}
if (cycle->connections_reuse_time != ngx_time()) {
cycle->connections_reuse_time = ngx_time();
ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"%ui worker_connections are not enough, "
"reusing connections",
cycle->connection_n);
}
c = NULL;
n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);
for (i = 0; i < n; i++) {
@ -1313,6 +1327,21 @@ ngx_drain_connections(ngx_cycle_t *cycle)
c->close = 1;
c->read->handler(c->read);
}
if (cycle->free_connection_n == 0 && c && c->reusable) {
/*
* if no connections were freed, try to reuse the last
* connection again: this should free it as long as
* previous reuse moved it to lingering close
*/
ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
"reusing connection again");
c->close = 1;
c->read->handler(c->read);
}
}

View file

@ -45,8 +45,6 @@ struct ngx_listening_s {
size_t pool_size;
/* should be here because of the AcceptEx() preread */
size_t post_accept_buffer_size;
/* should be here because of the deferred accept */
ngx_msec_t post_accept_timeout;
ngx_listening_t *previous;
ngx_connection_t *connection;
@ -164,6 +162,7 @@ struct ngx_connection_s {
ngx_atomic_uint_t number;
ngx_msec_t start_time;
ngx_uint_t requests;
unsigned buffered:8;

View file

@ -96,6 +96,15 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
return NULL;
}
cycle->error_log.len = old_cycle->error_log.len;
cycle->error_log.data = ngx_pnalloc(pool, old_cycle->error_log.len + 1);
if (cycle->error_log.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
ngx_cpystrn(cycle->error_log.data, old_cycle->error_log.data,
old_cycle->error_log.len + 1);
cycle->conf_file.len = old_cycle->conf_file.len;
cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
if (cycle->conf_file.data == NULL) {
@ -520,6 +529,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
== NGX_OK)
{
nls[n].fd = ls[i].fd;
nls[n].inherited = ls[i].inherited;
nls[n].previous = &ls[i];
ls[i].remain = 1;
@ -1008,6 +1018,7 @@ ngx_int_t
ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
{
size_t len;
ngx_int_t rc;
ngx_uint_t create;
ngx_file_t file;
u_char pid[NGX_INT64_LEN + 2];
@ -1032,11 +1043,13 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
return NGX_ERROR;
}
rc = NGX_OK;
if (!ngx_test_config) {
len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;
if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
return NGX_ERROR;
rc = NGX_ERROR;
}
}
@ -1045,7 +1058,7 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
ngx_close_file_n " \"%s\" failed", file.name.data);
}
return NGX_OK;
return rc;
}

View file

@ -55,6 +55,7 @@ struct ngx_cycle_s {
ngx_queue_t reusable_connections_queue;
ngx_uint_t reusable_connections_n;
time_t connections_reuse_time;
ngx_array_t listening;
ngx_array_t paths;
@ -79,6 +80,7 @@ struct ngx_cycle_s {
ngx_str_t conf_param;
ngx_str_t conf_prefix;
ngx_str_t prefix;
ngx_str_t error_log;
ngx_str_t lock_file;
ngx_str_t hostname;
};

View file

@ -315,7 +315,7 @@ ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err)
ngx_log_t *
ngx_log_init(u_char *prefix)
ngx_log_init(u_char *prefix, u_char *error_log)
{
u_char *p, *name;
size_t nlen, plen;
@ -323,13 +323,11 @@ ngx_log_init(u_char *prefix)
ngx_log.file = &ngx_log_file;
ngx_log.log_level = NGX_LOG_NOTICE;
name = (u_char *) NGX_ERROR_LOG_PATH;
/*
* we use ngx_strlen() here since BCC warns about
* condition is always false and unreachable code
*/
if (error_log == NULL) {
error_log = (u_char *) NGX_ERROR_LOG_PATH;
}
name = error_log;
nlen = ngx_strlen(name);
if (nlen == 0) {
@ -369,7 +367,7 @@ ngx_log_init(u_char *prefix)
*p++ = '/';
}
ngx_cpystrn(p, (u_char *) NGX_ERROR_LOG_PATH, nlen + 1);
ngx_cpystrn(p, error_log, nlen + 1);
p = name;
}
@ -403,8 +401,7 @@ ngx_log_init(u_char *prefix)
ngx_int_t
ngx_log_open_default(ngx_cycle_t *cycle)
{
ngx_log_t *log;
static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH);
ngx_log_t *log;
if (ngx_log_get_file_log(&cycle->new_log) != NULL) {
return NGX_OK;
@ -425,7 +422,7 @@ ngx_log_open_default(ngx_cycle_t *cycle)
log->log_level = NGX_LOG_ERR;
log->file = ngx_conf_open_file(cycle, &error_log);
log->file = ngx_conf_open_file(cycle, &cycle->error_log);
if (log->file == NULL) {
return NGX_ERROR;
}

View file

@ -228,7 +228,7 @@ void ngx_cdecl ngx_log_debug_core(ngx_log_t *log, ngx_err_t err,
/*********************************/
ngx_log_t *ngx_log_init(u_char *prefix);
ngx_log_t *ngx_log_init(u_char *prefix, u_char *error_log);
void ngx_cdecl ngx_log_abort(ngx_err_t err, const char *fmt, ...);
void ngx_cdecl ngx_log_stderr(ngx_err_t err, const char *fmt, ...);
u_char *ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err);

View file

@ -1563,13 +1563,28 @@ ngx_resolver_udp_read(ngx_event_t *rev)
do {
n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE);
if (n < 0) {
return;
if (n == NGX_AGAIN) {
break;
}
if (n == NGX_ERROR) {
goto failed;
}
ngx_resolver_process_response(rec->resolver, buf, n, 0);
} while (rev->ready);
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
goto failed;
}
return;
failed:
ngx_close_connection(rec->udp);
rec->udp = NULL;
}
@ -1783,6 +1798,12 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n,
i = sizeof(ngx_resolver_hdr_t);
while (i < (ngx_uint_t) n) {
if (buf[i] & 0xc0) {
err = "unexpected compression pointer in DNS response";
goto done;
}
if (buf[i] == '\0') {
goto found;
}
@ -1918,7 +1939,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
if (rn == NULL) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected response for %V", &name);
"unexpected DNS response for %V", &name);
ngx_resolver_free(r, name.data);
goto failed;
}
@ -1930,7 +1951,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
if (rn->query6 == NULL || rn->naddrs6 != (u_short) -1) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected response for %V", &name);
"unexpected DNS response for %V", &name);
ngx_resolver_free(r, name.data);
goto failed;
}
@ -1949,7 +1970,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
if (rn->query == NULL || rn->naddrs != (u_short) -1) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected response for %V", &name);
"unexpected DNS response for %V", &name);
ngx_resolver_free(r, name.data);
goto failed;
}
@ -1964,7 +1985,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
if (ident != qident) {
ngx_log_error(r->log_level, r->log, 0,
"wrong ident %ui response for %V, expect %ui",
"wrong ident %ui in DNS response for %V, expect %ui",
ident, &name, qident);
ngx_resolver_free(r, name.data);
goto failed;
@ -2149,7 +2170,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
if (class != 1) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected RR class %ui", class);
"unexpected RR class %ui in DNS response", class);
goto failed;
}
@ -2218,7 +2239,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
default:
ngx_log_error(r->log_level, r->log, 0,
"unexpected RR type %ui", type);
"unexpected RR type %ui in DNS response", type);
}
i += len;
@ -2567,7 +2588,7 @@ ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
if (rn == NULL || rn->query == NULL) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected response for %V", &name);
"unexpected DNS response for %V", &name);
ngx_resolver_free(r, name.data);
goto failed;
}
@ -2581,7 +2602,7 @@ ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
if (ident != qident) {
ngx_log_error(r->log_level, r->log, 0,
"wrong ident %ui response for %V, expect %ui",
"wrong ident %ui in DNS response for %V, expect %ui",
ident, &name, qident);
ngx_resolver_free(r, name.data);
goto failed;
@ -2691,7 +2712,7 @@ ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
if (class != 1) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected RR class %ui", class);
"unexpected RR class %ui in DNS response", class);
goto failed;
}
@ -2734,7 +2755,7 @@ ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
default:
ngx_log_error(r->log_level, r->log, 0,
"unexpected RR type %ui", type);
"unexpected RR type %ui in DNS response", type);
}
i += len;
@ -3165,7 +3186,7 @@ valid:
if (rn == NULL || rn->query == NULL) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected response for %V", &name);
"unexpected DNS response for %V", &name);
ngx_resolver_free(r, name.data);
goto failed;
}
@ -3174,7 +3195,7 @@ valid:
if (ident != qident) {
ngx_log_error(r->log_level, r->log, 0,
"wrong ident %ui response for %V, expect %ui",
"wrong ident %ui in DNS response for %V, expect %ui",
ident, &name, qident);
ngx_resolver_free(r, name.data);
goto failed;
@ -3256,7 +3277,7 @@ valid:
if (class != 1) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected RR class %ui", class);
"unexpected RR class %ui in DNS response", class);
goto failed;
}
@ -3283,7 +3304,7 @@ valid:
default:
ngx_log_error(r->log_level, r->log, 0,
"unexpected RR type %ui", type);
"unexpected RR type %ui in DNS response", type);
}
i += len;
@ -3924,11 +3945,11 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src,
{
char *err;
u_char *p, *dst;
ssize_t len;
size_t len;
ngx_uint_t i, n;
p = src;
len = -1;
len = 0;
/*
* compression pointers allow to create endless loop, so we set limit;
@ -3943,6 +3964,16 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src,
}
if (n & 0xc0) {
if ((n & 0xc0) != 0xc0) {
err = "invalid label type in DNS response";
goto invalid;
}
if (p >= last) {
err = "name is out of DNS response";
goto invalid;
}
n = ((n & 0x3f) << 8) + *p;
p = &buf[n];
@ -3952,12 +3983,12 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src,
}
if (p >= last) {
err = "name is out of response";
err = "name is out of DNS response";
goto invalid;
}
}
err = "compression pointers loop";
err = "compression pointers loop in DNS response";
invalid:
@ -3971,7 +4002,7 @@ done:
return NGX_OK;
}
if (len == -1) {
if (len == 0) {
ngx_str_null(name);
return NGX_OK;
}
@ -3983,30 +4014,23 @@ done:
name->data = dst;
n = *src++;
for ( ;; ) {
n = *src++;
if (n == 0) {
name->len = dst - name->data - 1;
return NGX_OK;
}
if (n & 0xc0) {
n = ((n & 0x3f) << 8) + *src;
src = &buf[n];
n = *src++;
} else {
ngx_strlow(dst, src, n);
dst += n;
src += n;
n = *src++;
if (n != 0) {
*dst++ = '.';
}
}
if (n == 0) {
name->len = dst - name->data;
return NGX_OK;
*dst++ = '.';
}
}
}
@ -4444,6 +4468,8 @@ ngx_udp_connect(ngx_resolver_connection_t *rec)
c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
c->start_time = ngx_current_msec;
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0,
"connect to %V, fd:%d #%uA", &rec->server, s, c->number);
@ -4530,6 +4556,8 @@ ngx_tcp_connect(ngx_resolver_connection_t *rec)
c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
c->start_time = ngx_current_msec;
if (ngx_add_conn) {
if (ngx_add_conn(c) == NGX_ERROR) {
goto failed;

View file

@ -11,6 +11,8 @@
static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64,
u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width);
static u_char *ngx_sprintf_str(u_char *buf, u_char *last, u_char *src,
size_t len, ngx_uint_t hexadecimal);
static void ngx_encode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
const u_char *basis, ngx_uint_t padding);
static ngx_int_t ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
@ -101,10 +103,10 @@ ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src)
* %M ngx_msec_t
* %r rlim_t
* %p void *
* %V ngx_str_t *
* %v ngx_variable_value_t *
* %s null-terminated string
* %*s length and string
* %[x|X]V ngx_str_t *
* %[x|X]v ngx_variable_value_t *
* %[x|X]s null-terminated string
* %*[x|X]s length and string
* %Z '\0'
* %N '\n'
* %c char
@ -165,7 +167,7 @@ ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args)
u_char *p, zero;
int d;
double f;
size_t len, slen;
size_t slen;
int64_t i64;
uint64_t ui64, frac;
ngx_msec_t ms;
@ -250,8 +252,7 @@ ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args)
case 'V':
v = va_arg(args, ngx_str_t *);
len = ngx_min(((size_t) (last - buf)), v->len);
buf = ngx_cpymem(buf, v->data, len);
buf = ngx_sprintf_str(buf, last, v->data, v->len, hex);
fmt++;
continue;
@ -259,8 +260,7 @@ ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args)
case 'v':
vv = va_arg(args, ngx_variable_value_t *);
len = ngx_min(((size_t) (last - buf)), vv->len);
buf = ngx_cpymem(buf, vv->data, len);
buf = ngx_sprintf_str(buf, last, vv->data, vv->len, hex);
fmt++;
continue;
@ -268,16 +268,7 @@ ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args)
case 's':
p = va_arg(args, u_char *);
if (slen == (size_t) -1) {
while (*p && buf < last) {
*buf++ = *p++;
}
} else {
len = ngx_min(((size_t) (last - buf)), slen);
buf = ngx_cpymem(buf, p, len);
}
buf = ngx_sprintf_str(buf, last, p, slen, hex);
fmt++;
continue;
@ -576,6 +567,64 @@ ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero,
}
static u_char *
ngx_sprintf_str(u_char *buf, u_char *last, u_char *src, size_t len,
ngx_uint_t hexadecimal)
{
static u_char hex[] = "0123456789abcdef";
static u_char HEX[] = "0123456789ABCDEF";
if (hexadecimal == 0) {
if (len == (size_t) -1) {
while (*src && buf < last) {
*buf++ = *src++;
}
} else {
len = ngx_min((size_t) (last - buf), len);
buf = ngx_cpymem(buf, src, len);
}
} else if (hexadecimal == 1) {
if (len == (size_t) -1) {
while (*src && buf < last - 1) {
*buf++ = hex[*src >> 4];
*buf++ = hex[*src++ & 0xf];
}
} else {
while (len-- && buf < last - 1) {
*buf++ = hex[*src >> 4];
*buf++ = hex[*src++ & 0xf];
}
}
} else { /* hexadecimal == 2 */
if (len == (size_t) -1) {
while (*src && buf < last - 1) {
*buf++ = HEX[*src >> 4];
*buf++ = HEX[*src++ & 0xf];
}
} else {
while (len-- && buf < last - 1) {
*buf++ = HEX[*src >> 4];
*buf++ = HEX[*src++ & 0xf];
}
}
}
return buf;
}
/*
* We use ngx_strcasecmp()/ngx_strncasecmp() for 7-bit ASCII strings only,
* and implement our own ngx_strcasecmp()/ngx_strncasecmp()

View file

@ -399,7 +399,7 @@ ngx_eventport_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
return NGX_ERROR;
}
} else {
} else if (ev->active) {
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"eventport del event: fd:%d", c->fd);

View file

@ -257,9 +257,7 @@ ngx_process_events_and_timers(ngx_cycle_t *cycle)
ngx_shmtx_unlock(&ngx_accept_mutex);
}
if (delta) {
ngx_event_expire_timers();
}
ngx_event_expire_timers();
ngx_event_process_posted(cycle, &ngx_posted_events);
}
@ -318,7 +316,7 @@ ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)
return NGX_OK;
}
if (rev->oneshot && !rev->ready) {
if (rev->oneshot && rev->ready) {
if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
return NGX_ERROR;
}

View file

@ -256,6 +256,8 @@ ngx_event_accept(ngx_event_t *ev)
c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
c->start_time = ngx_current_msec;
#if (NGX_STAT_STUB)
(void) ngx_atomic_fetch_add(ngx_stat_handled, 1);
#endif

View file

@ -193,6 +193,8 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
c->start_time = ngx_current_msec;
if (ngx_add_conn) {
if (ngx_add_conn(c) == NGX_ERROR) {
goto failed;

View file

@ -83,7 +83,7 @@ static time_t ngx_ssl_parse_time(
#if OPENSSL_VERSION_NUMBER > 0x10100000L
const
#endif
ASN1_TIME *asn1time);
ASN1_TIME *asn1time, ngx_log_t *log);
static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
@ -130,6 +130,7 @@ int ngx_ssl_connection_index;
int ngx_ssl_server_conf_index;
int ngx_ssl_session_cache_index;
int ngx_ssl_session_ticket_keys_index;
int ngx_ssl_ocsp_index;
int ngx_ssl_certificate_index;
int ngx_ssl_next_certificate_index;
int ngx_ssl_certificate_name_index;
@ -213,6 +214,13 @@ ngx_ssl_init(ngx_log_t *log)
return NGX_ERROR;
}
ngx_ssl_ocsp_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
if (ngx_ssl_ocsp_index == -1) {
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
"SSL_CTX_get_ex_new_index() failed");
return NGX_ERROR;
}
ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
NULL);
if (ngx_ssl_certificate_index == -1) {
@ -370,6 +378,10 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_CLIENT_RENEGOTIATION);
#endif
#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
SSL_CTX_set_options(ssl->ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
@ -912,6 +924,9 @@ ngx_int_t
ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
ngx_int_t depth)
{
SSL_CTX_set_verify(ssl->ctx, SSL_CTX_get_verify_mode(ssl->ctx),
ngx_ssl_verify_callback);
SSL_CTX_set_verify_depth(ssl->ctx, depth);
if (cert->len == 0) {
@ -1003,26 +1018,52 @@ ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
c = ngx_ssl_get_connection(ssl_conn);
if (!(c->log->log_level & NGX_LOG_DEBUG_EVENT)) {
return 1;
}
cert = X509_STORE_CTX_get_current_cert(x509_store);
err = X509_STORE_CTX_get_error(x509_store);
depth = X509_STORE_CTX_get_error_depth(x509_store);
sname = X509_get_subject_name(cert);
subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)";
if (sname) {
subject = X509_NAME_oneline(sname, NULL, 0);
if (subject == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
"X509_NAME_oneline() failed");
}
} else {
subject = NULL;
}
iname = X509_get_issuer_name(cert);
issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)";
if (iname) {
issuer = X509_NAME_oneline(iname, NULL, 0);
if (issuer == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
"X509_NAME_oneline() failed");
}
} else {
issuer = NULL;
}
ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
"verify:%d, error:%d, depth:%d, "
"subject:\"%s\", issuer:\"%s\"",
ok, err, depth, subject, issuer);
ok, err, depth,
subject ? subject : "(none)",
issuer ? issuer : "(none)");
if (sname) {
if (subject) {
OPENSSL_free(subject);
}
if (iname) {
if (issuer) {
OPENSSL_free(issuer);
}
#endif
@ -1079,6 +1120,8 @@ ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
}
#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)
RSA *
ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
int key_length)
@ -1089,7 +1132,7 @@ ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
return NULL;
}
#if (OPENSSL_VERSION_NUMBER < 0x10100003L && !defined OPENSSL_NO_DEPRECATED)
#ifndef OPENSSL_NO_DEPRECATED
if (key == NULL) {
key = RSA_generate_key(512, RSA_F4, NULL, NULL);
@ -1100,6 +1143,8 @@ ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
return key;
}
#endif
ngx_array_t *
ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file)
@ -1313,7 +1358,6 @@ ngx_ssl_passwords_cleanup(void *data)
ngx_int_t
ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
{
DH *dh;
BIO *bio;
if (file->len == 0) {
@ -1331,6 +1375,10 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
return NGX_ERROR;
}
#ifdef SSL_CTX_set_tmp_dh
{
DH *dh;
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
if (dh == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
@ -1339,9 +1387,42 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
return NGX_ERROR;
}
SSL_CTX_set_tmp_dh(ssl->ctx, dh);
if (SSL_CTX_set_tmp_dh(ssl->ctx, dh) != 1) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_set_tmp_dh(\"%s\") failed", file->data);
DH_free(dh);
BIO_free(bio);
return NGX_ERROR;
}
DH_free(dh);
}
#else
{
EVP_PKEY *dh;
/*
* PEM_read_bio_DHparams() and SSL_CTX_set_tmp_dh()
* are deprecated in OpenSSL 3.0
*/
dh = PEM_read_bio_Parameters(bio, NULL);
if (dh == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"PEM_read_bio_Parameters(\"%s\") failed", file->data);
BIO_free(bio);
return NGX_ERROR;
}
if (SSL_CTX_set0_tmp_dh_pkey(ssl->ctx, dh) != 1) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_set0_tmp_dh_pkey(\%s\") failed", file->data);
BIO_free(bio);
return NGX_ERROR;
}
}
#endif
BIO_free(bio);
return NGX_OK;
@ -1459,6 +1540,78 @@ ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable)
}
ngx_int_t
ngx_ssl_conf_commands(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *commands)
{
if (commands == NULL) {
return NGX_OK;
}
#ifdef SSL_CONF_FLAG_FILE
{
int type;
u_char *key, *value;
ngx_uint_t i;
ngx_keyval_t *cmd;
SSL_CONF_CTX *cctx;
cctx = SSL_CONF_CTX_new();
if (cctx == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CONF_CTX_new() failed");
return NGX_ERROR;
}
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS);
SSL_CONF_CTX_set_ssl_ctx(cctx, ssl->ctx);
cmd = commands->elts;
for (i = 0; i < commands->nelts; i++) {
key = cmd[i].key.data;
type = SSL_CONF_cmd_value_type(cctx, (char *) key);
if (type == SSL_CONF_TYPE_FILE || type == SSL_CONF_TYPE_DIR) {
if (ngx_conf_full_name(cf->cycle, &cmd[i].value, 1) != NGX_OK) {
SSL_CONF_CTX_free(cctx);
return NGX_ERROR;
}
}
value = cmd[i].value.data;
if (SSL_CONF_cmd(cctx, (char *) key, (char *) value) <= 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CONF_cmd(\"%s\", \"%s\") failed", key, value);
SSL_CONF_CTX_free(cctx);
return NGX_ERROR;
}
}
if (SSL_CONF_CTX_finish(cctx) != 1) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CONF_finish() failed");
SSL_CONF_CTX_free(cctx);
return NGX_ERROR;
}
SSL_CONF_CTX_free(cctx);
return NGX_OK;
}
#else
ngx_log_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CONF_cmd() is not available on this platform");
return NGX_ERROR;
#endif
}
ngx_int_t
ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable)
{
@ -1594,6 +1747,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
{
int n, sslerr;
ngx_err_t err;
ngx_int_t rc;
#ifdef SSL_READ_EARLY_DATA_SUCCESS
if (c->ssl->try_early_data) {
@ -1601,6 +1755,10 @@ ngx_ssl_handshake(ngx_connection_t *c)
}
#endif
if (c->ssl->in_ocsp) {
return ngx_ssl_ocsp_validate(c);
}
ngx_ssl_clear_error(c->log);
n = SSL_do_handshake(c->ssl->connection);
@ -1621,13 +1779,14 @@ ngx_ssl_handshake(ngx_connection_t *c)
ngx_ssl_handshake_log(c);
#endif
c->ssl->handshaked = 1;
c->recv = ngx_ssl_recv;
c->send = ngx_ssl_write;
c->recv_chain = ngx_ssl_recv_chain;
c->send_chain = ngx_ssl_send_chain;
c->read->ready = 1;
c->write->ready = 1;
#ifndef SSL_OP_NO_RENEGOTIATION
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
@ -1641,6 +1800,20 @@ ngx_ssl_handshake(ngx_connection_t *c)
#endif
#endif
rc = ngx_ssl_ocsp_validate(c);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
if (rc == NGX_AGAIN) {
c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;
return NGX_AGAIN;
}
c->ssl->handshaked = 1;
return NGX_OK;
}
@ -1693,6 +1866,13 @@ ngx_ssl_handshake(ngx_connection_t *c)
return NGX_ERROR;
}
if (c->ssl->handshake_rejected) {
ngx_connection_error(c, err, "handshake rejected");
ERR_clear_error();
return NGX_ERROR;
}
c->read->error = 1;
ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
@ -1710,6 +1890,7 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
u_char buf;
size_t readbytes;
ngx_err_t err;
ngx_int_t rc;
ngx_ssl_clear_error(c->log);
@ -1744,7 +1925,6 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
c->ssl->early_buf = buf;
c->ssl->early_preread = 1;
c->ssl->handshaked = 1;
c->ssl->in_early = 1;
c->recv = ngx_ssl_recv;
@ -1752,6 +1932,23 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
c->recv_chain = ngx_ssl_recv_chain;
c->send_chain = ngx_ssl_send_chain;
c->read->ready = 1;
c->write->ready = 1;
rc = ngx_ssl_ocsp_validate(c);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
if (rc == NGX_AGAIN) {
c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;
return NGX_AGAIN;
}
c->ssl->handshaked = 1;
return NGX_OK;
}
@ -1827,6 +2024,10 @@ ngx_ssl_handshake_log(ngx_connection_t *c)
#endif
SSL_CIPHER *cipher;
if (!(c->log->log_level & NGX_LOG_DEBUG_EVENT)) {
return;
}
cipher = SSL_get_current_cipher(c->ssl->connection);
if (cipher) {
@ -2531,6 +2732,18 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
sslerr = SSL_get_error(c->ssl->connection, n);
if (sslerr == SSL_ERROR_ZERO_RETURN) {
/*
* OpenSSL 1.1.1 fails to return SSL_ERROR_SYSCALL if an error
* happens during SSL_write() after close_notify alert from the
* peer, and returns SSL_ERROR_ZERO_RETURN instead,
* https://git.openssl.org/?p=openssl.git;a=commitdiff;h=8051ab2
*/
sslerr = SSL_ERROR_SYSCALL;
}
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
@ -2732,8 +2945,14 @@ ngx_ssl_free_buffer(ngx_connection_t *c)
ngx_int_t
ngx_ssl_shutdown(ngx_connection_t *c)
{
int n, sslerr, mode;
ngx_err_t err;
int n, sslerr, mode;
ngx_int_t rc;
ngx_err_t err;
ngx_uint_t tries;
rc = NGX_OK;
ngx_ssl_ocsp_cleanup(c);
if (SSL_in_init(c->ssl->connection)) {
/*
@ -2742,13 +2961,10 @@ ngx_ssl_shutdown(ngx_connection_t *c)
* Avoid calling SSL_shutdown() if handshake wasn't completed.
*/
SSL_free(c->ssl->connection);
c->ssl = NULL;
return NGX_OK;
goto done;
}
if (c->timedout) {
if (c->timedout || c->error || c->buffered) {
mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
SSL_set_quiet_shutdown(c->ssl->connection, 1);
@ -2772,55 +2988,87 @@ ngx_ssl_shutdown(ngx_connection_t *c)
ngx_ssl_clear_error(c->log);
n = SSL_shutdown(c->ssl->connection);
tries = 2;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
for ( ;; ) {
sslerr = 0;
/*
* For bidirectional shutdown, SSL_shutdown() needs to be called
* twice: first call sends the "close notify" alert and returns 0,
* second call waits for the peer's "close notify" alert.
*/
/* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */
n = SSL_shutdown(c->ssl->connection);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
if (n == 1) {
goto done;
}
if (n == 0 && tries-- > 1) {
continue;
}
/* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */
if (n != 1 && ERR_peek_error()) {
sslerr = SSL_get_error(c->ssl->connection, n);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL_get_error: %d", sslerr);
}
if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
SSL_free(c->ssl->connection);
c->ssl = NULL;
if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
c->read->handler = ngx_ssl_shutdown_handler;
c->write->handler = ngx_ssl_shutdown_handler;
return NGX_OK;
}
if (sslerr == SSL_ERROR_WANT_READ) {
c->read->ready = 0;
if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
c->read->handler = ngx_ssl_shutdown_handler;
c->write->handler = ngx_ssl_shutdown_handler;
} else {
c->write->ready = 0;
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
goto failed;
}
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
goto failed;
}
ngx_add_timer(c->read, 3000);
return NGX_AGAIN;
}
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
goto done;
}
if (sslerr == SSL_ERROR_WANT_READ) {
ngx_add_timer(c->read, 30000);
}
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
return NGX_AGAIN;
ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
break;
}
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
failed:
ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
rc = NGX_ERROR;
done:
if (c->ssl->shutdown_without_free) {
c->ssl->shutdown_without_free = 0;
c->recv = ngx_recv;
return rc;
}
SSL_free(c->ssl->connection);
c->ssl = NULL;
c->recv = ngx_recv;
return NGX_ERROR;
return rc;
}
@ -3036,7 +3284,7 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
for ( ;; ) {
n = ERR_peek_error_line_data(NULL, NULL, &data, &flags);
n = ERR_peek_error_data(&data, &flags);
if (n == 0) {
break;
@ -3202,8 +3450,9 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
}
}
if (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index) == NULL) {
if (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index) == NULL
&& certificates != NULL)
{
/*
* If certificates are loaded dynamically, we use certificate
* names as specified in the configuration (with variables).
@ -3897,9 +4146,6 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
ngx_ssl_session_ticket_key_t *key;
const EVP_MD *digest;
const EVP_CIPHER *cipher;
#if (NGX_DEBUG)
u_char buf[32];
#endif
c = ngx_ssl_get_connection(ssl_conn);
ssl_ctx = c->ssl->session_ctx;
@ -3921,8 +4167,8 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
/* encrypt session ticket */
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl session ticket encrypt, key: \"%*s\" (%s session)",
ngx_hex_dump(buf, key[0].name, 16) - buf, buf,
"ssl session ticket encrypt, key: \"%*xs\" (%s session)",
(size_t) 16, key[0].name,
SSL_session_reused(ssl_conn) ? "reused" : "new");
if (key[0].size == 48) {
@ -3968,17 +4214,16 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
}
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl session ticket decrypt, key: \"%*s\" not found",
ngx_hex_dump(buf, name, 16) - buf, buf);
"ssl session ticket decrypt, key: \"%*xs\" not found",
(size_t) 16, name);
return 0;
found:
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl session ticket decrypt, key: \"%*s\"%s",
ngx_hex_dump(buf, key[i].name, 16) - buf, buf,
(i == 0) ? " (default)" : "");
"ssl session ticket decrypt, key: \"%*xs\"%s",
(size_t) 16, key[i].name, (i == 0) ? " (default)" : "");
if (key[i].size == 48) {
cipher = EVP_aes_128_cbc();
@ -4635,11 +4880,13 @@ ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
bio = BIO_new(BIO_s_mem());
if (bio == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
X509_free(cert);
return NGX_ERROR;
}
if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_print_ex() failed");
goto failed;
}
@ -4687,11 +4934,13 @@ ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
bio = BIO_new(BIO_s_mem());
if (bio == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
X509_free(cert);
return NGX_ERROR;
}
if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_print_ex() failed");
goto failed;
}
@ -4740,6 +4989,11 @@ ngx_ssl_get_subject_dn_legacy(ngx_connection_t *c, ngx_pool_t *pool,
}
p = X509_NAME_oneline(name, NULL, 0);
if (p == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_oneline() failed");
X509_free(cert);
return NGX_ERROR;
}
for (len = 0; p[len]; len++) { /* void */ }
@ -4783,6 +5037,11 @@ ngx_ssl_get_issuer_dn_legacy(ngx_connection_t *c, ngx_pool_t *pool,
}
p = X509_NAME_oneline(name, NULL, 0);
if (p == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_oneline() failed");
X509_free(cert);
return NGX_ERROR;
}
for (len = 0; p[len]; len++) { /* void */ }
@ -4819,6 +5078,7 @@ ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
bio = BIO_new(BIO_s_mem());
if (bio == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
X509_free(cert);
return NGX_ERROR;
}
@ -4857,6 +5117,7 @@ ngx_ssl_get_fingerprint(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
}
if (!X509_digest(cert, EVP_sha1(), buf, &len)) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_digest() failed");
X509_free(cert);
return NGX_ERROR;
}
@ -4894,11 +5155,14 @@ ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
rc = SSL_get_verify_result(c->ssl->connection);
if (rc == X509_V_OK) {
ngx_str_set(s, "SUCCESS");
return NGX_OK;
}
if (ngx_ssl_ocsp_get_status(c, &str) == NGX_OK) {
ngx_str_set(s, "SUCCESS");
return NGX_OK;
}
str = X509_verify_cert_error_string(rc);
} else {
str = X509_verify_cert_error_string(rc);
}
s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str));
if (s->data == NULL) {
@ -4927,6 +5191,7 @@ ngx_ssl_get_client_v_start(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
bio = BIO_new(BIO_s_mem());
if (bio == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
X509_free(cert);
return NGX_ERROR;
}
@ -4971,6 +5236,7 @@ ngx_ssl_get_client_v_end(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
bio = BIO_new(BIO_s_mem());
if (bio == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
X509_free(cert);
return NGX_ERROR;
}
@ -5013,9 +5279,9 @@ ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
}
#if OPENSSL_VERSION_NUMBER > 0x10100000L
end = ngx_ssl_parse_time(X509_get0_notAfter(cert));
end = ngx_ssl_parse_time(X509_get0_notAfter(cert), c->log);
#else
end = ngx_ssl_parse_time(X509_get_notAfter(cert));
end = ngx_ssl_parse_time(X509_get_notAfter(cert), c->log);
#endif
if (end == (time_t) NGX_ERROR) {
@ -5050,7 +5316,7 @@ ngx_ssl_parse_time(
#if OPENSSL_VERSION_NUMBER > 0x10100000L
const
#endif
ASN1_TIME *asn1time)
ASN1_TIME *asn1time, ngx_log_t *log)
{
BIO *bio;
char *value;
@ -5066,6 +5332,7 @@ ngx_ssl_parse_time(
bio = BIO_new(BIO_s_mem());
if (bio == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, log, 0, "BIO_new() failed");
return NGX_ERROR;
}

View file

@ -12,6 +12,8 @@
#include <ngx_config.h>
#include <ngx_core.h>
#define OPENSSL_SUPPRESS_DEPRECATED
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bn.h>
@ -64,6 +66,19 @@
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined SSL_get_peer_certificate)
#define SSL_get_peer_certificate(s) SSL_get1_peer_certificate(s)
#endif
#if (OPENSSL_VERSION_NUMBER < 0x30000000L && !defined ERR_peek_error_data)
#define ERR_peek_error_data(d, f) ERR_peek_error_line_data(NULL, NULL, d, f)
#endif
typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t;
struct ngx_ssl_s {
SSL_CTX *ctx;
ngx_log_t *log;
@ -87,16 +102,21 @@ struct ngx_ssl_connection_s {
ngx_event_handler_pt saved_read_handler;
ngx_event_handler_pt saved_write_handler;
ngx_ssl_ocsp_t *ocsp;
u_char early_buf;
unsigned handshaked:1;
unsigned handshake_rejected:1;
unsigned renegotiation:1;
unsigned buffer:1;
unsigned no_wait_shutdown:1;
unsigned no_send_shutdown:1;
unsigned shutdown_without_free:1;
unsigned handshake_buffer_set:1;
unsigned try_early_data:1;
unsigned in_early:1;
unsigned in_ocsp:1;
unsigned early_preread:1;
unsigned write_blocked:1;
};
@ -180,8 +200,18 @@ ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
ngx_int_t ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
ngx_uint_t depth, ngx_shm_zone_t *shm_zone);
ngx_int_t ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
ngx_int_t ngx_ssl_ocsp_validate(ngx_connection_t *c);
ngx_int_t ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s);
void ngx_ssl_ocsp_cleanup(ngx_connection_t *c);
ngx_int_t ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data);
#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)
RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
int key_length);
#endif
ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file);
ngx_array_t *ngx_ssl_preserve_passwords(ngx_conf_t *cf,
ngx_array_t *passwords);
@ -189,6 +219,9 @@ ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file);
ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name);
ngx_int_t ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_uint_t enable);
ngx_int_t ngx_ssl_conf_commands(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_array_t *commands);
ngx_int_t ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_uint_t enable);
ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
@ -197,6 +230,7 @@ ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_array_t *paths);
ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
ngx_uint_t flags);
@ -281,6 +315,7 @@ extern int ngx_ssl_connection_index;
extern int ngx_ssl_server_conf_index;
extern int ngx_ssl_session_cache_index;
extern int ngx_ssl_session_ticket_keys_index;
extern int ngx_ssl_ocsp_index;
extern int ngx_ssl_certificate_index;
extern int ngx_ssl_next_certificate_index;
extern int ngx_ssl_certificate_name_index;

File diff suppressed because it is too large Load diff

View file

@ -960,6 +960,22 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
return NGX_OK;
}
if (p->upstream_done) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
"input data after close");
return NGX_OK;
}
if (p->length == 0) {
p->upstream_done = 1;
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
return NGX_OK;
}
cl = ngx_chain_get_free_buf(p->pool, &p->free);
if (cl == NULL) {
return NGX_ERROR;
@ -987,6 +1003,18 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
return NGX_OK;
}
if (b->last - b->pos > p->length) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
b->last = b->pos + p->length;
p->upstream_done = 1;
return NGX_OK;
}
p->length -= b->last - b->pos;
return NGX_OK;

View file

@ -363,6 +363,8 @@ ngx_event_recvmsg(ngx_event_t *ev)
c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
c->start_time = ngx_current_msec;
#if (NGX_STAT_STUB)
(void) ngx_atomic_fetch_add(ngx_stat_handled, 1);
#endif

View file

@ -81,12 +81,15 @@ typedef struct {
size_t length;
size_t padding;
off_t rest;
ngx_chain_t *free;
ngx_chain_t *busy;
unsigned fastcgi_stdout:1;
unsigned large_stderr:1;
unsigned header_sent:1;
unsigned closed:1;
ngx_array_t *split_parts;
@ -2075,13 +2078,31 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
static ngx_int_t
ngx_http_fastcgi_input_filter_init(void *data)
{
ngx_http_request_t *r = data;
ngx_http_request_t *r = data;
ngx_http_upstream_t *u;
ngx_http_fastcgi_ctx_t *f;
ngx_http_fastcgi_loc_conf_t *flcf;
u = r->upstream;
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
r->upstream->pipe->length = flcf->keep_conn ?
(off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
u->pipe->length = flcf->keep_conn ?
(off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
{
f->rest = 0;
} else if (r->method == NGX_HTTP_HEAD) {
f->rest = -2;
} else {
f->rest = u->headers_in.content_length_n;
}
return NGX_OK;
}
@ -2106,6 +2127,15 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
if (p->upstream_done || f->closed) {
r->upstream->keepalive = 0;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi data after close");
return NGX_OK;
}
b = NULL;
prev = &buf->shadow;
@ -2128,13 +2158,25 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
f->state = ngx_http_fastcgi_st_padding;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi closed stdout");
if (f->rest > 0) {
ngx_log_error(NGX_LOG_ERR, p->log, 0,
"upstream prematurely closed "
"FastCGI stdout");
p->upstream_error = 1;
p->upstream_eof = 0;
f->closed = 1;
break;
}
if (!flcf->keep_conn) {
p->upstream_done = 1;
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi closed stdout");
continue;
}
@ -2143,6 +2185,18 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi sent end request");
if (f->rest > 0) {
ngx_log_error(NGX_LOG_ERR, p->log, 0,
"upstream prematurely closed "
"FastCGI request");
p->upstream_error = 1;
p->upstream_eof = 0;
f->closed = 1;
break;
}
if (!flcf->keep_conn) {
p->upstream_done = 1;
break;
@ -2252,6 +2306,18 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
break;
}
if (f->rest == -2) {
f->rest = r->upstream->headers_in.content_length_n;
}
if (f->rest == 0) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
p->upstream_done = 1;
break;
}
cl = ngx_chain_get_free_buf(p->pool, &p->free);
if (cl == NULL) {
return NGX_ERROR;
@ -2289,15 +2355,27 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
f->pos += f->length;
b->last = f->pos;
continue;
} else {
f->length -= f->last - f->pos;
f->pos = f->last;
b->last = f->last;
}
f->length -= f->last - f->pos;
if (f->rest > 0) {
b->last = f->last;
if (b->last - b->pos > f->rest) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
break;
b->last = b->pos + f->rest;
p->upstream_done = 1;
break;
}
f->rest -= b->last - b->pos;
}
}
if (flcf->keep_conn) {
@ -2391,6 +2469,14 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
if (f->rest > 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream prematurely closed "
"FastCGI request");
u->error = 1;
break;
}
if (f->pos + f->padding < f->last) {
u->length = 0;
break;
@ -2486,6 +2572,14 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
break;
}
if (f->rest == 0) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
u->length = 0;
break;
}
cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
if (cl == NULL) {
return NGX_ERROR;
@ -2510,13 +2604,27 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
f->pos += f->length;
b->last = f->pos;
continue;
} else {
f->length -= f->last - f->pos;
f->pos = f->last;
b->last = f->last;
}
f->length -= f->last - f->pos;
b->last = f->last;
if (f->rest > 0) {
break;
if (b->last - b->pos > f->rest) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
b->last = b->pos + f->rest;
u->length = 0;
break;
}
f->rest -= b->last - b->pos;
}
}
return NGX_OK;

View file

@ -156,12 +156,6 @@ ngx_http_flv_handler(ngx_http_request_t *r)
}
if (!of.is_file) {
if (ngx_close_file(of.fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
ngx_close_file_n " \"%s\" failed", path.data);
}
return NGX_DECLINED;
}

View file

@ -40,6 +40,7 @@ typedef struct {
ngx_str_t ssl_certificate;
ngx_str_t ssl_certificate_key;
ngx_array_t *ssl_passwords;
ngx_array_t *ssl_conf_commands;
#endif
} ngx_http_grpc_loc_conf_t;
@ -84,6 +85,8 @@ typedef struct {
ngx_uint_t pings;
ngx_uint_t settings;
off_t length;
ssize_t send_window;
size_t recv_window;
@ -120,6 +123,8 @@ typedef struct {
unsigned end_stream:1;
unsigned done:1;
unsigned status:1;
unsigned rst:1;
unsigned goaway:1;
ngx_http_request_t *request;
@ -205,6 +210,8 @@ static char *ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd,
#if (NGX_HTTP_SSL)
static char *ngx_http_grpc_ssl_password_file(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
static char *ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post,
void *data);
static ngx_int_t ngx_http_grpc_set_ssl(ngx_conf_t *cf,
ngx_http_grpc_loc_conf_t *glcf);
#endif
@ -239,6 +246,9 @@ static ngx_conf_bitmask_t ngx_http_grpc_ssl_protocols[] = {
{ ngx_null_string, 0 }
};
static ngx_conf_post_t ngx_http_grpc_ssl_conf_command_post =
{ ngx_http_grpc_ssl_conf_command_check };
#endif
@ -435,6 +445,13 @@ static ngx_command_t ngx_http_grpc_commands[] = {
0,
NULL },
{ ngx_string("grpc_ssl_conf_command"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
ngx_conf_set_keyval_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_grpc_loc_conf_t, ssl_conf_commands),
&ngx_http_grpc_ssl_conf_command_post },
#endif
ngx_null_command
@ -1125,20 +1142,11 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
f->flags |= NGX_HTTP_V2_END_HEADERS_FLAG;
#if (NGX_DEBUG)
if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
u_char buf[512];
size_t n, m;
n = ngx_min(b->last - b->pos, 256);
m = ngx_hex_dump(buf, b->pos, n) - buf;
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"grpc header: %*s%s, len: %uz",
m, buf, b->last - b->pos > 256 ? "..." : "",
b->last - b->pos);
}
#endif
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"grpc header: %*xs%s, len: %uz",
(size_t) ngx_min(b->last - b->pos, 256), b->pos,
b->last - b->pos > 256 ? "..." : "",
b->last - b->pos);
if (r->request_body_no_buffering) {
@ -1205,6 +1213,8 @@ ngx_http_grpc_reinit_request(ngx_http_request_t *r)
ctx->end_stream = 0;
ctx->done = 0;
ctx->status = 0;
ctx->rst = 0;
ctx->goaway = 0;
ctx->connection = NULL;
return NGX_OK;
@ -1560,6 +1570,7 @@ ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in)
&& ctx->out == NULL
&& ctx->output_closed
&& !ctx->output_blocked
&& !ctx->goaway
&& ctx->state == ngx_http_grpc_st_start)
{
u->keepalive = 1;
@ -1587,20 +1598,11 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
u = r->upstream;
b = &u->buffer;
#if (NGX_DEBUG)
if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
u_char buf[512];
size_t n, m;
n = ngx_min(b->last - b->pos, 256);
m = ngx_hex_dump(buf, b->pos, n) - buf;
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"grpc response: %*s%s, len: %uz",
m, buf, b->last - b->pos > 256 ? "..." : "",
b->last - b->pos);
}
#endif
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"grpc response: %*xs%s, len: %uz",
(size_t) ngx_min(b->last - b->pos, 256),
b->pos, b->last - b->pos > 256 ? "..." : "",
b->last - b->pos);
ctx = ngx_http_grpc_get_ctx(r);
@ -1718,6 +1720,8 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
ctx->goaway = 1;
continue;
}
@ -1911,6 +1915,7 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
&& ctx->out == NULL
&& ctx->output_closed
&& !ctx->output_blocked
&& !ctx->goaway
&& b->last == b->pos)
{
u->keepalive = 1;
@ -1951,10 +1956,29 @@ ngx_http_grpc_filter_init(void *data)
r = ctx->request;
u = r->upstream;
u->length = 1;
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
|| r->method == NGX_HTTP_HEAD)
{
ctx->length = 0;
} else {
ctx->length = u->headers_in.content_length_n;
}
if (ctx->end_stream) {
if (ctx->length > 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream prematurely closed stream");
return NGX_ERROR;
}
u->length = 0;
ctx->done = 1;
} else {
u->length = 1;
}
return NGX_OK;
@ -1997,6 +2021,12 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
if (ctx->done) {
if (ctx->length > 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream prematurely closed stream");
return NGX_ERROR;
}
/*
* We have finished parsing the response and the
* remaining control frames. If there are unsent
@ -2014,6 +2044,7 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
if (ctx->in == NULL
&& ctx->output_closed
&& !ctx->output_blocked
&& !ctx->goaway
&& ctx->state == ngx_http_grpc_st_start)
{
u->keepalive = 1;
@ -2088,7 +2119,10 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR;
}
if (ctx->stream_id && ctx->done) {
if (ctx->stream_id && ctx->done
&& ctx->type != NGX_HTTP_V2_RST_STREAM_FRAME
&& ctx->type != NGX_HTTP_V2_WINDOW_UPDATE_FRAME)
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent frame for closed stream %ui",
ctx->stream_id);
@ -2131,11 +2165,21 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR;
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream rejected request with error %ui",
ctx->error);
if (ctx->error || !ctx->done) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream rejected request with error %ui",
ctx->error);
return NGX_ERROR;
}
return NGX_ERROR;
if (ctx->rst) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent frame for closed stream %ui",
ctx->stream_id);
return NGX_ERROR;
}
ctx->rst = 1;
}
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
@ -2170,6 +2214,8 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR;
}
ctx->goaway = 1;
continue;
}
@ -2402,6 +2448,18 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
b->pos = b->last;
buf->last = b->pos;
if (ctx->length != -1) {
if (buf->last - buf->pos > ctx->length) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent response body larger "
"than indicated content length");
return NGX_ERROR;
}
ctx->length -= buf->last - buf->pos;
}
return NGX_AGAIN;
}
@ -2409,6 +2467,18 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
buf->last = b->pos;
ctx->rest = ctx->padding;
if (ctx->length != -1) {
if (buf->last - buf->pos > ctx->length) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent response body larger "
"than indicated content length");
return NGX_ERROR;
}
ctx->length -= buf->last - buf->pos;
}
done:
if (ctx->padding) {
@ -4272,7 +4342,6 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
* conf->upstream.hide_headers_hash = { NULL, 0 };
* conf->upstream.ssl_name = NULL;
*
* conf->headers_source = NULL;
* conf->headers.lengths = NULL;
* conf->headers.values = NULL;
* conf->headers.hash = { NULL, 0 };
@ -4308,6 +4377,7 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
conf->upstream.ssl_verify = NGX_CONF_UNSET;
conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
conf->ssl_passwords = NGX_CONF_UNSET_PTR;
conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
#endif
/* the hardcoded values */
@ -4325,6 +4395,8 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
conf->upstream.pass_trailers = 1;
conf->upstream.preserve_output = 1;
conf->headers_source = NGX_CONF_UNSET_PTR;
ngx_str_set(&conf->upstream.module, "grpc");
return conf;
@ -4416,6 +4488,9 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
prev->ssl_certificate_key, "");
ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
prev->ssl_conf_commands, NULL);
if (conf->ssl && ngx_http_grpc_set_ssl(cf, conf) != NGX_OK) {
return NGX_CONF_ERROR;
}
@ -4455,9 +4530,10 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
clcf->handler = ngx_http_grpc_handler;
}
if (conf->headers_source == NULL) {
ngx_conf_merge_ptr_value(conf->headers_source, prev->headers_source, NULL);
if (conf->headers_source == prev->headers_source) {
conf->headers = prev->headers;
conf->headers_source = prev->headers_source;
conf->host_set = prev->host_set;
}
@ -4782,6 +4858,17 @@ ngx_http_grpc_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
static char *
ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#else
return NGX_CONF_OK;
#endif
}
static ngx_int_t
ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
{
@ -4872,6 +4959,12 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
#endif
if (ngx_ssl_conf_commands(cf, glcf->upstream.ssl, glcf->ssl_conf_commands)
!= NGX_OK)
{
return NGX_ERROR;
}
return NGX_OK;
}

View file

@ -56,7 +56,7 @@ typedef struct {
unsigned done:1;
unsigned nomem:1;
unsigned buffering:1;
unsigned intel:1;
unsigned zlib_ng:1;
size_t zin;
size_t zout;
@ -213,7 +213,7 @@ static ngx_str_t ngx_http_gzip_ratio = ngx_string("gzip_ratio");
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
static ngx_uint_t ngx_http_gzip_assume_intel;
static ngx_uint_t ngx_http_gzip_assume_zlib_ng;
static ngx_int_t
@ -501,18 +501,21 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
* 8K is for zlib deflate_state, it takes
* *) 5816 bytes on i386 and sparc64 (32-bit mode)
* *) 5920 bytes on amd64 and sparc64
*
* A zlib variant from Intel (https://github.com/jtkukunas/zlib)
* uses additional 16-byte padding in one of window-sized buffers.
*/
if (!ngx_http_gzip_assume_intel) {
ctx->allocated = 8192 + (1 << (wbits + 2)) + (1 << (memlevel + 9));
if (!ngx_http_gzip_assume_zlib_ng) {
ctx->allocated = 8192 + 16 + (1 << (wbits + 2))
+ (1 << (memlevel + 9));
} else {
/*
* A zlib variant from Intel, https://github.com/jtkukunas/zlib.
* It can force window bits to 13 for fast compression level,
* on processors with SSE 4.2 it uses 64K hash instead of scaling
* it from the specified memory level, and also introduces
* 16-byte padding in one out of the two window-sized buffers.
* Another zlib variant, https://github.com/zlib-ng/zlib-ng.
* It forces window bits to 13 for fast compression level,
* uses 16-byte padding in one of window-sized buffers, and
* uses 128K hash.
*/
if (conf->level == 1) {
@ -520,9 +523,8 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
}
ctx->allocated = 8192 + 16 + (1 << (wbits + 2))
+ (1 << (ngx_max(memlevel, 8) + 8))
+ (1 << (memlevel + 8));
ctx->intel = 1;
+ 131072 + (1 << (memlevel + 8));
ctx->zlib_ng = 1;
}
}
@ -945,13 +947,13 @@ ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size)
return p;
}
if (ctx->intel) {
if (ctx->zlib_ng) {
ngx_log_error(NGX_LOG_ALERT, ctx->request->connection->log, 0,
"gzip filter failed to use preallocated memory: "
"%ud of %ui", items * size, ctx->allocated);
} else {
ngx_http_gzip_assume_intel = 1;
ngx_http_gzip_assume_zlib_ng = 1;
}
p = ngx_palloc(ctx->request->pool, items * size);

View file

@ -69,6 +69,8 @@ static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit,
ngx_uint_t hash, ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account);
static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits,
ngx_uint_t n, ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit);
static void ngx_http_limit_req_unlock(ngx_http_limit_req_limit_t *limits,
ngx_uint_t n);
static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
ngx_uint_t n);
@ -223,6 +225,7 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
ctx = limit->shm_zone->data;
if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) {
ngx_http_limit_req_unlock(limits, n);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@ -270,21 +273,7 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
&limit->shm_zone->shm.name);
}
while (n--) {
ctx = limits[n].shm_zone->data;
if (ctx->node == NULL) {
continue;
}
ngx_shmtx_lock(&ctx->shpool->mutex);
ctx->node->count--;
ngx_shmtx_unlock(&ctx->shpool->mutex);
ctx->node = NULL;
}
ngx_http_limit_req_unlock(limits, n);
if (lrcf->dry_run) {
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN;
@ -321,8 +310,13 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
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;
if (r->connection->read->ready) {
ngx_post_event(r->connection->read, &ngx_posted_events);
} else {
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
r->read_event_handler = ngx_http_test_reading;
@ -612,6 +606,29 @@ ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, ngx_uint_t n,
}
static void
ngx_http_limit_req_unlock(ngx_http_limit_req_limit_t *limits, ngx_uint_t n)
{
ngx_http_limit_req_ctx_t *ctx;
while (n--) {
ctx = limits[n].shm_zone->data;
if (ctx->node == NULL) {
continue;
}
ngx_shmtx_lock(&ctx->shpool->mutex);
ctx->node->count--;
ngx_shmtx_unlock(&ctx->shpool->mutex);
ctx->node = NULL;
}
}
static void
ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n)
{

View file

@ -485,10 +485,11 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
if (u->length == (ssize_t) ctx->rest) {
if (ngx_strncmp(b->last,
if (bytes > u->length
|| ngx_strncmp(b->last,
ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
bytes)
!= 0)
!= 0)
{
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
"memcached sent invalid trailer");
@ -540,7 +541,9 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END);
if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) {
if (bytes > u->length
|| ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0)
{
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
"memcached sent invalid trailer");

View file

@ -521,12 +521,6 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
}
if (!of.is_file) {
if (ngx_close_file(of.fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
ngx_close_file_n " \"%s\" failed", path.data);
}
return NGX_DECLINED;
}

File diff suppressed because it is too large Load diff

View file

@ -49,6 +49,7 @@ static ngx_int_t ngx_http_scgi_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_input_filter_init(void *data);
static void ngx_http_scgi_abort_request(ngx_http_request_t *r);
static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
@ -534,6 +535,10 @@ ngx_http_scgi_handler(ngx_http_request_t *r)
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
u->pipe->input_ctx = r;
u->input_filter_init = ngx_http_scgi_input_filter_init;
u->input_filter = ngx_http_upstream_non_buffered_filter;
u->input_filter_ctx = r;
if (!scf->upstream.request_buffering
&& scf->upstream.pass_request_body
&& !r->headers_in.chunked)
@ -1145,6 +1150,37 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
}
static ngx_int_t
ngx_http_scgi_input_filter_init(void *data)
{
ngx_http_request_t *r = data;
ngx_http_upstream_t *u;
u = r->upstream;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http scgi filter init s:%ui l:%O",
u->headers_in.status_n, u->headers_in.content_length_n);
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
{
u->pipe->length = 0;
u->length = 0;
} else if (r->method == NGX_HTTP_HEAD) {
u->pipe->length = -1;
u->length = -1;
} else {
u->pipe->length = u->headers_in.content_length_n;
u->length = u->headers_in.content_length_n;
}
return NGX_OK;
}
static void
ngx_http_scgi_abort_request(ngx_http_request_t *r)
{

View file

@ -180,6 +180,11 @@ ngx_http_slice_header_filter(ngx_http_request_t *r)
r->headers_out.content_range->hash = 0;
r->headers_out.content_range = NULL;
if (r->headers_out.accept_ranges) {
r->headers_out.accept_ranges->hash = 0;
r->headers_out.accept_ranges = NULL;
}
r->allow_ranges = 1;
r->subrequest_ranges = 1;
r->single_range = 1;

View file

@ -50,6 +50,11 @@ static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_ssl_conf_command_check(ngx_conf_t *cf, void *post,
void *data);
static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
@ -74,11 +79,23 @@ static ngx_conf_enum_t ngx_http_ssl_verify[] = {
};
static ngx_conf_enum_t ngx_http_ssl_ocsp[] = {
{ ngx_string("off"), 0 },
{ ngx_string("on"), 1 },
{ ngx_string("leaf"), 2 },
{ ngx_null_string, 0 }
};
static ngx_conf_deprecated_t ngx_http_ssl_deprecated = {
ngx_conf_deprecated, "ssl", "listen ... ssl"
};
static ngx_conf_post_t ngx_http_ssl_conf_command_post =
{ ngx_http_ssl_conf_command_check };
static ngx_command_t ngx_http_ssl_commands[] = {
{ ngx_string("ssl"),
@ -214,6 +231,27 @@ static ngx_command_t ngx_http_ssl_commands[] = {
offsetof(ngx_http_ssl_srv_conf_t, crl),
NULL },
{ ngx_string("ssl_ocsp"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_enum_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_ssl_srv_conf_t, ocsp),
&ngx_http_ssl_ocsp },
{ ngx_string("ssl_ocsp_responder"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_ssl_srv_conf_t, ocsp_responder),
NULL },
{ ngx_string("ssl_ocsp_cache"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_ssl_ocsp_cache,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
{ ngx_string("ssl_stapling"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@ -249,6 +287,20 @@ static ngx_command_t ngx_http_ssl_commands[] = {
offsetof(ngx_http_ssl_srv_conf_t, early_data),
NULL },
{ ngx_string("ssl_conf_command"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2,
ngx_conf_set_keyval_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_ssl_srv_conf_t, conf_commands),
&ngx_http_ssl_conf_command_post },
{ ngx_string("ssl_reject_handshake"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_ssl_srv_conf_t, reject_handshake),
NULL },
ngx_null_command
};
@ -561,6 +613,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
* sscf->crl = { 0, NULL };
* sscf->ciphers = { 0, NULL };
* sscf->shm_zone = NULL;
* sscf->ocsp_responder = { 0, NULL };
* sscf->stapling_file = { 0, NULL };
* sscf->stapling_responder = { 0, NULL };
*/
@ -568,16 +621,20 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
sscf->enable = NGX_CONF_UNSET;
sscf->prefer_server_ciphers = NGX_CONF_UNSET;
sscf->early_data = NGX_CONF_UNSET;
sscf->reject_handshake = NGX_CONF_UNSET;
sscf->buffer_size = NGX_CONF_UNSET_SIZE;
sscf->verify = NGX_CONF_UNSET_UINT;
sscf->verify_depth = NGX_CONF_UNSET_UINT;
sscf->certificates = NGX_CONF_UNSET_PTR;
sscf->certificate_keys = NGX_CONF_UNSET_PTR;
sscf->passwords = NGX_CONF_UNSET_PTR;
sscf->conf_commands = NGX_CONF_UNSET_PTR;
sscf->builtin_session_cache = NGX_CONF_UNSET;
sscf->session_timeout = NGX_CONF_UNSET;
sscf->session_tickets = NGX_CONF_UNSET;
sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
sscf->ocsp = NGX_CONF_UNSET_UINT;
sscf->ocsp_cache_zone = NGX_CONF_UNSET_PTR;
sscf->stapling = NGX_CONF_UNSET;
sscf->stapling_verify = NGX_CONF_UNSET;
@ -611,6 +668,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
prev->prefer_server_ciphers, 0);
ngx_conf_merge_value(conf->early_data, prev->early_data, 0);
ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0);
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
@ -641,6 +699,13 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);
ngx_conf_merge_uint_value(conf->ocsp, prev->ocsp, 0);
ngx_conf_merge_str_value(conf->ocsp_responder, prev->ocsp_responder, "");
ngx_conf_merge_ptr_value(conf->ocsp_cache_zone,
prev->ocsp_cache_zone, NULL);
ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0);
ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
@ -651,7 +716,27 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->enable) {
if (conf->certificates == NULL) {
if (conf->certificates) {
if (conf->certificate_keys == NULL) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no \"ssl_certificate_key\" is defined for "
"the \"ssl\" directive in %s:%ui",
conf->file, conf->line);
return NGX_CONF_ERROR;
}
if (conf->certificate_keys->nelts < conf->certificates->nelts) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no \"ssl_certificate_key\" is defined "
"for certificate \"%V\" and "
"the \"ssl\" directive in %s:%ui",
((ngx_str_t *) conf->certificates->elts)
+ conf->certificates->nelts - 1,
conf->file, conf->line);
return NGX_CONF_ERROR;
}
} else if (!conf->reject_handshake) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no \"ssl_certificate\" is defined for "
"the \"ssl\" directive in %s:%ui",
@ -659,30 +744,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
if (conf->certificate_keys == NULL) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no \"ssl_certificate_key\" is defined for "
"the \"ssl\" directive in %s:%ui",
conf->file, conf->line);
return NGX_CONF_ERROR;
}
if (conf->certificate_keys->nelts < conf->certificates->nelts) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no \"ssl_certificate_key\" is defined "
"for certificate \"%V\" and "
"the \"ssl\" directive in %s:%ui",
((ngx_str_t *) conf->certificates->elts)
+ conf->certificates->nelts - 1,
conf->file, conf->line);
return NGX_CONF_ERROR;
}
} else {
if (conf->certificates == NULL) {
return NGX_CONF_OK;
}
} else if (conf->certificates) {
if (conf->certificate_keys == NULL
|| conf->certificate_keys->nelts < conf->certificates->nelts)
@ -694,6 +756,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
+ conf->certificates->nelts - 1);
return NGX_CONF_ERROR;
}
} else if (!conf->reject_handshake) {
return NGX_CONF_OK;
}
if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
@ -752,7 +817,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
#endif
} else {
} else if (conf->certificates) {
/* configure certificates */
@ -802,6 +867,23 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
if (conf->ocsp) {
if (conf->verify == 3) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"\"ssl_ocsp\" is incompatible with "
"\"ssl_verify_client optional_no_ca\"");
return NGX_CONF_ERROR;
}
if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, conf->ocsp,
conf->ocsp_cache_zone)
!= NGX_OK)
{
return NGX_CONF_ERROR;
}
}
if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
return NGX_CONF_ERROR;
}
@ -857,6 +939,10 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
@ -870,6 +956,10 @@ ngx_http_ssl_compile_certificates(ngx_conf_t *cf,
ngx_http_complex_value_t *cv;
ngx_http_compile_complex_value_t ccv;
if (conf->certificates == NULL) {
return NGX_OK;
}
cert = conf->certificates->elts;
key = conf->certificate_keys->elts;
nelts = conf->certificates->nelts;
@ -1100,6 +1190,96 @@ invalid:
}
static char *
ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_ssl_srv_conf_t *sscf = conf;
size_t len;
ngx_int_t n;
ngx_str_t *value, name, size;
ngx_uint_t j;
if (sscf->ocsp_cache_zone != NGX_CONF_UNSET_PTR) {
return "is duplicate";
}
value = cf->args->elts;
if (ngx_strcmp(value[1].data, "off") == 0) {
sscf->ocsp_cache_zone = NULL;
return NGX_CONF_OK;
}
if (value[1].len <= sizeof("shared:") - 1
|| ngx_strncmp(value[1].data, "shared:", sizeof("shared:") - 1) != 0)
{
goto invalid;
}
len = 0;
for (j = sizeof("shared:") - 1; j < value[1].len; j++) {
if (value[1].data[j] == ':') {
break;
}
len++;
}
if (len == 0) {
goto invalid;
}
name.len = len;
name.data = value[1].data + sizeof("shared:") - 1;
size.len = value[1].len - j - 1;
size.data = name.data + len + 1;
n = ngx_parse_size(&size);
if (n == NGX_ERROR) {
goto invalid;
}
if (n < (ngx_int_t) (8 * ngx_pagesize)) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"OCSP cache \"%V\" is too small", &value[1]);
return NGX_CONF_ERROR;
}
sscf->ocsp_cache_zone = ngx_shared_memory_add(cf, &name, n,
&ngx_http_ssl_module_ctx);
if (sscf->ocsp_cache_zone == NULL) {
return NGX_CONF_ERROR;
}
sscf->ocsp_cache_zone->init = ngx_ssl_ocsp_cache_init;
return NGX_CONF_OK;
invalid:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid OCSP cache \"%V\"", &value[1]);
return NGX_CONF_ERROR;
}
static char *
ngx_http_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#else
return NGX_CONF_OK;
#endif
}
static ngx_int_t
ngx_http_ssl_init(ngx_conf_t *cf)
{
@ -1118,17 +1298,28 @@ ngx_http_ssl_init(ngx_conf_t *cf)
sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
if (sscf->ssl.ctx == NULL || !sscf->stapling) {
if (sscf->ssl.ctx == NULL) {
continue;
}
clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
if (sscf->stapling) {
if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
clcf->resolver_timeout)
!= NGX_OK)
{
return NGX_ERROR;
}
}
if (sscf->ocsp) {
if (ngx_ssl_ocsp_resolver(cf, &sscf->ssl, clcf->resolver,
clcf->resolver_timeout)
!= NGX_OK)
{
return NGX_ERROR;
!= NGX_OK)
{
return NGX_ERROR;
}
}
}
@ -1149,7 +1340,33 @@ ngx_http_ssl_init(ngx_conf_t *cf)
cscf = addr[a].default_server;
sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
if (sscf->certificates == NULL) {
if (sscf->certificates) {
continue;
}
if (!sscf->reject_handshake) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no \"ssl_certificate\" is defined for "
"the \"listen ... ssl\" directive in %s:%ui",
cscf->file_name, cscf->line);
return NGX_ERROR;
}
/*
* if no certificates are defined in the default server,
* check all non-default server blocks
*/
cscfp = addr[a].servers.elts;
for (s = 0; s < addr[a].servers.nelts; s++) {
cscf = cscfp[s];
sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
if (sscf->certificates || sscf->reject_handshake) {
continue;
}
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no \"ssl_certificate\" is defined for "
"the \"listen ... ssl\" directive in %s:%ui",

View file

@ -21,6 +21,7 @@ typedef struct {
ngx_flag_t prefer_server_ciphers;
ngx_flag_t early_data;
ngx_flag_t reject_handshake;
ngx_uint_t protocols;
@ -48,12 +49,17 @@ typedef struct {
ngx_str_t ciphers;
ngx_array_t *passwords;
ngx_array_t *conf_commands;
ngx_shm_zone_t *shm_zone;
ngx_flag_t session_tickets;
ngx_array_t *session_ticket_keys;
ngx_uint_t ocsp;
ngx_str_t ocsp_responder;
ngx_shm_zone_t *ocsp_cache_zone;
ngx_flag_t stapling;
ngx_flag_t stapling_verify;
ngx_str_t stapling_file;

View file

@ -103,16 +103,6 @@ ngx_http_stub_status_handler(ngx_http_request_t *r)
ngx_str_set(&r->headers_out.content_type, "text/plain");
r->headers_out.content_type_lowcase = NULL;
if (r->method == NGX_HTTP_HEAD) {
r->headers_out.status = NGX_HTTP_OK;
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
return rc;
}
}
size = sizeof("Active connections: \n") + NGX_ATOMIC_T_LEN
+ sizeof("server accepts handled requests\n") - 1
+ 6 + 3 * NGX_ATOMIC_T_LEN

View file

@ -13,6 +13,7 @@
typedef struct {
ngx_uint_t max_cached;
ngx_uint_t requests;
ngx_msec_t time;
ngx_msec_t timeout;
ngx_queue_t cache;
@ -86,6 +87,13 @@ static ngx_command_t ngx_http_upstream_keepalive_commands[] = {
0,
NULL },
{ ngx_string("keepalive_time"),
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_upstream_keepalive_srv_conf_t, time),
NULL },
{ ngx_string("keepalive_timeout"),
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@ -149,8 +157,9 @@ ngx_http_upstream_init_keepalive(ngx_conf_t *cf,
kcf = ngx_http_conf_upstream_srv_conf(us,
ngx_http_upstream_keepalive_module);
ngx_conf_init_msec_value(kcf->time, 3600000);
ngx_conf_init_msec_value(kcf->timeout, 60000);
ngx_conf_init_uint_value(kcf->requests, 100);
ngx_conf_init_uint_value(kcf->requests, 1000);
if (kcf->original_init_upstream(cf, us) != NGX_OK) {
return NGX_ERROR;
@ -326,6 +335,10 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
goto invalid;
}
if (ngx_current_msec - c->start_time > kp->conf->time) {
goto invalid;
}
if (!u->keepalive) {
goto invalid;
}
@ -513,6 +526,7 @@ ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf)
* conf->max_cached = 0;
*/
conf->time = NGX_CONF_UNSET_MSEC;
conf->timeout = NGX_CONF_UNSET_MSEC;
conf->requests = NGX_CONF_UNSET_UINT;

View file

@ -15,12 +15,21 @@
#define NGX_HTTP_USERID_V1 2
#define NGX_HTTP_USERID_ON 3
#define NGX_HTTP_USERID_COOKIE_OFF 0x0002
#define NGX_HTTP_USERID_COOKIE_SECURE 0x0004
#define NGX_HTTP_USERID_COOKIE_HTTPONLY 0x0008
#define NGX_HTTP_USERID_COOKIE_SAMESITE 0x0010
#define NGX_HTTP_USERID_COOKIE_SAMESITE_STRICT 0x0020
#define NGX_HTTP_USERID_COOKIE_SAMESITE_LAX 0x0040
#define NGX_HTTP_USERID_COOKIE_SAMESITE_NONE 0x0080
/* 31 Dec 2037 23:55:55 GMT */
#define NGX_HTTP_USERID_MAX_EXPIRES 2145916555
typedef struct {
ngx_uint_t enable;
ngx_uint_t flags;
ngx_int_t service;
@ -88,6 +97,20 @@ static ngx_conf_enum_t ngx_http_userid_state[] = {
};
static ngx_conf_bitmask_t ngx_http_userid_flags[] = {
{ ngx_string("off"), NGX_HTTP_USERID_COOKIE_OFF },
{ ngx_string("secure"), NGX_HTTP_USERID_COOKIE_SECURE },
{ ngx_string("httponly"), NGX_HTTP_USERID_COOKIE_HTTPONLY },
{ ngx_string("samesite=strict"),
NGX_HTTP_USERID_COOKIE_SAMESITE|NGX_HTTP_USERID_COOKIE_SAMESITE_STRICT },
{ ngx_string("samesite=lax"),
NGX_HTTP_USERID_COOKIE_SAMESITE|NGX_HTTP_USERID_COOKIE_SAMESITE_LAX },
{ ngx_string("samesite=none"),
NGX_HTTP_USERID_COOKIE_SAMESITE|NGX_HTTP_USERID_COOKIE_SAMESITE_NONE },
{ ngx_null_string, 0 }
};
static ngx_conf_post_handler_pt ngx_http_userid_domain_p =
ngx_http_userid_domain;
static ngx_conf_post_handler_pt ngx_http_userid_path_p = ngx_http_userid_path;
@ -138,6 +161,13 @@ static ngx_command_t ngx_http_userid_commands[] = {
0,
NULL },
{ ngx_string("userid_flags"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
ngx_conf_set_bitmask_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_userid_conf_t, flags),
&ngx_http_userid_flags },
{ ngx_string("userid_p3p"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
@ -383,6 +413,26 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
len += conf->domain.len;
}
if (conf->flags & NGX_HTTP_USERID_COOKIE_SECURE) {
len += sizeof("; secure") - 1;
}
if (conf->flags & NGX_HTTP_USERID_COOKIE_HTTPONLY) {
len += sizeof("; httponly") - 1;
}
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_STRICT) {
len += sizeof("; samesite=strict") - 1;
}
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_LAX) {
len += sizeof("; samesite=lax") - 1;
}
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_NONE) {
len += sizeof("; samesite=none") - 1;
}
cookie = ngx_pnalloc(r->pool, len);
if (cookie == NULL) {
return NGX_ERROR;
@ -422,6 +472,26 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
p = ngx_copy(p, conf->path.data, conf->path.len);
if (conf->flags & NGX_HTTP_USERID_COOKIE_SECURE) {
p = ngx_cpymem(p, "; secure", sizeof("; secure") - 1);
}
if (conf->flags & NGX_HTTP_USERID_COOKIE_HTTPONLY) {
p = ngx_cpymem(p, "; httponly", sizeof("; httponly") - 1);
}
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_STRICT) {
p = ngx_cpymem(p, "; samesite=strict", sizeof("; samesite=strict") - 1);
}
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_LAX) {
p = ngx_cpymem(p, "; samesite=lax", sizeof("; samesite=lax") - 1);
}
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_NONE) {
p = ngx_cpymem(p, "; samesite=none", sizeof("; samesite=none") - 1);
}
set_cookie = ngx_list_push(&r->headers_out.headers);
if (set_cookie == NULL) {
return NGX_ERROR;
@ -658,6 +728,7 @@ ngx_http_userid_create_conf(ngx_conf_t *cf)
/*
* set by ngx_pcalloc():
*
* conf->flags = 0;
* conf->name = { 0, NULL };
* conf->domain = { 0, NULL };
* conf->path = { 0, NULL };
@ -682,6 +753,9 @@ ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_uint_value(conf->enable, prev->enable,
NGX_HTTP_USERID_OFF);
ngx_conf_merge_bitmask_value(conf->flags, prev->flags,
(NGX_CONF_BITMASK_SET|NGX_HTTP_USERID_COOKIE_OFF));
ngx_conf_merge_str_value(conf->name, prev->name, "uid");
ngx_conf_merge_str_value(conf->domain, prev->domain, "");
ngx_conf_merge_str_value(conf->path, prev->path, "; path=/");

View file

@ -57,6 +57,7 @@ typedef struct {
ngx_str_t ssl_certificate;
ngx_str_t ssl_certificate_key;
ngx_array_t *ssl_passwords;
ngx_array_t *ssl_conf_commands;
#endif
} ngx_http_uwsgi_loc_conf_t;
@ -67,6 +68,7 @@ static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r);
static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r);
static ngx_int_t ngx_http_uwsgi_input_filter_init(void *data);
static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
ngx_int_t rc);
@ -95,6 +97,8 @@ static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
#if (NGX_HTTP_SSL)
static char *ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
static char *ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post,
void *data);
static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
ngx_http_uwsgi_loc_conf_t *uwcf);
#endif
@ -133,6 +137,9 @@ static ngx_conf_bitmask_t ngx_http_uwsgi_ssl_protocols[] = {
{ ngx_null_string, 0 }
};
static ngx_conf_post_t ngx_http_uwsgi_ssl_conf_command_post =
{ ngx_http_uwsgi_ssl_conf_command_check };
#endif
@ -560,6 +567,13 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
0,
NULL },
{ ngx_string("uwsgi_ssl_conf_command"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
ngx_conf_set_keyval_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_uwsgi_loc_conf_t, ssl_conf_commands),
&ngx_http_uwsgi_ssl_conf_command_post },
#endif
ngx_null_command
@ -703,6 +717,10 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
u->pipe->input_ctx = r;
u->input_filter_init = ngx_http_uwsgi_input_filter_init;
u->input_filter = ngx_http_upstream_non_buffered_filter;
u->input_filter_ctx = r;
if (!uwcf->upstream.request_buffering
&& uwcf->upstream.pass_request_body
&& !r->headers_in.chunked)
@ -1141,6 +1159,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
r->upstream->request_bufs = cl;
}
b->flush = 1;
cl->next = NULL;
return NGX_OK;
@ -1355,6 +1374,37 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
}
static ngx_int_t
ngx_http_uwsgi_input_filter_init(void *data)
{
ngx_http_request_t *r = data;
ngx_http_upstream_t *u;
u = r->upstream;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http uwsgi filter init s:%ui l:%O",
u->headers_in.status_n, u->headers_in.content_length_n);
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
{
u->pipe->length = 0;
u->length = 0;
} else if (r->method == NGX_HTTP_HEAD) {
u->pipe->length = -1;
u->length = -1;
} else {
u->pipe->length = u->headers_in.content_length_n;
u->length = u->headers_in.content_length_n;
}
return NGX_OK;
}
static void
ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
{
@ -1463,6 +1513,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.ssl_verify = NGX_CONF_UNSET;
conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
conf->ssl_passwords = NGX_CONF_UNSET_PTR;
conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
#endif
/* "uwsgi_cyclic_temp_file" is disabled */
@ -1793,6 +1844,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
prev->ssl_certificate_key, "");
ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
prev->ssl_conf_commands, NULL);
if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
return NGX_CONF_ERROR;
}
@ -2339,6 +2393,17 @@ ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
static char *
ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#else
return NGX_CONF_OK;
#endif
}
static ngx_int_t
ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
{
@ -2416,6 +2481,12 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
return NGX_ERROR;
}
if (ngx_ssl_conf_commands(cf, uwcf->upstream.ssl, uwcf->ssl_conf_commands)
!= NGX_OK)
{
return NGX_ERROR;
}
return NGX_OK;
}

View file

@ -233,6 +233,7 @@ ngx_http_xslt_header_filter(ngx_http_request_t *r)
ngx_http_set_ctx(r, ctx, ngx_http_xslt_filter_module);
r->main_filter_need_in_memory = 1;
r->allow_ranges = 0;
return NGX_OK;
}

View file

@ -1469,14 +1469,14 @@ ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
NGX_HASH_WILDCARD_KEY);
if (rc == NGX_ERROR) {
return NGX_ERROR;
goto failed;
}
if (rc == NGX_DECLINED) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"invalid server name or wildcard \"%V\" on %V",
&name[n].name, &addr->opt.addr_text);
return NGX_ERROR;
goto failed;
}
if (rc == NGX_BUSY) {
@ -1714,7 +1714,6 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
cscf = addr->default_server;
ls->pool_size = cscf->connection_pool_size;
ls->post_accept_timeout = cscf->client_header_timeout;
clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];

View file

@ -80,6 +80,7 @@ struct ngx_http_cache_s {
ngx_str_t vary;
u_char variant[NGX_HTTP_CACHE_KEY_LEN];
size_t buffer_size;
size_t header_start;
size_t body_start;
off_t length;
@ -116,6 +117,7 @@ struct ngx_http_cache_s {
unsigned purged:1;
unsigned reading:1;
unsigned secondary:1;
unsigned update_variant:1;
unsigned background:1;
unsigned stale_updating:1;
@ -160,6 +162,7 @@ struct ngx_http_file_cache_s {
ngx_path_t *path;
off_t min_free;
off_t max_size;
size_t bsize;

View file

@ -495,6 +495,13 @@ static ngx_command_t ngx_http_core_commands[] = {
offsetof(ngx_http_core_loc_conf_t, limit_rate_after),
NULL },
{ ngx_string("keepalive_time"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, keepalive_time),
NULL },
{ ngx_string("keepalive_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
ngx_http_core_keepalive,
@ -1190,8 +1197,13 @@ ngx_http_core_auth_delay(ngx_http_request_t *r)
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"delaying unauthorized request");
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
if (r->connection->read->ready) {
ngx_post_event(r->connection->read, &ngx_posted_events);
} else {
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
r->read_event_handler = ngx_http_test_reading;
@ -1330,6 +1342,11 @@ ngx_http_update_location_config(ngx_http_request_t *r)
} else if (r->connection->requests >= clcf->keepalive_requests) {
r->keepalive = 0;
} else if (ngx_current_msec - r->connection->start_time
> clcf->keepalive_time)
{
r->keepalive = 0;
} else if (r->headers_in.msie6
&& r->method == NGX_HTTP_POST
&& (clcf->keepalive_disable
@ -1782,7 +1799,7 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
}
}
if (r->method == NGX_HTTP_HEAD || (r != r->main && val.len == 0)) {
if (r != r->main && val.len == 0) {
return ngx_http_send_header(r);
}
@ -3495,6 +3512,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
clcf->send_timeout = NGX_CONF_UNSET_MSEC;
clcf->send_lowat = NGX_CONF_UNSET_SIZE;
clcf->postpone_output = NGX_CONF_UNSET_SIZE;
clcf->keepalive_time = NGX_CONF_UNSET_MSEC;
clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
clcf->keepalive_header = NGX_CONF_UNSET;
clcf->keepalive_requests = NGX_CONF_UNSET_UINT;
@ -3733,12 +3751,14 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->limit_rate_after = prev->limit_rate_after;
}
ngx_conf_merge_msec_value(conf->keepalive_time,
prev->keepalive_time, 3600000);
ngx_conf_merge_msec_value(conf->keepalive_timeout,
prev->keepalive_timeout, 75000);
ngx_conf_merge_sec_value(conf->keepalive_header,
prev->keepalive_header, 0);
ngx_conf_merge_uint_value(conf->keepalive_requests,
prev->keepalive_requests, 100);
prev->keepalive_requests, 1000);
ngx_conf_merge_uint_value(conf->lingering_close,
prev->lingering_close, NGX_HTTP_LINGERING_ON);
ngx_conf_merge_msec_value(conf->lingering_time,
@ -4078,14 +4098,6 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
}
if (ngx_strcmp(value[n].data, "spdy") == 0) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"invalid parameter \"spdy\": "
"ngx_http_spdy_module was superseded "
"by ngx_http_v2_module");
continue;
}
if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) {
if (ngx_strcmp(&value[n].data[13], "on") == 0) {

View file

@ -359,6 +359,7 @@ struct ngx_http_core_loc_conf_s {
ngx_msec_t client_body_timeout; /* client_body_timeout */
ngx_msec_t send_timeout; /* send_timeout */
ngx_msec_t keepalive_time; /* keepalive_time */
ngx_msec_t keepalive_timeout; /* keepalive_timeout */
ngx_msec_t lingering_time; /* lingering_time */
ngx_msec_t lingering_timeout; /* lingering_timeout */

View file

@ -294,6 +294,8 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
cln->data = c;
}
c->buffer_size = c->body_start;
rc = ngx_http_file_cache_exists(cache, c);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@ -852,7 +854,7 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
if (fcn->exists || fcn->uses >= c->min_uses) {
c->exists = fcn->exists;
if (fcn->body_start) {
if (fcn->body_start && !c->update_variant) {
c->body_start = fcn->body_start;
}
@ -1230,7 +1232,7 @@ ngx_http_file_cache_reopen(ngx_http_request_t *r, ngx_http_cache_t *c)
c->secondary = 1;
c->file.name.len = 0;
c->body_start = c->buf->end - c->buf->start;
c->body_start = c->buffer_size;
ngx_memcpy(c->key, c->variant, NGX_HTTP_CACHE_KEY_LEN);
@ -1337,6 +1339,7 @@ ngx_http_file_cache_update_variant(ngx_http_request_t *r, ngx_http_cache_t *c)
ngx_shmtx_unlock(&cache->shpool->mutex);
c->file.name.len = 0;
c->update_variant = 1;
ngx_memcpy(c->key, c->main, NGX_HTTP_CACHE_KEY_LEN);
@ -1959,7 +1962,7 @@ ngx_http_file_cache_manager(void *data)
{
ngx_http_file_cache_t *cache = data;
off_t size;
off_t size, free;
time_t wait;
ngx_msec_t elapsed, next;
ngx_uint_t count, watermark;
@ -1988,7 +1991,19 @@ ngx_http_file_cache_manager(void *data)
size, count, (ngx_int_t) watermark);
if (size < cache->max_size && count < watermark) {
break;
if (!cache->min_free) {
break;
}
free = ngx_fs_available(cache->path->name.data);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"http file cache free: %O", free);
if (free > cache->min_free) {
break;
}
}
wait = ngx_http_file_cache_forced_expire(cache);
@ -2304,7 +2319,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *confp = conf;
off_t max_size;
off_t max_size, min_free;
u_char *last, *p;
time_t inactive;
ssize_t size;
@ -2341,6 +2356,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
name.len = 0;
size = 0;
max_size = NGX_MAX_OFF_T_VALUE;
min_free = 0;
value = cf->args->elts;
@ -2476,6 +2492,29 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue;
}
if (ngx_strncmp(value[i].data, "min_free=", 9) == 0) {
#if (NGX_WIN32 || NGX_HAVE_STATFS || NGX_HAVE_STATVFS)
s.len = value[i].len - 9;
s.data = value[i].data + 9;
min_free = ngx_parse_offset(&s);
if (min_free < 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid min_free value \"%V\"", &value[i]);
return NGX_CONF_ERROR;
}
#else
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"min_free is not supported "
"on this platform, ignored");
#endif
continue;
}
if (ngx_strncmp(value[i].data, "loader_files=", 13) == 0) {
loader_files = ngx_atoi(value[i].data + 13, value[i].len - 13);
@ -2607,6 +2646,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
cache->inactive = inactive;
cache->max_size = max_size;
cache->min_free = min_free;
caches = (ngx_array_t *) (confp + cmd->offset);

View file

@ -380,6 +380,12 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
r->uri_start = p;
state = sw_after_slash_in_uri;
break;
case '?':
r->uri_start = p;
r->args_start = p + 1;
r->empty_path_in_uri = 1;
state = sw_uri;
break;
case ' ':
/*
* use single "/" from request line to preserve pointers,
@ -446,6 +452,13 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
r->uri_start = p;
state = sw_after_slash_in_uri;
break;
case '?':
r->port_end = p;
r->uri_start = p;
r->args_start = p + 1;
r->empty_path_in_uri = 1;
state = sw_uri;
break;
case ' ':
r->port_end = p;
/*
@ -1287,6 +1300,10 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
r->uri_ext = NULL;
r->args_start = NULL;
if (r->empty_path_in_uri) {
*u++ = '/';
}
ch = *p++;
while (p <= r->uri_end) {

View file

@ -49,7 +49,7 @@ static void ngx_http_request_finalizer(ngx_http_request_t *r);
static void ngx_http_set_keepalive(ngx_http_request_t *r);
static void ngx_http_keepalive_handler(ngx_event_t *ev);
static void ngx_http_set_lingering_close(ngx_http_request_t *r);
static void ngx_http_set_lingering_close(ngx_connection_t *c);
static void ngx_http_lingering_close_handler(ngx_event_t *ev);
static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
@ -206,16 +206,17 @@ ngx_http_header_t ngx_http_headers_in[] = {
void
ngx_http_init_connection(ngx_connection_t *c)
{
ngx_uint_t i;
ngx_event_t *rev;
struct sockaddr_in *sin;
ngx_http_port_t *port;
ngx_http_in_addr_t *addr;
ngx_http_log_ctx_t *ctx;
ngx_http_connection_t *hc;
ngx_uint_t i;
ngx_event_t *rev;
struct sockaddr_in *sin;
ngx_http_port_t *port;
ngx_http_in_addr_t *addr;
ngx_http_log_ctx_t *ctx;
ngx_http_connection_t *hc;
ngx_http_core_srv_conf_t *cscf;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
ngx_http_in6_addr_t *addr6;
struct sockaddr_in6 *sin6;
ngx_http_in6_addr_t *addr6;
#endif
hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
@ -361,7 +362,9 @@ ngx_http_init_connection(ngx_connection_t *c)
return;
}
ngx_add_timer(rev, c->listening->post_accept_timeout);
cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
ngx_add_timer(rev, cscf->client_header_timeout);
ngx_reusable_connection(c, 1);
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
@ -431,7 +434,7 @@ ngx_http_wait_request_handler(ngx_event_t *rev)
if (n == NGX_AGAIN) {
if (!rev->timer_set) {
ngx_add_timer(rev, c->listening->post_accept_timeout);
ngx_add_timer(rev, cscf->client_header_timeout);
ngx_reusable_connection(c, 1);
}
@ -649,6 +652,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
ngx_http_connection_t *hc;
ngx_http_ssl_srv_conf_t *sscf;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
c = rev->data;
hc = c->data;
@ -680,7 +684,9 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
rev->ready = 0;
if (!rev->timer_set) {
ngx_add_timer(rev, c->listening->post_accept_timeout);
cscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
ngx_http_core_module);
ngx_add_timer(rev, cscf->client_header_timeout);
ngx_reusable_connection(c, 1);
}
@ -755,7 +761,9 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
if (rc == NGX_AGAIN) {
if (!rev->timer_set) {
ngx_add_timer(rev, c->listening->post_accept_timeout);
cscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
ngx_http_core_module);
ngx_add_timer(rev, cscf->client_header_timeout);
}
c->ssl->handler = ngx_http_ssl_handshake_handler;
@ -871,10 +879,14 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
hc = c->data;
servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
if (servername == NULL) {
return SSL_TLSEXT_ERR_OK;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"SSL server name: null");
goto done;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
@ -883,7 +895,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
host.len = ngx_strlen(servername);
if (host.len == 0) {
return SSL_TLSEXT_ERR_OK;
goto done;
}
host.data = (u_char *) servername;
@ -891,32 +903,27 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
rc = ngx_http_validate_host(&host, c->pool, 1);
if (rc == NGX_ERROR) {
*ad = SSL_AD_INTERNAL_ERROR;
return SSL_TLSEXT_ERR_ALERT_FATAL;
goto error;
}
if (rc == NGX_DECLINED) {
return SSL_TLSEXT_ERR_OK;
goto done;
}
hc = c->data;
rc = ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
NULL, &cscf);
if (rc == NGX_ERROR) {
*ad = SSL_AD_INTERNAL_ERROR;
return SSL_TLSEXT_ERR_ALERT_FATAL;
goto error;
}
if (rc == NGX_DECLINED) {
return SSL_TLSEXT_ERR_OK;
goto done;
}
hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
if (hc->ssl_servername == NULL) {
*ad = SSL_AD_INTERNAL_ERROR;
return SSL_TLSEXT_ERR_ALERT_FATAL;
goto error;
}
*hc->ssl_servername = host;
@ -932,7 +939,9 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
c->ssl->buffer_size = sscf->buffer_size;
if (sscf->ssl.ctx) {
SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) {
goto error;
}
/*
* SSL_set_SSL_CTX() only changes certs as of 1.0.0d
@ -957,7 +966,22 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
#endif
}
done:
sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
if (sscf->reject_handshake) {
c->ssl->handshake_rejected = 1;
*ad = SSL_AD_UNRECOGNIZED_NAME;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
return SSL_TLSEXT_ERR_OK;
error:
*ad = SSL_AD_INTERNAL_ERROR;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
#endif
@ -1208,9 +1232,13 @@ ngx_http_process_request_uri(ngx_http_request_t *r)
r->uri.len = r->uri_end - r->uri_start;
}
if (r->complex_uri || r->quoted_uri) {
if (r->complex_uri || r->quoted_uri || r->empty_path_in_uri) {
r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1);
if (r->empty_path_in_uri) {
r->uri.len++;
}
r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
if (r->uri.data == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return NGX_ERROR;
@ -1234,7 +1262,7 @@ ngx_http_process_request_uri(ngx_http_request_t *r)
r->unparsed_uri.len = r->uri_end - r->uri_start;
r->unparsed_uri.data = r->uri_start;
r->valid_unparsed_uri = r->space_in_uri ? 0 : 1;
r->valid_unparsed_uri = (r->space_in_uri || r->empty_path_in_uri) ? 0 : 1;
if (r->uri_ext) {
if (r->args_start) {
@ -1647,6 +1675,12 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http large header copy: %uz", r->header_in->pos - old);
if (r->header_in->pos - old > b->end - b->start) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"too large header to copy");
return NGX_ERROR;
}
new = b->start;
ngx_memcpy(new, old, r->header_in->pos - old);
@ -1993,6 +2027,7 @@ ngx_http_process_request(ngx_http_request_t *r)
if (r->http_connection->ssl) {
long rc;
X509 *cert;
const char *s;
ngx_http_ssl_srv_conf_t *sscf;
if (c->ssl == NULL) {
@ -2037,6 +2072,17 @@ ngx_http_process_request(ngx_http_request_t *r)
X509_free(cert);
}
if (ngx_ssl_ocsp_get_status(c, &s) != NGX_OK) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client SSL certificate verify error: %s", s);
ngx_ssl_remove_cached_session(c->ssl->session_ctx,
(SSL_get0_session(c->ssl->connection)));
ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
return;
}
}
}
@ -2597,11 +2643,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
ngx_del_timer(c->write);
}
if (c->read->eof) {
ngx_http_close_request(r, 0);
return;
}
ngx_http_finalize_connection(r);
}
@ -2700,6 +2741,11 @@ ngx_http_finalize_connection(ngx_http_request_t *r)
r = r->main;
if (r->connection->read->eof) {
ngx_http_close_request(r, 0);
return;
}
if (r->reading_body) {
r->keepalive = 0;
r->lingering_close = 1;
@ -2720,7 +2766,7 @@ ngx_http_finalize_connection(ngx_http_request_t *r)
|| r->header_in->pos < r->header_in->last
|| r->connection->read->ready)))
{
ngx_http_set_lingering_close(r);
ngx_http_set_lingering_close(r->connection);
return;
}
@ -2974,6 +3020,12 @@ closed:
rev->error = 1;
}
#if (NGX_HTTP_SSL)
if (c->ssl) {
c->ssl->no_send_shutdown = 1;
}
#endif
ngx_log_error(NGX_LOG_INFO, c->log, err,
"client prematurely closed connection");
@ -2999,13 +3051,6 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
if (r->discard_body) {
r->write_event_handler = ngx_http_request_empty_handler;
r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
ngx_add_timer(rev, clcf->lingering_timeout);
return;
}
c->log->action = "closing request";
hc = r->http_connection;
@ -3335,22 +3380,43 @@ ngx_http_keepalive_handler(ngx_event_t *rev)
static void
ngx_http_set_lingering_close(ngx_http_request_t *r)
ngx_http_set_lingering_close(ngx_connection_t *c)
{
ngx_event_t *rev, *wev;
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_http_core_loc_conf_t *clcf;
c = r->connection;
r = c->data;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (r->lingering_time == 0) {
r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
}
#if (NGX_HTTP_SSL)
if (c->ssl) {
ngx_int_t rc;
c->ssl->shutdown_without_free = 1;
rc = ngx_ssl_shutdown(c);
if (rc == NGX_ERROR) {
ngx_http_close_request(r, 0);
return;
}
if (rc == NGX_AGAIN) {
c->ssl->handler = ngx_http_set_lingering_close;
return;
}
}
#endif
rev = c->read;
rev->handler = ngx_http_lingering_close_handler;
r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
ngx_add_timer(rev, clcf->lingering_timeout);
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_request(r, 0);
return;
@ -3373,6 +3439,11 @@ ngx_http_set_lingering_close(ngx_http_request_t *r)
return;
}
c->close = 0;
ngx_reusable_connection(c, 1);
ngx_add_timer(rev, clcf->lingering_timeout);
if (rev->ready) {
ngx_http_lingering_close_handler(rev);
}
@ -3395,7 +3466,7 @@ ngx_http_lingering_close_handler(ngx_event_t *rev)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http lingering close handler");
if (rev->timedout) {
if (rev->timedout || c->close) {
ngx_http_close_request(r, 0);
return;
}

View file

@ -470,6 +470,9 @@ struct ngx_http_request_s {
/* URI with " " */
unsigned space_in_uri:1;
/* URI with empty path */
unsigned empty_path_in_uri:1;
unsigned invalid_header:1;
unsigned add_uri_to_alias:1;

View file

@ -12,6 +12,8 @@
static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
static ngx_int_t ngx_http_copy_pipelined_header(ngx_http_request_t *r,
ngx_buf_t *buf);
static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r);
static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
static ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r,
@ -135,8 +137,9 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
} else {
/* set rb->rest */
if (ngx_http_request_body_filter(r, NULL) != NGX_OK) {
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
rc = ngx_http_request_body_filter(r, NULL);
if (rc != NGX_OK) {
goto done;
}
}
@ -282,28 +285,12 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
for ( ;; ) {
if (rb->buf->last == rb->buf->end) {
if (rb->buf->pos != rb->buf->last) {
/* update chains */
/* pass buffer to request body filter chain */
rc = ngx_http_request_body_filter(r, NULL);
out.buf = rb->buf;
out.next = NULL;
rc = ngx_http_request_body_filter(r, &out);
if (rc != NGX_OK) {
return rc;
}
} else {
/* update chains */
rc = ngx_http_request_body_filter(r, NULL);
if (rc != NGX_OK) {
return rc;
}
if (rc != NGX_OK) {
return rc;
}
if (rb->busy != NULL) {
@ -319,6 +306,9 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
return NGX_AGAIN;
}
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"busy buffers after request body flush");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@ -355,17 +345,15 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
rb->buf->last += n;
r->request_length += n;
if (n == rest) {
/* pass buffer to request body filter chain */
/* pass buffer to request body filter chain */
out.buf = rb->buf;
out.next = NULL;
out.buf = rb->buf;
out.next = NULL;
rc = ngx_http_request_body_filter(r, &out);
rc = ngx_http_request_body_filter(r, &out);
if (rc != NGX_OK) {
return rc;
}
if (rc != NGX_OK) {
return rc;
}
if (rb->rest == 0) {
@ -386,21 +374,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
if (!c->read->ready) {
if (r->request_body_no_buffering
&& rb->buf->pos != rb->buf->last)
{
/* pass buffer to request body filter chain */
out.buf = rb->buf;
out.next = NULL;
rc = ngx_http_request_body_filter(r, &out);
if (rc != NGX_OK) {
return rc;
}
}
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
ngx_add_timer(c->read, clcf->client_body_timeout);
@ -412,6 +385,10 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
}
}
if (ngx_http_copy_pipelined_header(r, rb->buf) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (c->read->timer_set) {
ngx_del_timer(c->read);
}
@ -425,6 +402,88 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
}
static ngx_int_t
ngx_http_copy_pipelined_header(ngx_http_request_t *r, ngx_buf_t *buf)
{
size_t n;
ngx_buf_t *b;
ngx_chain_t *cl;
ngx_http_connection_t *hc;
ngx_http_core_srv_conf_t *cscf;
b = r->header_in;
n = buf->last - buf->pos;
if (buf == b || n == 0) {
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http body pipelined header: %uz", n);
/*
* if there is a pipelined request in the client body buffer,
* copy it to the r->header_in buffer if there is enough room,
* or allocate a large client header buffer
*/
if (n > (size_t) (b->end - b->last)) {
hc = r->http_connection;
if (hc->free) {
cl = hc->free;
hc->free = cl->next;
b = cl->buf;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http large header free: %p %uz",
b->pos, b->end - b->last);
} else {
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
b = ngx_create_temp_buf(r->connection->pool,
cscf->large_client_header_buffers.size);
if (b == NULL) {
return NGX_ERROR;
}
cl = ngx_alloc_chain_link(r->connection->pool);
if (cl == NULL) {
return NGX_ERROR;
}
cl->buf = b;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http large header alloc: %p %uz",
b->pos, b->end - b->last);
}
cl->next = hc->busy;
hc->busy = cl;
hc->nbusy++;
r->header_in = b;
if (n > (size_t) (b->end - b->last)) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"too large pipelined header after reading body");
return NGX_ERROR;
}
}
ngx_memcpy(b->last, buf->pos, n);
b->last += n;
r->request_length -= n;
return NGX_OK;
}
static ngx_int_t
ngx_http_write_request_body(ngx_http_request_t *r)
{
@ -619,6 +678,7 @@ ngx_http_discarded_request_body_handler(ngx_http_request_t *r)
if (rc == NGX_OK) {
r->discard_body = 0;
r->lingering_close = 0;
r->lingering_time = 0;
ngx_http_finalize_request(r, NGX_DONE);
return;
}
@ -670,8 +730,7 @@ ngx_http_read_discarded_request_body(ngx_http_request_t *r)
for ( ;; ) {
if (r->headers_in.content_length_n == 0) {
r->read_event_handler = ngx_http_block_reading;
return NGX_OK;
break;
}
if (!r->connection->read->ready) {
@ -705,15 +764,24 @@ ngx_http_read_discarded_request_body(ngx_http_request_t *r)
return rc;
}
}
if (ngx_http_copy_pipelined_header(r, &b) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
r->read_event_handler = ngx_http_block_reading;
return NGX_OK;
}
static ngx_int_t
ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
{
size_t size;
ngx_int_t rc;
ngx_http_request_body_t *rb;
size_t size;
ngx_int_t rc;
ngx_http_request_body_t *rb;
ngx_http_core_srv_conf_t *cscf;
if (r->headers_in.chunked) {
@ -768,7 +836,10 @@ ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
/* set amount of data we want to see next time */
r->headers_in.content_length_n = rb->chunked->length;
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
r->headers_in.content_length_n = ngx_max(rb->chunked->length,
(off_t) cscf->large_client_header_buffers.size);
break;
}
@ -936,6 +1007,7 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
ngx_chain_t *cl, *out, *tl, **ll;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
rb = r->request_body;
@ -949,8 +1021,10 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
r->headers_in.content_length_n = 0;
rb->rest = 3;
rb->rest = cscf->large_client_header_buffers.size;
}
out = NULL;
@ -958,6 +1032,8 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
for (cl = in; cl; cl = cl->next) {
b = NULL;
for ( ;; ) {
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
@ -992,6 +1068,29 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
}
if (b
&& rb->chunked->size <= 128
&& cl->buf->last - cl->buf->pos >= rb->chunked->size)
{
r->headers_in.content_length_n += rb->chunked->size;
if (rb->chunked->size < 8) {
while (rb->chunked->size) {
*b->last++ = *cl->buf->pos++;
rb->chunked->size--;
}
} else {
ngx_memmove(b->last, cl->buf->pos, rb->chunked->size);
b->last += rb->chunked->size;
cl->buf->pos += rb->chunked->size;
rb->chunked->size = 0;
}
continue;
}
tl = ngx_chain_get_free_buf(r->pool, &rb->free);
if (tl == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
@ -1057,7 +1156,10 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
/* set rb->rest, amount of data we want to see next time */
rb->rest = rb->chunked->length;
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
rb->rest = ngx_max(rb->chunked->length,
(off_t) cscf->large_client_header_buffers.size);
break;
}

View file

@ -575,6 +575,10 @@ ngx_http_clean_header(ngx_http_request_t *r)
r->headers_out.headers.part.next = NULL;
r->headers_out.headers.last = &r->headers_out.headers.part;
r->headers_out.trailers.part.nelts = 0;
r->headers_out.trailers.part.next = NULL;
r->headers_out.trailers.last = &r->headers_out.trailers.part;
r->headers_out.content_length_n = -1;
r->headers_out.last_modified_time = -1;
}

View file

@ -77,9 +77,6 @@ static void
static void
ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
ngx_uint_t do_write);
static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
ssize_t bytes);
#if (NGX_THREADS)
static ngx_int_t ngx_http_upstream_thread_handler(ngx_thread_task_t *task,
ngx_file_t *file);
@ -610,6 +607,17 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
u->store = u->conf->store;
if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
if (r->connection->read->ready) {
ngx_post_event(r->connection->read, &ngx_posted_events);
} else {
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
}
r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
}
@ -1919,6 +1927,7 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->keepalive = 0;
u->upgrade = 0;
u->error = 0;
ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
u->headers_in.content_length_n = -1;
@ -2053,6 +2062,10 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u,
c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
}
if (c->read->ready) {
ngx_post_event(c->read, &ngx_posted_events);
}
return;
}
@ -2475,7 +2488,7 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
#if (NGX_HTTP_CACHE)
if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
&& ((u->conf->cache_use_stale & un->mask) || r->cache->stale_error))
&& (u->conf->cache_use_stale & un->mask))
{
ngx_int_t rc;
@ -2502,6 +2515,8 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
#endif
break;
}
#if (NGX_HTTP_CACHE)
@ -3011,9 +3026,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
return;
}
if (u->peer.connection->read->ready || u->length == 0) {
ngx_http_upstream_process_non_buffered_upstream(r, u);
}
ngx_http_upstream_process_non_buffered_upstream(r, u);
}
return;
@ -3625,7 +3638,7 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
return;
}
if (upstream->read->error) {
if (upstream->read->error || u->error) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_BAD_GATEWAY);
return;
@ -3703,14 +3716,14 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
}
static ngx_int_t
ngx_int_t
ngx_http_upstream_non_buffered_filter_init(void *data)
{
return NGX_OK;
}
static ngx_int_t
ngx_int_t
ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
{
ngx_http_request_t *r = data;
@ -3721,6 +3734,13 @@ ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
u = r->upstream;
if (u->length == 0) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
return NGX_OK;
}
for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
ll = &cl->next;
}
@ -3746,6 +3766,18 @@ ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
return NGX_OK;
}
if (bytes > u->length) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
cl->buf->last = cl->buf->pos + u->length;
u->length = 0;
return NGX_OK;
}
u->length -= bytes;
return NGX_OK;

View file

@ -391,6 +391,7 @@ struct ngx_http_upstream_s {
unsigned buffering:1;
unsigned keepalive:1;
unsigned upgrade:1;
unsigned error:1;
unsigned request_sent:1;
unsigned request_body_sent:1;
@ -414,6 +415,8 @@ typedef struct {
ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r);
void ngx_http_upstream_init(ngx_http_request_t *r);
ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
ngx_int_t ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes);
ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
ngx_url_t *u, ngx_uint_t flags);
char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,

View file

@ -10,8 +10,8 @@
#include <ngx_http.h>
#define ngx_http_upstream_tries(p) ((p)->number \
+ ((p)->next ? (p)->next->number : 0))
#define ngx_http_upstream_tries(p) ((p)->tries \
+ ((p)->next ? (p)->next->tries : 0))
static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer(
@ -32,7 +32,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
ngx_http_upstream_srv_conf_t *us)
{
ngx_url_t u;
ngx_uint_t i, j, n, w;
ngx_uint_t i, j, n, w, t;
ngx_http_upstream_server_t *server;
ngx_http_upstream_rr_peer_t *peer, **peerp;
ngx_http_upstream_rr_peers_t *peers, *backup;
@ -44,6 +44,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
n = 0;
w = 0;
t = 0;
for (i = 0; i < us->servers->nelts; i++) {
if (server[i].backup) {
@ -52,6 +53,10 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
n += server[i].naddrs;
w += server[i].naddrs * server[i].weight;
if (!server[i].down) {
t += server[i].naddrs;
}
}
if (n == 0) {
@ -75,6 +80,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
peers->number = n;
peers->weighted = (w != n);
peers->total_weight = w;
peers->tries = t;
peers->name = &us->host;
n = 0;
@ -110,6 +116,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
n = 0;
w = 0;
t = 0;
for (i = 0; i < us->servers->nelts; i++) {
if (!server[i].backup) {
@ -118,6 +125,10 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
n += server[i].naddrs;
w += server[i].naddrs * server[i].weight;
if (!server[i].down) {
t += server[i].naddrs;
}
}
if (n == 0) {
@ -139,6 +150,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
backup->number = n;
backup->weighted = (w != n);
backup->total_weight = w;
backup->tries = t;
backup->name = &us->host;
n = 0;
@ -214,6 +226,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
peers->number = n;
peers->weighted = 0;
peers->total_weight = n;
peers->tries = n;
peers->name = &us->host;
peerp = &peers->peer;
@ -332,6 +345,7 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
peers->single = (ur->naddrs == 1);
peers->number = ur->naddrs;
peers->tries = ur->naddrs;
peers->name = &ur->host;
if (ur->sockaddr) {

View file

@ -68,6 +68,7 @@ struct ngx_http_upstream_rr_peers_s {
#endif
ngx_uint_t total_weight;
ngx_uint_t tries;
unsigned single:1;
unsigned weighted:1;

View file

@ -129,6 +129,8 @@ static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_connection_requests(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_connection_time(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
@ -342,6 +344,9 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("connection_requests"), NULL,
ngx_http_variable_connection_requests, 0, 0, 0 },
{ ngx_string("connection_time"), NULL, ngx_http_variable_connection_time,
0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
{ ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
0, 0, 0 },
@ -1075,7 +1080,7 @@ ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
len = name->len - (sizeof("arg_") - 1);
arg = name->data + sizeof("arg_") - 1;
if (ngx_http_arg(r, arg, len, &value) != NGX_OK) {
if (len == 0 || ngx_http_arg(r, arg, len, &value) != NGX_OK) {
v->not_found = 1;
return NGX_OK;
}
@ -1174,6 +1179,10 @@ ngx_http_variable_content_length(ngx_http_request_t *r,
v->no_cacheable = 0;
v->not_found = 0;
} else if (r->headers_in.chunked) {
v->not_found = 1;
v->no_cacheable = 1;
} else {
v->not_found = 1;
}
@ -2252,6 +2261,31 @@ ngx_http_variable_connection_requests(ngx_http_request_t *r,
}
static ngx_int_t
ngx_http_variable_connection_time(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
u_char *p;
ngx_msec_int_t ms;
p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
if (p == NULL) {
return NGX_ERROR;
}
ms = ngx_current_msec - r->connection->start_time;
ms = ngx_max(ms, 0);
v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = p;
return NGX_OK;
}
static ngx_int_t
ngx_http_variable_nginx_version(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)

View file

@ -60,6 +60,8 @@ typedef struct {
static void ngx_http_v2_read_handler(ngx_event_t *rev);
static void ngx_http_v2_write_handler(ngx_event_t *wev);
static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c);
static void ngx_http_v2_lingering_close(ngx_connection_t *c);
static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev);
static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c,
u_char *pos, u_char *end);
@ -236,6 +238,7 @@ ngx_http_v2_init(ngx_event_t *rev)
ngx_http_v2_srv_conf_t *h2scf;
ngx_http_v2_main_conf_t *h2mcf;
ngx_http_v2_connection_t *h2c;
ngx_http_core_srv_conf_t *cscf;
c = rev->data;
hc = c->data;
@ -274,7 +277,7 @@ ngx_http_v2_init(ngx_event_t *rev)
h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module);
h2c->concurrent_pushes = h2scf->concurrent_pushes;
h2c->priority_limit = h2scf->concurrent_streams;
h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100);
h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log);
if (h2c->pool == NULL) {
@ -323,7 +326,14 @@ ngx_http_v2_init(ngx_event_t *rev)
rev->handler = ngx_http_v2_read_handler;
c->write->handler = ngx_http_v2_write_handler;
if (!rev->timer_set) {
cscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
ngx_http_core_module);
ngx_add_timer(rev, cscf->client_header_timeout);
}
c->idle = 1;
ngx_reusable_connection(c, 0);
ngx_http_v2_read_handler(rev);
}
@ -360,6 +370,11 @@ ngx_http_v2_read_handler(ngx_event_t *rev)
return;
}
if (!h2c->processing && !h2c->pushing) {
ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR);
return;
}
if (!h2c->goaway) {
h2c->goaway = 1;
@ -447,14 +462,6 @@ ngx_http_v2_read_handler(ngx_event_t *rev)
h2c->blocked = 0;
if (h2c->processing || h2c->pushing) {
if (rev->timer_set) {
ngx_del_timer(rev);
}
return;
}
ngx_http_v2_handle_connection(h2c);
}
@ -473,6 +480,7 @@ ngx_http_v2_write_handler(ngx_event_t *wev)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http2 write event timed out");
c->error = 1;
c->timedout = 1;
ngx_http_v2_finalize_connection(h2c, 0);
return;
}
@ -626,9 +634,9 @@ error:
static void
ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
{
ngx_int_t rc;
ngx_connection_t *c;
ngx_http_v2_srv_conf_t *h2scf;
ngx_int_t rc;
ngx_connection_t *c;
ngx_http_core_loc_conf_t *clcf;
if (h2c->last_out || h2c->processing || h2c->pushing) {
return;
@ -661,14 +669,20 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
}
if (h2c->goaway) {
ngx_http_close_connection(c);
ngx_http_v2_lingering_close(c);
return;
}
h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
ngx_http_v2_module);
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
ngx_http_core_module);
if (!c->read->timer_set) {
ngx_add_timer(c->read, clcf->keepalive_timeout);
}
ngx_reusable_connection(c, 1);
if (h2c->state.incomplete) {
ngx_add_timer(c->read, h2scf->recv_timeout);
return;
}
@ -686,7 +700,6 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
#endif
c->destroyed = 1;
ngx_reusable_connection(c, 1);
c->write->handler = ngx_http_empty_handler;
c->read->handler = ngx_http_v2_idle_handler;
@ -694,8 +707,142 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
if (c->write->timer_set) {
ngx_del_timer(c->write);
}
}
ngx_add_timer(c->read, h2scf->idle_timeout);
static void
ngx_http_v2_lingering_close(ngx_connection_t *c)
{
ngx_event_t *rev, *wev;
ngx_http_v2_connection_t *h2c;
ngx_http_core_loc_conf_t *clcf;
h2c = c->data;
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
ngx_http_core_module);
if (clcf->lingering_close == NGX_HTTP_LINGERING_OFF) {
ngx_http_close_connection(c);
return;
}
if (h2c->lingering_time == 0) {
h2c->lingering_time = ngx_time()
+ (time_t) (clcf->lingering_time / 1000);
}
#if (NGX_HTTP_SSL)
if (c->ssl) {
ngx_int_t rc;
rc = ngx_ssl_shutdown(c);
if (rc == NGX_ERROR) {
ngx_http_close_connection(c);
return;
}
if (rc == NGX_AGAIN) {
c->ssl->handler = ngx_http_v2_lingering_close;
return;
}
}
#endif
rev = c->read;
rev->handler = ngx_http_v2_lingering_close_handler;
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
wev = c->write;
wev->handler = ngx_http_empty_handler;
if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
}
if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
ngx_connection_error(c, ngx_socket_errno,
ngx_shutdown_socket_n " failed");
ngx_http_close_connection(c);
return;
}
c->close = 0;
ngx_reusable_connection(c, 1);
ngx_add_timer(rev, clcf->lingering_timeout);
if (rev->ready) {
ngx_http_v2_lingering_close_handler(rev);
}
}
static void
ngx_http_v2_lingering_close_handler(ngx_event_t *rev)
{
ssize_t n;
ngx_msec_t timer;
ngx_connection_t *c;
ngx_http_core_loc_conf_t *clcf;
ngx_http_v2_connection_t *h2c;
u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
c = rev->data;
h2c = c->data;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http2 lingering close handler");
if (rev->timedout || c->close) {
ngx_http_close_connection(c);
return;
}
timer = (ngx_msec_t) h2c->lingering_time - (ngx_msec_t) ngx_time();
if ((ngx_msec_int_t) timer <= 0) {
ngx_http_close_connection(c);
return;
}
do {
n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n);
if (n == NGX_AGAIN) {
break;
}
if (n == NGX_ERROR || n == 0) {
ngx_http_close_connection(c);
return;
}
} while (rev->ready);
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
ngx_http_core_module);
timer *= 1000;
if (timer > clcf->lingering_timeout) {
timer = clcf->lingering_timeout;
}
ngx_add_timer(rev, timer);
}
@ -731,9 +878,8 @@ ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos,
}
if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"invalid http2 connection preface \"%*s\"",
sizeof(preface) - 1, pos);
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"invalid connection preface");
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
}
@ -754,9 +900,8 @@ ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos,
}
if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"invalid http2 connection preface \"%*s\"",
sizeof(preface) - 1, pos);
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"invalid connection preface");
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
}
@ -845,6 +990,13 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"http2 DATA frame");
if (h2c->state.sid == 0) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"client sent DATA frame with incorrect identifier");
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
}
if (size > h2c->recv_window) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"client violated connection flow control: "
@ -943,6 +1095,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
size_t size;
ngx_buf_t *buf;
ngx_int_t rc;
ngx_connection_t *fc;
ngx_http_request_t *r;
ngx_http_v2_stream_t *stream;
ngx_http_v2_srv_conf_t *h2scf;
@ -961,6 +1114,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
}
r = stream->request;
fc = r->connection;
if (r->reading_body && !r->request_body_no_buffering) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
@ -969,6 +1123,13 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
return ngx_http_v2_state_skip_padded(h2c, pos, end);
}
if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"skipping http2 DATA frame");
return ngx_http_v2_state_skip_padded(h2c, pos, end);
}
size = end - pos;
if (size >= h2c->state.length) {
@ -986,6 +1147,8 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
ngx_http_finalize_request(r, rc);
}
ngx_http_run_posted_requests(fc);
} else if (size) {
buf = stream->preread;
@ -1031,12 +1194,15 @@ static u_char *
ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos,
u_char *end)
{
size_t size;
ngx_uint_t padded, priority, depend, dependency, excl, weight;
ngx_uint_t status;
ngx_http_v2_node_t *node;
ngx_http_v2_stream_t *stream;
ngx_http_v2_srv_conf_t *h2scf;
size_t size;
ngx_uint_t padded, priority, depend, dependency, excl,
weight;
ngx_uint_t status;
ngx_http_v2_node_t *node;
ngx_http_v2_stream_t *stream;
ngx_http_v2_srv_conf_t *h2scf;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_loc_conf_t *clcf;
padded = h2c->state.flags & NGX_HTTP_V2_PADDED_FLAG;
priority = h2c->state.flags & NGX_HTTP_V2_PRIORITY_FLAG;
@ -1137,11 +1303,15 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos,
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
}
cscf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
ngx_http_core_module);
h2c->state.header_limit = cscf->large_client_header_buffers.size
* cscf->large_client_header_buffers.num;
h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
ngx_http_v2_module);
h2c->state.header_limit = h2scf->max_header_size;
if (h2c->processing >= h2scf->concurrent_streams) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"concurrent streams exceeded %ui", h2c->processing);
@ -1195,7 +1365,14 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos,
ngx_http_v2_set_dependency(h2c, node, depend, excl);
}
if (h2c->connection->requests >= h2scf->max_requests) {
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
ngx_http_core_module);
if (clcf->keepalive_timeout == 0
|| h2c->connection->requests >= clcf->keepalive_requests
|| ngx_current_msec - h2c->connection->start_time
> clcf->keepalive_time)
{
h2c->goaway = 1;
if (ngx_http_v2_send_goaway(h2c, NGX_HTTP_V2_NO_ERROR) == NGX_ERROR) {
@ -1320,10 +1497,10 @@ static u_char *
ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos,
u_char *end)
{
size_t alloc;
ngx_int_t len;
ngx_uint_t huff;
ngx_http_v2_srv_conf_t *h2scf;
size_t alloc;
ngx_int_t len;
ngx_uint_t huff;
ngx_http_core_srv_conf_t *cscf;
if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)
&& h2c->state.length < NGX_HTTP_V2_INT_OCTETS)
@ -1370,12 +1547,12 @@ ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos,
"http2 %s string, len:%i",
huff ? "encoded" : "raw", len);
h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
ngx_http_v2_module);
cscf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
ngx_http_core_module);
if ((size_t) len > h2scf->max_field_size) {
if ((size_t) len > cscf->large_client_header_buffers.size) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"client exceeded http2_max_field_size limit");
"client sent too large header field");
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM);
}
@ -1590,7 +1767,7 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
if (len > h2c->state.header_limit) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"client exceeded http2_max_header_size limit");
"client sent too large header");
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM);
}
@ -1987,6 +2164,16 @@ static u_char *
ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos,
u_char *end)
{
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"http2 SETTINGS frame");
if (h2c->state.sid) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"client sent SETTINGS frame with incorrect identifier");
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
}
if (h2c->state.flags == NGX_HTTP_V2_ACK_FLAG) {
if (h2c->state.length != 0) {
@ -2010,9 +2197,6 @@ ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos,
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"http2 SETTINGS frame");
return ngx_http_v2_state_settings_params(h2c, pos, end);
}
@ -2161,6 +2345,13 @@ ngx_http_v2_state_ping(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"http2 PING frame");
if (h2c->state.sid) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"client sent PING frame with incorrect identifier");
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
}
if (h2c->state.flags & NGX_HTTP_V2_ACK_FLAG) {
return ngx_http_v2_state_skip(h2c, pos, end);
}
@ -2202,6 +2393,13 @@ ngx_http_v2_state_goaway(ngx_http_v2_connection_t *h2c, u_char *pos,
return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_goaway);
}
if (h2c->state.sid) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"client sent GOAWAY frame with incorrect identifier");
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
}
#if (NGX_DEBUG)
h2c->state.length -= NGX_HTTP_V2_GOAWAY_SIZE;
@ -3103,6 +3301,10 @@ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push)
h2c->priority_limit += h2scf->concurrent_streams;
if (h2c->connection->read->timer_set) {
ngx_del_timer(h2c->connection->read);
}
return stream;
}
@ -4469,6 +4671,7 @@ ngx_http_v2_idle_handler(ngx_event_t *rev)
ngx_connection_t *c;
ngx_http_v2_srv_conf_t *h2scf;
ngx_http_v2_connection_t *h2c;
ngx_http_core_loc_conf_t *clcf;
c = rev->data;
h2c = c->data;
@ -4500,10 +4703,10 @@ ngx_http_v2_idle_handler(ngx_event_t *rev)
#endif
h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
ngx_http_v2_module);
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
ngx_http_core_module);
if (h2c->idle++ > 10 * h2scf->max_requests) {
if (h2c->idle++ > 10 * clcf->keepalive_requests) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"http2 flood detected");
ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR);
@ -4513,6 +4716,9 @@ ngx_http_v2_idle_handler(ngx_event_t *rev)
c->destroyed = 0;
ngx_reusable_connection(c, 0);
h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
ngx_http_v2_module);
h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log);
if (h2c->pool == NULL) {
ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
@ -4543,16 +4749,15 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
h2c->blocked = 1;
if (!c->error && !h2c->goaway) {
h2c->goaway = 1;
if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) {
(void) ngx_http_v2_send_output_queue(h2c);
}
}
c->error = 1;
if (!h2c->processing && !h2c->pushing) {
ngx_http_close_connection(c);
return;
goto done;
}
c->read->handler = ngx_http_empty_handler;
@ -4600,10 +4805,18 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
h2c->blocked = 0;
if (h2c->processing || h2c->pushing) {
c->error = 1;
return;
}
ngx_http_close_connection(c);
done:
if (c->error) {
ngx_http_close_connection(c);
return;
}
ngx_http_v2_lingering_close(c);
}

View file

@ -157,6 +157,8 @@ struct ngx_http_v2_connection_s {
ngx_uint_t last_sid;
ngx_uint_t last_push;
time_t lingering_time;
unsigned closed_nodes:8;
unsigned settings_ack:1;
unsigned table_update:1;

View file

@ -36,10 +36,31 @@ static char *ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data);
static char *ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post,
void *data);
static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data);
static char *ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_conf_deprecated_t ngx_http_v2_recv_timeout_deprecated = {
ngx_conf_deprecated, "http2_recv_timeout", "client_header_timeout"
};
static ngx_conf_deprecated_t ngx_http_v2_idle_timeout_deprecated = {
ngx_conf_deprecated, "http2_idle_timeout", "keepalive_timeout"
};
static ngx_conf_deprecated_t ngx_http_v2_max_requests_deprecated = {
ngx_conf_deprecated, "http2_max_requests", "keepalive_requests"
};
static ngx_conf_deprecated_t ngx_http_v2_max_field_size_deprecated = {
ngx_conf_deprecated, "http2_max_field_size", "large_client_header_buffers"
};
static ngx_conf_deprecated_t ngx_http_v2_max_header_size_deprecated = {
ngx_conf_deprecated, "http2_max_header_size", "large_client_header_buffers"
};
static ngx_conf_post_t ngx_http_v2_recv_buffer_size_post =
{ ngx_http_v2_recv_buffer_size };
static ngx_conf_post_t ngx_http_v2_pool_size_post =
@ -84,24 +105,24 @@ static ngx_command_t ngx_http_v2_commands[] = {
{ ngx_string("http2_max_requests"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_v2_srv_conf_t, max_requests),
NULL },
ngx_http_v2_obsolete,
0,
0,
&ngx_http_v2_max_requests_deprecated },
{ ngx_string("http2_max_field_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_v2_srv_conf_t, max_field_size),
NULL },
ngx_http_v2_obsolete,
0,
0,
&ngx_http_v2_max_field_size_deprecated },
{ ngx_string("http2_max_header_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_v2_srv_conf_t, max_header_size),
NULL },
ngx_http_v2_obsolete,
0,
0,
&ngx_http_v2_max_header_size_deprecated },
{ ngx_string("http2_body_preread_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
@ -119,17 +140,17 @@ static ngx_command_t ngx_http_v2_commands[] = {
{ ngx_string("http2_recv_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_v2_srv_conf_t, recv_timeout),
NULL },
ngx_http_v2_obsolete,
0,
0,
&ngx_http_v2_recv_timeout_deprecated },
{ ngx_string("http2_idle_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_v2_srv_conf_t, idle_timeout),
NULL },
ngx_http_v2_obsolete,
0,
0,
&ngx_http_v2_idle_timeout_deprecated },
{ ngx_string("http2_chunk_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
@ -152,62 +173,6 @@ static ngx_command_t ngx_http_v2_commands[] = {
0,
NULL },
{ ngx_string("spdy_recv_buffer_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_http_v2_spdy_deprecated,
NGX_HTTP_MAIN_CONF_OFFSET,
0,
NULL },
{ ngx_string("spdy_pool_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_v2_spdy_deprecated,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
{ ngx_string("spdy_max_concurrent_streams"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_v2_spdy_deprecated,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
{ ngx_string("spdy_streams_index_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_v2_spdy_deprecated,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
{ ngx_string("spdy_recv_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_v2_spdy_deprecated,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
{ ngx_string("spdy_keepalive_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_v2_spdy_deprecated,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
{ ngx_string("spdy_headers_comp"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_v2_spdy_deprecated,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
{ ngx_string("spdy_chunk_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_v2_spdy_deprecated,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
ngx_null_command
};
@ -353,18 +318,11 @@ ngx_http_v2_create_srv_conf(ngx_conf_t *cf)
h2scf->concurrent_streams = NGX_CONF_UNSET_UINT;
h2scf->concurrent_pushes = NGX_CONF_UNSET_UINT;
h2scf->max_requests = NGX_CONF_UNSET_UINT;
h2scf->max_field_size = NGX_CONF_UNSET_SIZE;
h2scf->max_header_size = NGX_CONF_UNSET_SIZE;
h2scf->preread_size = NGX_CONF_UNSET_SIZE;
h2scf->streams_index_mask = NGX_CONF_UNSET_UINT;
h2scf->recv_timeout = NGX_CONF_UNSET_MSEC;
h2scf->idle_timeout = NGX_CONF_UNSET_MSEC;
return h2scf;
}
@ -381,23 +339,12 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
prev->concurrent_streams, 128);
ngx_conf_merge_uint_value(conf->concurrent_pushes,
prev->concurrent_pushes, 10);
ngx_conf_merge_uint_value(conf->max_requests, prev->max_requests, 1000);
ngx_conf_merge_size_value(conf->max_field_size, prev->max_field_size,
4096);
ngx_conf_merge_size_value(conf->max_header_size, prev->max_header_size,
16384);
ngx_conf_merge_size_value(conf->preread_size, prev->preread_size, 65536);
ngx_conf_merge_uint_value(conf->streams_index_mask,
prev->streams_index_mask, 32 - 1);
ngx_conf_merge_msec_value(conf->recv_timeout,
prev->recv_timeout, 30000);
ngx_conf_merge_msec_value(conf->idle_timeout,
prev->idle_timeout, 180000);
return NGX_CONF_OK;
}
@ -600,11 +547,14 @@ ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data)
static char *
ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_conf_deprecated_t *d = cmd->post;
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"invalid directive \"%V\": ngx_http_spdy_module "
"was superseded by ngx_http_v2_module", &cmd->name);
"the \"%s\" directive is obsolete, "
"use the \"%s\" directive instead",
d->old_name, d->new_name);
return NGX_CONF_OK;
}

View file

@ -24,13 +24,8 @@ typedef struct {
size_t pool_size;
ngx_uint_t concurrent_streams;
ngx_uint_t concurrent_pushes;
ngx_uint_t max_requests;
size_t max_field_size;
size_t max_header_size;
size_t preread_size;
ngx_uint_t streams_index_mask;
ngx_msec_t recv_timeout;
ngx_msec_t idle_timeout;
} ngx_http_v2_srv_conf_t;

View file

@ -405,6 +405,7 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
#if (NGX_MAIL_SSL)
addrs[i].conf.ssl = addr[i].opt.ssl;
#endif
addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
addrs[i].conf.addr_text = addr[i].opt.addr_text;
}
@ -439,6 +440,7 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
#if (NGX_MAIL_SSL)
addrs6[i].conf.ssl = addr[i].opt.ssl;
#endif
addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
addrs6[i].conf.addr_text = addr[i].opt.addr_text;
}

View file

@ -41,6 +41,7 @@ typedef struct {
unsigned ipv6only:1;
#endif
unsigned so_keepalive:2;
unsigned proxy_protocol:1;
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
int tcp_keepidle;
int tcp_keepintvl;
@ -55,7 +56,8 @@ typedef struct {
typedef struct {
ngx_mail_conf_ctx_t *ctx;
ngx_str_t addr_text;
ngx_uint_t ssl; /* unsigned ssl:1; */
unsigned ssl:1;
unsigned proxy_protocol:1;
} ngx_mail_addr_conf_t;
typedef struct {
@ -162,10 +164,12 @@ typedef enum {
ngx_smtp_auth_external,
ngx_smtp_helo,
ngx_smtp_helo_xclient,
ngx_smtp_helo_auth,
ngx_smtp_helo_from,
ngx_smtp_xclient,
ngx_smtp_xclient_from,
ngx_smtp_xclient_helo,
ngx_smtp_xclient_auth,
ngx_smtp_from,
ngx_smtp_to
} ngx_smtp_state_e;
@ -174,6 +178,7 @@ typedef enum {
typedef struct {
ngx_peer_connection_t upstream;
ngx_buf_t *buffer;
ngx_uint_t proxy_protocol; /* unsigned proxy_protocol:1; */
} ngx_mail_proxy_ctx_t;
@ -195,6 +200,7 @@ typedef struct {
ngx_uint_t mail_state;
unsigned ssl:1;
unsigned protocol:3;
unsigned blocked:1;
unsigned quit:1;
@ -403,6 +409,7 @@ char *ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
/* STUB */
void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer);
void ngx_mail_auth_http_init(ngx_mail_session_t *s);
ngx_int_t ngx_mail_realip_handler(ngx_mail_session_t *s);
/**/

View file

@ -1135,10 +1135,10 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
size_t len;
ngx_buf_t *b;
ngx_str_t login, passwd;
ngx_connection_t *c;
#if (NGX_MAIL_SSL)
ngx_str_t verify, subject, issuer, serial, fingerprint,
raw_cert, cert;
ngx_connection_t *c;
ngx_mail_ssl_conf_t *sslcf;
#endif
ngx_mail_core_srv_conf_t *cscf;
@ -1151,9 +1151,10 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
return NULL;
}
c = s->connection;
#if (NGX_MAIL_SSL)
c = s->connection;
sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
if (c->ssl && sslcf->verify) {
@ -1224,22 +1225,49 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
+ sizeof("Client-IP: ") - 1 + s->connection->addr_text.len
+ sizeof(CRLF) - 1
+ sizeof("Client-Host: ") - 1 + s->host.len + sizeof(CRLF) - 1
+ sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + sizeof(CRLF) - 1
+ sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + sizeof(CRLF) - 1
+ sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + sizeof(CRLF) - 1
#if (NGX_MAIL_SSL)
+ sizeof("Auth-SSL: on" CRLF) - 1
+ sizeof("Auth-SSL-Verify: ") - 1 + verify.len + sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Subject: ") - 1 + subject.len + sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Issuer: ") - 1 + issuer.len + sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Serial: ") - 1 + serial.len + sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Fingerprint: ") - 1 + fingerprint.len
+ sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Cert: ") - 1 + cert.len + sizeof(CRLF) - 1
#endif
+ ahcf->header.len
+ sizeof(CRLF) - 1;
if (c->proxy_protocol) {
len += sizeof("Proxy-Protocol-Addr: ") - 1
+ c->proxy_protocol->src_addr.len + sizeof(CRLF) - 1
+ sizeof("Proxy-Protocol-Port: ") - 1
+ sizeof("65535") - 1 + sizeof(CRLF) - 1
+ sizeof("Proxy-Protocol-Server-Addr: ") - 1
+ c->proxy_protocol->dst_addr.len + sizeof(CRLF) - 1
+ sizeof("Proxy-Protocol-Server-Port: ") - 1
+ sizeof("65535") - 1 + sizeof(CRLF) - 1;
}
if (s->auth_method == NGX_MAIL_AUTH_NONE) {
len += sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len
+ sizeof(CRLF) - 1
+ sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len
+ sizeof(CRLF) - 1
+ sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len
+ sizeof(CRLF) - 1;
}
#if (NGX_MAIL_SSL)
if (c->ssl) {
len += sizeof("Auth-SSL: on" CRLF) - 1
+ sizeof("Auth-SSL-Verify: ") - 1 + verify.len
+ sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Subject: ") - 1 + subject.len
+ sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Issuer: ") - 1 + issuer.len
+ sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Serial: ") - 1 + serial.len
+ sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Fingerprint: ") - 1 + fingerprint.len
+ sizeof(CRLF) - 1
+ sizeof("Auth-SSL-Cert: ") - 1 + cert.len
+ sizeof(CRLF) - 1;
}
#endif
b = ngx_create_temp_buf(pool, len);
if (b == NULL) {
return NULL;
@ -1298,6 +1326,26 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
*b->last++ = CR; *b->last++ = LF;
}
if (c->proxy_protocol) {
b->last = ngx_cpymem(b->last, "Proxy-Protocol-Addr: ",
sizeof("Proxy-Protocol-Addr: ") - 1);
b->last = ngx_copy(b->last, c->proxy_protocol->src_addr.data,
c->proxy_protocol->src_addr.len);
*b->last++ = CR; *b->last++ = LF;
b->last = ngx_sprintf(b->last, "Proxy-Protocol-Port: %d" CRLF,
c->proxy_protocol->src_port);
b->last = ngx_cpymem(b->last, "Proxy-Protocol-Server-Addr: ",
sizeof("Proxy-Protocol-Server-Addr: ") - 1);
b->last = ngx_copy(b->last, c->proxy_protocol->dst_addr.data,
c->proxy_protocol->dst_addr.len);
*b->last++ = CR; *b->last++ = LF;
b->last = ngx_sprintf(b->last, "Proxy-Protocol-Server-Port: %d" CRLF,
c->proxy_protocol->dst_port);
}
if (s->auth_method == NGX_MAIL_AUTH_NONE) {
/* HELO, MAIL FROM, and RCPT TO can't contain CRLF, no need to escape */

View file

@ -548,6 +548,11 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
}
if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
ls->proxy_protocol = 1;
continue;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"the invalid \"%V\" parameter", &value[i]);
return NGX_CONF_ERROR;

View file

@ -11,6 +11,8 @@
#include <ngx_mail.h>
static void ngx_mail_proxy_protocol_handler(ngx_event_t *rev);
static void ngx_mail_init_session_handler(ngx_event_t *rev);
static void ngx_mail_init_session(ngx_connection_t *c);
#if (NGX_MAIL_SSL)
@ -26,6 +28,7 @@ ngx_mail_init_connection(ngx_connection_t *c)
{
size_t len;
ngx_uint_t i;
ngx_event_t *rev;
ngx_mail_port_t *port;
struct sockaddr *sa;
struct sockaddr_in *sin;
@ -129,6 +132,10 @@ ngx_mail_init_connection(ngx_connection_t *c)
s->main_conf = addr_conf->ctx->main_conf;
s->srv_conf = addr_conf->ctx->srv_conf;
#if (NGX_MAIL_SSL)
s->ssl = addr_conf->ssl;
#endif
s->addr_text = &addr_conf->addr_text;
c->data = s;
@ -159,13 +166,126 @@ ngx_mail_init_connection(ngx_connection_t *c)
c->log_error = NGX_ERROR_INFO;
rev = c->read;
rev->handler = ngx_mail_init_session_handler;
if (addr_conf->proxy_protocol) {
c->log->action = "reading PROXY protocol";
rev->handler = ngx_mail_proxy_protocol_handler;
if (!rev->ready) {
ngx_add_timer(rev, cscf->timeout);
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_mail_close_connection(c);
}
return;
}
}
if (ngx_use_accept_mutex) {
ngx_post_event(rev, &ngx_posted_events);
return;
}
rev->handler(rev);
}
static void
ngx_mail_proxy_protocol_handler(ngx_event_t *rev)
{
u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
size_t size;
ssize_t n;
ngx_err_t err;
ngx_connection_t *c;
ngx_mail_session_t *s;
ngx_mail_core_srv_conf_t *cscf;
c = rev->data;
s = c->data;
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0,
"mail PROXY protocol handler");
if (rev->timedout) {
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
c->timedout = 1;
ngx_mail_close_connection(c);
return;
}
n = recv(c->fd, (char *) buf, sizeof(buf), MSG_PEEK);
err = ngx_socket_errno;
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "recv(): %z", n);
if (n == -1) {
if (err == NGX_EAGAIN) {
rev->ready = 0;
if (!rev->timer_set) {
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
ngx_add_timer(rev, cscf->timeout);
}
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_mail_close_connection(c);
}
return;
}
ngx_connection_error(c, err, "recv() failed");
ngx_mail_close_connection(c);
return;
}
p = ngx_proxy_protocol_read(c, buf, buf + n);
if (p == NULL) {
ngx_mail_close_connection(c);
return;
}
size = p - buf;
if (c->recv(c, buf, size) != (ssize_t) size) {
ngx_mail_close_connection(c);
return;
}
if (ngx_mail_realip_handler(s) != NGX_OK) {
ngx_mail_close_connection(c);
return;
}
ngx_mail_init_session_handler(rev);
}
static void
ngx_mail_init_session_handler(ngx_event_t *rev)
{
ngx_connection_t *c;
c = rev->data;
#if (NGX_MAIL_SSL)
{
ngx_mail_session_t *s;
ngx_mail_ssl_conf_t *sslcf;
s = c->data;
sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
if (sslcf->enable || addr_conf->ssl) {
if (sslcf->enable || s->ssl) {
c->log->action = "SSL handshaking";
ngx_mail_ssl_init_connection(&sslcf->ssl, c);
@ -215,9 +335,10 @@ ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
s = c->data;
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
ngx_add_timer(c->read, cscf->timeout);
if (!c->read->timer_set) {
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
ngx_add_timer(c->read, cscf->timeout);
}
c->ssl->handler = ngx_mail_ssl_handshake_handler;
@ -338,6 +459,8 @@ ngx_mail_init_session(ngx_connection_t *c)
s = c->data;
c->log->action = "sending client greeting line";
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
s->protocol = cscf->protocol->type;
@ -722,11 +845,6 @@ ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c)
}
if (n == NGX_AGAIN) {
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return NGX_ERROR;
}
if (s->buffer->pos == s->buffer->last) {
return NGX_AGAIN;
}

View file

@ -123,6 +123,12 @@ ngx_mail_imap_auth_state(ngx_event_t *rev)
if (s->out.len) {
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap send handler busy");
s->blocked = 1;
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_close_connection(c);
return;
}
return;
}
@ -130,7 +136,16 @@ ngx_mail_imap_auth_state(ngx_event_t *rev)
rc = ngx_mail_read_command(s, c);
if (rc == NGX_AGAIN || rc == NGX_ERROR) {
if (rc == NGX_AGAIN) {
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return;
}
return;
}
if (rc == NGX_ERROR) {
return;
}
@ -293,6 +308,11 @@ ngx_mail_imap_auth_state(ngx_event_t *rev)
}
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return;
}
ngx_mail_send(c->write);
}

View file

@ -138,6 +138,12 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev)
if (s->out.len) {
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 send handler busy");
s->blocked = 1;
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_close_connection(c);
return;
}
return;
}
@ -145,7 +151,16 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev)
rc = ngx_mail_read_command(s, c);
if (rc == NGX_AGAIN || rc == NGX_ERROR) {
if (rc == NGX_AGAIN) {
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return;
}
return;
}
if (rc == NGX_ERROR) {
return;
}
@ -275,6 +290,11 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev)
s->arg_start = s->buffer->start;
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return;
}
ngx_mail_send(c->write);
}
}

View file

@ -16,6 +16,8 @@ typedef struct {
ngx_flag_t enable;
ngx_flag_t pass_error_message;
ngx_flag_t xclient;
ngx_flag_t smtp_auth;
ngx_flag_t proxy_protocol;
size_t buffer_size;
ngx_msec_t timeout;
} ngx_mail_proxy_conf_t;
@ -25,7 +27,8 @@ static void ngx_mail_proxy_block_read(ngx_event_t *rev);
static void ngx_mail_proxy_pop3_handler(ngx_event_t *rev);
static void ngx_mail_proxy_imap_handler(ngx_event_t *rev);
static void ngx_mail_proxy_smtp_handler(ngx_event_t *rev);
static void ngx_mail_proxy_dummy_handler(ngx_event_t *ev);
static void ngx_mail_proxy_write_handler(ngx_event_t *wev);
static ngx_int_t ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s);
static ngx_int_t ngx_mail_proxy_read_response(ngx_mail_session_t *s,
ngx_uint_t state);
static void ngx_mail_proxy_handler(ngx_event_t *ev);
@ -74,6 +77,20 @@ static ngx_command_t ngx_mail_proxy_commands[] = {
offsetof(ngx_mail_proxy_conf_t, xclient),
NULL },
{ ngx_string("proxy_smtp_auth"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_MAIL_SRV_CONF_OFFSET,
offsetof(ngx_mail_proxy_conf_t, smtp_auth),
NULL },
{ ngx_string("proxy_protocol"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_MAIL_SRV_CONF_OFFSET,
offsetof(ngx_mail_proxy_conf_t, proxy_protocol),
NULL },
ngx_null_command
};
@ -148,7 +165,7 @@ ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer)
p->upstream.connection->pool = s->connection->pool;
s->connection->read->handler = ngx_mail_proxy_block_read;
p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler;
p->upstream.connection->write->handler = ngx_mail_proxy_write_handler;
pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
@ -159,6 +176,8 @@ ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer)
return;
}
s->proxy->proxy_protocol = pcf->proxy_protocol;
s->out.len = 0;
switch (s->protocol) {
@ -178,6 +197,12 @@ ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer)
s->mail_state = ngx_smtp_start;
break;
}
if (rc == NGX_AGAIN) {
return;
}
ngx_mail_proxy_write_handler(p->upstream.connection->write);
}
@ -222,9 +247,25 @@ ngx_mail_proxy_pop3_handler(ngx_event_t *rev)
return;
}
if (s->proxy->proxy_protocol) {
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail proxy pop3 busy");
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return;
}
return;
}
rc = ngx_mail_proxy_read_response(s, 0);
if (rc == NGX_AGAIN) {
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return;
}
return;
}
@ -306,6 +347,11 @@ ngx_mail_proxy_pop3_handler(ngx_event_t *rev)
return;
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return;
}
s->proxy->buffer->pos = s->proxy->buffer->start;
s->proxy->buffer->last = s->proxy->buffer->start;
}
@ -335,9 +381,25 @@ ngx_mail_proxy_imap_handler(ngx_event_t *rev)
return;
}
if (s->proxy->proxy_protocol) {
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail proxy imap busy");
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return;
}
return;
}
rc = ngx_mail_proxy_read_response(s, s->mail_state);
if (rc == NGX_AGAIN) {
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return;
}
return;
}
@ -440,6 +502,11 @@ ngx_mail_proxy_imap_handler(ngx_event_t *rev)
return;
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return;
}
s->proxy->buffer->pos = s->proxy->buffer->start;
s->proxy->buffer->last = s->proxy->buffer->start;
}
@ -450,7 +517,7 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
{
u_char *p;
ngx_int_t rc;
ngx_str_t line;
ngx_str_t line, auth, encoded;
ngx_buf_t *b;
ngx_connection_t *c;
ngx_mail_session_t *s;
@ -471,9 +538,25 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
return;
}
if (s->proxy->proxy_protocol) {
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail proxy smtp busy");
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return;
}
return;
}
rc = ngx_mail_proxy_read_response(s, s->mail_state);
if (rc == NGX_AGAIN) {
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return;
}
return;
}
@ -513,6 +596,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
} else if (s->auth_method == NGX_MAIL_AUTH_NONE) {
s->mail_state = ngx_smtp_helo_from;
} else if (pcf->smtp_auth) {
s->mail_state = ngx_smtp_helo_auth;
} else {
s->mail_state = ngx_smtp_helo;
}
@ -552,7 +638,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
p = ngx_copy(p, s->connection->addr_text.data,
s->connection->addr_text.len);
if (s->login.len) {
pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
if (s->login.len && !pcf->smtp_auth) {
p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1);
p = ngx_copy(p, s->login.data, s->login.len);
}
@ -570,6 +658,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
} else if (s->auth_method == NGX_MAIL_AUTH_NONE) {
s->mail_state = ngx_smtp_xclient_from;
} else if (pcf->smtp_auth) {
s->mail_state = ngx_smtp_xclient_auth;
} else {
s->mail_state = ngx_smtp_xclient;
}
@ -595,8 +686,62 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
&s->smtp_helo)
- line.data;
s->mail_state = (s->auth_method == NGX_MAIL_AUTH_NONE) ?
ngx_smtp_helo_from : ngx_smtp_helo;
pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
if (s->auth_method == NGX_MAIL_AUTH_NONE) {
s->mail_state = ngx_smtp_helo_from;
} else if (pcf->smtp_auth) {
s->mail_state = ngx_smtp_helo_auth;
} else {
s->mail_state = ngx_smtp_helo;
}
break;
case ngx_smtp_helo_auth:
case ngx_smtp_xclient_auth:
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0,
"mail proxy send auth");
s->connection->log->action = "sending AUTH to upstream";
if (s->passwd.data == NULL) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"no password available");
ngx_mail_proxy_internal_server_error(s);
return;
}
auth.len = 1 + s->login.len + 1 + s->passwd.len;
auth.data = ngx_pnalloc(c->pool, auth.len);
if (auth.data == NULL) {
ngx_mail_proxy_internal_server_error(s);
return;
}
auth.len = ngx_sprintf(auth.data, "%Z%V%Z%V", &s->login, &s->passwd)
- auth.data;
line.len = sizeof("AUTH PLAIN " CRLF) - 1
+ ngx_base64_encoded_length(auth.len);
line.data = ngx_pnalloc(c->pool, line.len);
if (line.data == NULL) {
ngx_mail_proxy_internal_server_error(s);
return;
}
encoded.data = ngx_cpymem(line.data, "AUTH PLAIN ",
sizeof("AUTH PLAIN ") - 1);
ngx_encode_base64(&encoded, &auth);
p = encoded.data + encoded.len;
*p++ = CR; *p = LF;
s->mail_state = ngx_smtp_auth_plain;
break;
@ -643,6 +788,7 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
case ngx_smtp_helo:
case ngx_smtp_xclient:
case ngx_smtp_auth_plain:
case ngx_smtp_to:
b = s->proxy->buffer;
@ -692,25 +838,103 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
return;
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return;
}
s->proxy->buffer->pos = s->proxy->buffer->start;
s->proxy->buffer->last = s->proxy->buffer->start;
}
static void
ngx_mail_proxy_dummy_handler(ngx_event_t *wev)
ngx_mail_proxy_write_handler(ngx_event_t *wev)
{
ngx_connection_t *c;
ngx_mail_session_t *s;
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy dummy handler");
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy write handler");
c = wev->data;
s = c->data;
if (s->proxy->proxy_protocol) {
if (ngx_mail_proxy_send_proxy_protocol(s) != NGX_OK) {
return;
}
s->proxy->proxy_protocol = 0;
}
if (ngx_handle_write_event(wev, 0) != NGX_OK) {
c = wev->data;
s = c->data;
ngx_mail_proxy_close_session(s);
ngx_mail_proxy_internal_server_error(s);
}
if (c->read->ready) {
ngx_post_event(c->read, &ngx_posted_events);
}
}
static ngx_int_t
ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s)
{
u_char *p;
ssize_t n, size;
ngx_connection_t *c;
u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
s->connection->log->action = "sending PROXY protocol header to upstream";
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
"mail proxy send PROXY protocol header");
p = ngx_proxy_protocol_write(s->connection, buf,
buf + NGX_PROXY_PROTOCOL_MAX_HEADER);
if (p == NULL) {
ngx_mail_proxy_internal_server_error(s);
return NGX_ERROR;
}
c = s->proxy->upstream.connection;
size = p - buf;
n = c->send(c, buf, size);
if (n == NGX_AGAIN) {
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
ngx_mail_proxy_internal_server_error(s);
return NGX_ERROR;
}
return NGX_AGAIN;
}
if (n == NGX_ERROR) {
ngx_mail_proxy_internal_server_error(s);
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, s->connection->log, 0,
"could not send PROXY protocol header at once");
ngx_mail_proxy_internal_server_error(s);
return NGX_ERROR;
}
return NGX_OK;
}
@ -824,6 +1048,7 @@ ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state)
case ngx_smtp_helo:
case ngx_smtp_helo_xclient:
case ngx_smtp_helo_from:
case ngx_smtp_helo_auth:
case ngx_smtp_from:
if (p[0] == '2' && p[1] == '5' && p[2] == '0') {
return NGX_OK;
@ -833,11 +1058,18 @@ ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state)
case ngx_smtp_xclient:
case ngx_smtp_xclient_from:
case ngx_smtp_xclient_helo:
case ngx_smtp_xclient_auth:
if (p[0] == '2' && (p[1] == '2' || p[1] == '5') && p[2] == '0') {
return NGX_OK;
}
break;
case ngx_smtp_auth_plain:
if (p[0] == '2' && p[1] == '3' && p[2] == '5') {
return NGX_OK;
}
break;
case ngx_smtp_to:
return NGX_OK;
}
@ -1102,6 +1334,8 @@ ngx_mail_proxy_create_conf(ngx_conf_t *cf)
pcf->enable = NGX_CONF_UNSET;
pcf->pass_error_message = NGX_CONF_UNSET;
pcf->xclient = NGX_CONF_UNSET;
pcf->smtp_auth = NGX_CONF_UNSET;
pcf->proxy_protocol = NGX_CONF_UNSET;
pcf->buffer_size = NGX_CONF_UNSET_SIZE;
pcf->timeout = NGX_CONF_UNSET_MSEC;
@ -1118,6 +1352,8 @@ ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->enable, prev->enable, 0);
ngx_conf_merge_value(conf->pass_error_message, prev->pass_error_message, 0);
ngx_conf_merge_value(conf->xclient, prev->xclient, 1);
ngx_conf_merge_value(conf->smtp_auth, prev->smtp_auth, 0);
ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0);
ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
(size_t) ngx_pagesize);
ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000);

View file

@ -0,0 +1,269 @@
/*
* Copyright (C) Igor Sysoev
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_mail.h>
typedef struct {
ngx_array_t *from; /* array of ngx_cidr_t */
} ngx_mail_realip_srv_conf_t;
static ngx_int_t ngx_mail_realip_set_addr(ngx_mail_session_t *s,
ngx_addr_t *addr);
static char *ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static void *ngx_mail_realip_create_srv_conf(ngx_conf_t *cf);
static char *ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent,
void *child);
static ngx_command_t ngx_mail_realip_commands[] = {
{ ngx_string("set_real_ip_from"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
ngx_mail_realip_from,
NGX_MAIL_SRV_CONF_OFFSET,
0,
NULL },
ngx_null_command
};
static ngx_mail_module_t ngx_mail_realip_module_ctx = {
NULL, /* protocol */
NULL, /* create main configuration */
NULL, /* init main configuration */
ngx_mail_realip_create_srv_conf, /* create server configuration */
ngx_mail_realip_merge_srv_conf /* merge server configuration */
};
ngx_module_t ngx_mail_realip_module = {
NGX_MODULE_V1,
&ngx_mail_realip_module_ctx, /* module context */
ngx_mail_realip_commands, /* module directives */
NGX_MAIL_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
};
ngx_int_t
ngx_mail_realip_handler(ngx_mail_session_t *s)
{
ngx_addr_t addr;
ngx_connection_t *c;
ngx_mail_realip_srv_conf_t *rscf;
rscf = ngx_mail_get_module_srv_conf(s, ngx_mail_realip_module);
if (rscf->from == NULL) {
return NGX_OK;
}
c = s->connection;
if (c->proxy_protocol == NULL) {
return NGX_OK;
}
if (ngx_cidr_match(c->sockaddr, rscf->from) != NGX_OK) {
return NGX_OK;
}
if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol->src_addr.data,
c->proxy_protocol->src_addr.len)
!= NGX_OK)
{
return NGX_OK;
}
ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port);
return ngx_mail_realip_set_addr(s, &addr);
}
static ngx_int_t
ngx_mail_realip_set_addr(ngx_mail_session_t *s, ngx_addr_t *addr)
{
size_t len;
u_char *p;
u_char text[NGX_SOCKADDR_STRLEN];
ngx_connection_t *c;
c = s->connection;
len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text,
NGX_SOCKADDR_STRLEN, 0);
if (len == 0) {
return NGX_ERROR;
}
p = ngx_pnalloc(c->pool, len);
if (p == NULL) {
return NGX_ERROR;
}
ngx_memcpy(p, text, len);
c->sockaddr = addr->sockaddr;
c->socklen = addr->socklen;
c->addr_text.len = len;
c->addr_text.data = p;
return NGX_OK;
}
static char *
ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_mail_realip_srv_conf_t *rscf = conf;
ngx_int_t rc;
ngx_str_t *value;
ngx_url_t u;
ngx_cidr_t c, *cidr;
ngx_uint_t i;
struct sockaddr_in *sin;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
#endif
value = cf->args->elts;
if (rscf->from == NULL) {
rscf->from = ngx_array_create(cf->pool, 2,
sizeof(ngx_cidr_t));
if (rscf->from == NULL) {
return NGX_CONF_ERROR;
}
}
#if (NGX_HAVE_UNIX_DOMAIN)
if (ngx_strcmp(value[1].data, "unix:") == 0) {
cidr = ngx_array_push(rscf->from);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
cidr->family = AF_UNIX;
return NGX_CONF_OK;
}
#endif
rc = ngx_ptocidr(&value[1], &c);
if (rc != NGX_ERROR) {
if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless",
&value[1]);
}
cidr = ngx_array_push(rscf->from);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
*cidr = c;
return NGX_CONF_OK;
}
ngx_memzero(&u, sizeof(ngx_url_t));
u.host = value[1];
if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
if (u.err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"%s in set_real_ip_from \"%V\"",
u.err, &u.host);
}
return NGX_CONF_ERROR;
}
cidr = ngx_array_push_n(rscf->from, u.naddrs);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t));
for (i = 0; i < u.naddrs; i++) {
cidr[i].family = u.addrs[i].sockaddr->sa_family;
switch (cidr[i].family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr;
cidr[i].u.in6.addr = sin6->sin6_addr;
ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16);
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) u.addrs[i].sockaddr;
cidr[i].u.in.addr = sin->sin_addr.s_addr;
cidr[i].u.in.mask = 0xffffffff;
break;
}
}
return NGX_CONF_OK;
}
static void *
ngx_mail_realip_create_srv_conf(ngx_conf_t *cf)
{
ngx_mail_realip_srv_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_realip_srv_conf_t));
if (conf == NULL) {
return NULL;
}
/*
* set by ngx_pcalloc():
*
* conf->from = NULL;
*/
return conf;
}
static char *
ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_mail_realip_srv_conf_t *prev = parent;
ngx_mail_realip_srv_conf_t *conf = child;
if (conf->from == NULL) {
conf->from = prev->from;
}
return NGX_CONF_OK;
}

View file

@ -449,6 +449,12 @@ ngx_mail_smtp_auth_state(ngx_event_t *rev)
if (s->out.len) {
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp send handler busy");
s->blocked = 1;
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_close_connection(c);
return;
}
return;
}
@ -456,7 +462,16 @@ ngx_mail_smtp_auth_state(ngx_event_t *rev)
rc = ngx_mail_read_command(s, c);
if (rc == NGX_AGAIN || rc == NGX_ERROR) {
if (rc == NGX_AGAIN) {
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return;
}
return;
}
if (rc == NGX_ERROR) {
return;
}
@ -568,6 +583,11 @@ ngx_mail_smtp_auth_state(ngx_event_t *rev)
s->arg_start = s->buffer->pos;
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return;
}
ngx_mail_send(c->write);
}
}

View file

@ -26,6 +26,9 @@ static char *ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post,
void *data);
static ngx_conf_enum_t ngx_mail_starttls_state[] = {
{ ngx_string("off"), NGX_MAIL_STARTTLS_OFF },
@ -61,6 +64,10 @@ static ngx_conf_deprecated_t ngx_mail_ssl_deprecated = {
};
static ngx_conf_post_t ngx_mail_ssl_conf_command_post =
{ ngx_mail_ssl_conf_command_check };
static ngx_command_t ngx_mail_ssl_commands[] = {
{ ngx_string("ssl"),
@ -196,6 +203,13 @@ static ngx_command_t ngx_mail_ssl_commands[] = {
offsetof(ngx_mail_ssl_conf_t, crl),
NULL },
{ ngx_string("ssl_conf_command"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE2,
ngx_conf_set_keyval_slot,
NGX_MAIL_SRV_CONF_OFFSET,
offsetof(ngx_mail_ssl_conf_t, conf_commands),
&ngx_mail_ssl_conf_command_post },
ngx_null_command
};
@ -259,6 +273,7 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf)
scf->certificates = NGX_CONF_UNSET_PTR;
scf->certificate_keys = NGX_CONF_UNSET_PTR;
scf->passwords = NGX_CONF_UNSET_PTR;
scf->conf_commands = NGX_CONF_UNSET_PTR;
scf->prefer_server_ciphers = NGX_CONF_UNSET;
scf->verify = NGX_CONF_UNSET_UINT;
scf->verify_depth = NGX_CONF_UNSET_UINT;
@ -316,6 +331,8 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);
conf->ssl.log = cf->log;
@ -461,6 +478,10 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
@ -654,3 +675,14 @@ invalid:
return NGX_CONF_ERROR;
}
static char *
ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#else
return NGX_CONF_OK;
#endif
}

View file

@ -48,6 +48,7 @@ typedef struct {
ngx_str_t ciphers;
ngx_array_t *passwords;
ngx_array_t *conf_commands;
ngx_shm_zone_t *shm_zone;

View file

@ -14,6 +14,8 @@ extern "C" {
#include <ngx_mail_pop3_module.h>
#include <ngx_mail_imap_module.h>
#include <ngx_mail_smtp_module.h>
#include <ngx_stream.h>
}
// nginx header files should go before other, because they define 64-bit off_t

View file

@ -9,6 +9,49 @@
#include <ngx_core.h>
static ngx_str_t ngx_unknown_error = ngx_string("Unknown error");
#if (NGX_HAVE_STRERRORDESC_NP)
/*
* The strerrordesc_np() function, introduced in glibc 2.32, is
* async-signal-safe. This makes it possible to use it directly,
* without copying error messages.
*/
u_char *
ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
{
size_t len;
const char *msg;
msg = strerrordesc_np(err);
if (msg == NULL) {
msg = (char *) ngx_unknown_error.data;
len = ngx_unknown_error.len;
} else {
len = ngx_strlen(msg);
}
size = ngx_min(size, len);
return ngx_cpymem(errstr, msg, size);
}
ngx_int_t
ngx_strerror_init(void)
{
return NGX_OK;
}
#else
/*
* The strerror() messages are copied because:
*
@ -26,7 +69,8 @@
static ngx_str_t *ngx_sys_errlist;
static ngx_str_t ngx_unknown_error = ngx_string("Unknown error");
static ngx_err_t ngx_first_error;
static ngx_err_t ngx_last_error;
u_char *
@ -34,8 +78,13 @@ ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
{
ngx_str_t *msg;
msg = ((ngx_uint_t) err < NGX_SYS_NERR) ? &ngx_sys_errlist[err]:
&ngx_unknown_error;
if (err >= ngx_first_error && err < ngx_last_error) {
msg = &ngx_sys_errlist[err - ngx_first_error];
} else {
msg = &ngx_unknown_error;
}
size = ngx_min(size, msg->len);
return ngx_cpymem(errstr, msg->data, size);
@ -50,20 +99,92 @@ ngx_strerror_init(void)
size_t len;
ngx_err_t err;
#if (NGX_SYS_NERR)
ngx_first_error = 0;
ngx_last_error = NGX_SYS_NERR;
#elif (EPERM > 1000 && EPERM < 0x7fffffff - 1000)
/*
* If number of errors is not known, and EPERM error code has large
* but reasonable value, guess possible error codes based on the error
* messages returned by strerror(), starting from EPERM. Notably,
* this covers GNU/Hurd, where errors start at 0x40000001.
*/
for (err = EPERM; err > EPERM - 1000; err--) {
ngx_set_errno(0);
msg = strerror(err);
if (errno == EINVAL
|| msg == NULL
|| strncmp(msg, "Unknown error", 13) == 0)
{
continue;
}
ngx_first_error = err;
}
for (err = EPERM; err < EPERM + 1000; err++) {
ngx_set_errno(0);
msg = strerror(err);
if (errno == EINVAL
|| msg == NULL
|| strncmp(msg, "Unknown error", 13) == 0)
{
continue;
}
ngx_last_error = err + 1;
}
#else
/*
* If number of errors is not known, guess it based on the error
* messages returned by strerror().
*/
ngx_first_error = 0;
for (err = 0; err < 1000; err++) {
ngx_set_errno(0);
msg = strerror(err);
if (errno == EINVAL
|| msg == NULL
|| strncmp(msg, "Unknown error", 13) == 0)
{
continue;
}
ngx_last_error = err + 1;
}
#endif
/*
* ngx_strerror() is not ready to work at this stage, therefore,
* malloc() is used and possible errors are logged using strerror().
*/
len = NGX_SYS_NERR * sizeof(ngx_str_t);
len = (ngx_last_error - ngx_first_error) * sizeof(ngx_str_t);
ngx_sys_errlist = malloc(len);
if (ngx_sys_errlist == NULL) {
goto failed;
}
for (err = 0; err < NGX_SYS_NERR; err++) {
for (err = ngx_first_error; err < ngx_last_error; err++) {
msg = strerror(err);
if (msg == NULL) {
ngx_sys_errlist[err - ngx_first_error] = ngx_unknown_error;
continue;
}
len = ngx_strlen(msg);
p = malloc(len);
@ -72,8 +193,8 @@ ngx_strerror_init(void)
}
ngx_memcpy(p, msg, len);
ngx_sys_errlist[err].len = len;
ngx_sys_errlist[err].data = p;
ngx_sys_errlist[err - ngx_first_error].len = len;
ngx_sys_errlist[err - ngx_first_error].data = p;
}
return NGX_OK;
@ -85,3 +206,5 @@ failed:
return NGX_ERROR;
}
#endif

View file

@ -875,9 +875,28 @@ ngx_fs_bsize(u_char *name)
return 512;
}
#if (NGX_LINUX)
if ((size_t) fs.f_bsize > ngx_pagesize) {
return 512;
}
#endif
return (size_t) fs.f_bsize;
}
off_t
ngx_fs_available(u_char *name)
{
struct statfs fs;
if (statfs((char *) name, &fs) == -1) {
return NGX_MAX_OFF_T_VALUE;
}
return (off_t) fs.f_bavail * fs.f_bsize;
}
#elif (NGX_HAVE_STATVFS)
size_t
@ -893,9 +912,28 @@ ngx_fs_bsize(u_char *name)
return 512;
}
#if (NGX_LINUX)
if ((size_t) fs.f_frsize > ngx_pagesize) {
return 512;
}
#endif
return (size_t) fs.f_frsize;
}
off_t
ngx_fs_available(u_char *name)
{
struct statvfs fs;
if (statvfs((char *) name, &fs) == -1) {
return NGX_MAX_OFF_T_VALUE;
}
return (off_t) fs.f_bavail * fs.f_frsize;
}
#else
size_t
@ -904,4 +942,11 @@ ngx_fs_bsize(u_char *name)
return 512;
}
off_t
ngx_fs_available(u_char *name)
{
return NGX_MAX_OFF_T_VALUE;
}
#endif

View file

@ -185,7 +185,10 @@ ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s);
#define ngx_is_exec(sb) (((sb)->st_mode & S_IXUSR) == S_IXUSR)
#define ngx_file_access(sb) ((sb)->st_mode & 0777)
#define ngx_file_size(sb) (sb)->st_size
#define ngx_file_fs_size(sb) ngx_max((sb)->st_size, (sb)->st_blocks * 512)
#define ngx_file_fs_size(sb) \
(((sb)->st_blocks * 512 > (sb)->st_size \
&& (sb)->st_blocks * 512 < (sb)->st_size + 8 * (sb)->st_blksize) \
? (sb)->st_blocks * 512 : (sb)->st_size)
#define ngx_file_mtime(sb) (sb)->st_mtime
#define ngx_file_uniq(sb) (sb)->st_ino
@ -346,6 +349,7 @@ ngx_int_t ngx_directio_off(ngx_fd_t fd);
#endif
size_t ngx_fs_bsize(u_char *name);
off_t ngx_fs_available(u_char *name);
#if (NGX_HAVE_OPENAT)

View file

@ -15,7 +15,7 @@ static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
ngx_int_t type);
static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle,
ngx_uint_t respawn);
static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch);
static void ngx_pass_open_channel(ngx_cycle_t *cycle);
static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo);
static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle);
static void ngx_master_process_exit(ngx_cycle_t *cycle);
@ -77,12 +77,11 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
u_char *p;
size_t size;
ngx_int_t i;
ngx_uint_t n, sigio;
ngx_uint_t sigio;
sigset_t set;
struct itimerval itv;
ngx_uint_t live;
ngx_msec_t delay;
ngx_listening_t *ls;
ngx_core_conf_t *ccf;
sigemptyset(&set);
@ -204,16 +203,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
if (ngx_quit) {
ngx_signal_worker_processes(cycle,
ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
ls = cycle->listening.elts;
for (n = 0; n < cycle->listening.nelts; n++) {
if (ngx_close_socket(ls[n].fd) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls[n].addr_text);
}
}
cycle->listening.nelts = 0;
ngx_close_listening_sockets(cycle);
continue;
}
@ -345,25 +335,16 @@ ngx_single_process_cycle(ngx_cycle_t *cycle)
static void
ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
{
ngx_int_t i;
ngx_channel_t ch;
ngx_int_t i;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
ngx_memzero(&ch, sizeof(ngx_channel_t));
ch.command = NGX_CMD_OPEN_CHANNEL;
for (i = 0; i < n; i++) {
ngx_spawn_process(cycle, ngx_worker_process_cycle,
(void *) (intptr_t) i, "worker process", type);
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];
ngx_pass_open_channel(cycle, &ch);
ngx_pass_open_channel(cycle);
}
}
@ -371,9 +352,8 @@ ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
static void
ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
{
ngx_uint_t i, manager, loader;
ngx_path_t **path;
ngx_channel_t ch;
ngx_uint_t i, manager, loader;
ngx_path_t **path;
manager = 0;
loader = 0;
@ -398,14 +378,7 @@ ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
&ngx_cache_manager_ctx, "cache manager process",
respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN);
ngx_memzero(&ch, sizeof(ngx_channel_t));
ch.command = NGX_CMD_OPEN_CHANNEL;
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];
ngx_pass_open_channel(cycle, &ch);
ngx_pass_open_channel(cycle);
if (loader == 0) {
return;
@ -415,19 +388,20 @@ ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
&ngx_cache_loader_ctx, "cache loader process",
respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN);
ch.command = NGX_CMD_OPEN_CHANNEL;
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];
ngx_pass_open_channel(cycle, &ch);
ngx_pass_open_channel(cycle);
}
static void
ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch)
ngx_pass_open_channel(ngx_cycle_t *cycle)
{
ngx_int_t i;
ngx_int_t i;
ngx_channel_t ch;
ch.command = NGX_CMD_OPEN_CHANNEL;
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];
for (i = 0; i < ngx_last_process; i++) {
@ -440,14 +414,14 @@ ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch)
ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"pass channel s:%i pid:%P fd:%d to s:%i pid:%P fd:%d",
ch->slot, ch->pid, ch->fd,
ch.slot, ch.pid, ch.fd,
i, ngx_processes[i].pid,
ngx_processes[i].channel[0]);
/* TODO: NGX_AGAIN */
ngx_write_channel(ngx_processes[i].channel[0],
ch, sizeof(ngx_channel_t), cycle->log);
&ch, sizeof(ngx_channel_t), cycle->log);
}
}
@ -631,12 +605,7 @@ ngx_reap_children(ngx_cycle_t *cycle)
}
ch.command = NGX_CMD_OPEN_CHANNEL;
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];
ngx_pass_open_channel(cycle, &ch);
ngx_pass_open_channel(cycle);
live = 1;

View file

@ -189,6 +189,13 @@ ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, ngx_log_t *log)
return cl;
}
/* zero-sized datagram; pretend to have at least 1 iov */
if (n == 0) {
iov = &vec->iovs[n++];
iov->iov_base = NULL;
iov->iov_len = 0;
}
vec->count = n;
vec->size = total;

View file

@ -49,6 +49,7 @@ typedef struct {
ngx_str_t ssl_certificate;
ngx_str_t ssl_certificate_key;
ngx_array_t *ssl_passwords;
ngx_array_t *ssl_conf_commands;
ngx_ssl_t *ssl;
#endif
@ -94,6 +95,8 @@ static char *ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd,
static ngx_int_t ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s);
static char *ngx_stream_proxy_ssl_password_file(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
static char *ngx_stream_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post,
void *data);
static void ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s);
static void ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc);
static void ngx_stream_proxy_ssl_save_session(ngx_connection_t *c);
@ -112,6 +115,9 @@ static ngx_conf_bitmask_t ngx_stream_proxy_ssl_protocols[] = {
{ ngx_null_string, 0 }
};
static ngx_conf_post_t ngx_stream_proxy_ssl_conf_command_post =
{ ngx_stream_proxy_ssl_conf_command_check };
#endif
@ -331,6 +337,13 @@ static ngx_command_t ngx_stream_proxy_commands[] = {
0,
NULL },
{ ngx_string("proxy_ssl_conf_command"),
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2,
ngx_conf_set_keyval_slot,
NGX_STREAM_SRV_CONF_OFFSET,
offsetof(ngx_stream_proxy_srv_conf_t, ssl_conf_commands),
&ngx_stream_proxy_ssl_conf_command_post },
#endif
ngx_null_command
@ -839,7 +852,7 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
u->upstream_buf.last = p;
}
if (c->buffer && c->buffer->pos < c->buffer->last) {
if (c->buffer && c->buffer->pos <= c->buffer->last) {
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
"stream proxy add preread buffer: %uz",
c->buffer->last - c->buffer->pos);
@ -853,6 +866,7 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
*cl->buf = *c->buffer;
cl->buf->tag = (ngx_buf_tag_t) &ngx_stream_proxy_module;
cl->buf->temporary = (cl->buf->pos == cl->buf->last) ? 0 : 1;
cl->buf->flush = 1;
cl->next = u->upstream_out;
@ -1007,6 +1021,17 @@ ngx_stream_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
}
static char *
ngx_stream_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#else
return NGX_CONF_OK;
#endif
}
static void
ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
{
@ -1984,6 +2009,7 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
conf->ssl_verify = NGX_CONF_UNSET;
conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
conf->ssl_passwords = NGX_CONF_UNSET_PTR;
conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
#endif
return conf;
@ -2071,6 +2097,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
prev->ssl_conf_commands, NULL);
if (conf->ssl_enable && ngx_stream_proxy_set_ssl(cf, conf) != NGX_OK) {
return NGX_CONF_ERROR;
}
@ -2155,6 +2184,12 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf)
return NGX_ERROR;
}
if (ngx_ssl_conf_commands(cf, pscf->ssl, pscf->ssl_conf_commands)
!= NGX_OK)
{
return NGX_ERROR;
}
return NGX_OK;
}

View file

@ -0,0 +1,226 @@
/*
* Copyright (C) Pavel Pautov
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_stream.h>
typedef struct {
ngx_int_t index;
ngx_stream_set_variable_pt set_handler;
uintptr_t data;
ngx_stream_complex_value_t value;
} ngx_stream_set_cmd_t;
typedef struct {
ngx_array_t commands;
} ngx_stream_set_srv_conf_t;
static ngx_int_t ngx_stream_set_handler(ngx_stream_session_t *s);
static ngx_int_t ngx_stream_set_var(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_stream_set_init(ngx_conf_t *cf);
static void *ngx_stream_set_create_srv_conf(ngx_conf_t *cf);
static char *ngx_stream_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_stream_set_commands[] = {
{ ngx_string("set"),
NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2,
ngx_stream_set,
NGX_STREAM_SRV_CONF_OFFSET,
0,
NULL },
ngx_null_command
};
static ngx_stream_module_t ngx_stream_set_module_ctx = {
NULL, /* preconfiguration */
ngx_stream_set_init, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
ngx_stream_set_create_srv_conf, /* create server configuration */
NULL /* merge server configuration */
};
ngx_module_t ngx_stream_set_module = {
NGX_MODULE_V1,
&ngx_stream_set_module_ctx, /* module context */
ngx_stream_set_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_set_handler(ngx_stream_session_t *s)
{
ngx_str_t str;
ngx_uint_t i;
ngx_stream_set_cmd_t *cmds;
ngx_stream_set_srv_conf_t *scf;
ngx_stream_variable_value_t vv;
scf = ngx_stream_get_module_srv_conf(s, ngx_stream_set_module);
cmds = scf->commands.elts;
vv = ngx_stream_variable_null_value;
for (i = 0; i < scf->commands.nelts; i++) {
if (ngx_stream_complex_value(s, &cmds[i].value, &str) != NGX_OK) {
return NGX_ERROR;
}
if (cmds[i].set_handler != NULL) {
vv.len = str.len;
vv.data = str.data;
cmds[i].set_handler(s, &vv, cmds[i].data);
} else {
s->variables[cmds[i].index].len = str.len;
s->variables[cmds[i].index].valid = 1;
s->variables[cmds[i].index].no_cacheable = 0;
s->variables[cmds[i].index].not_found = 0;
s->variables[cmds[i].index].data = str.data;
}
}
return NGX_DECLINED;
}
static ngx_int_t
ngx_stream_set_var(ngx_stream_session_t *s, ngx_stream_variable_value_t *v,
uintptr_t data)
{
*v = ngx_stream_variable_null_value;
return NGX_OK;
}
static ngx_int_t
ngx_stream_set_init(ngx_conf_t *cf)
{
ngx_stream_handler_pt *h;
ngx_stream_core_main_conf_t *cmcf;
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
h = ngx_array_push(&cmcf->phases[NGX_STREAM_PREACCESS_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_stream_set_handler;
return NGX_OK;
}
static void *
ngx_stream_set_create_srv_conf(ngx_conf_t *cf)
{
ngx_stream_set_srv_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_set_srv_conf_t));
if (conf == NULL) {
return NULL;
}
/*
* set by ngx_pcalloc():
*
* conf->commands = { NULL };
*/
return conf;
}
static char *
ngx_stream_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_stream_set_srv_conf_t *scf = conf;
ngx_str_t *args;
ngx_int_t index;
ngx_stream_set_cmd_t *set_cmd;
ngx_stream_variable_t *v;
ngx_stream_compile_complex_value_t ccv;
args = cf->args->elts;
if (args[1].data[0] != '$') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid variable name \"%V\"", &args[1]);
return NGX_CONF_ERROR;
}
args[1].len--;
args[1].data++;
v = ngx_stream_add_variable(cf, &args[1],
NGX_STREAM_VAR_CHANGEABLE|NGX_STREAM_VAR_WEAK);
if (v == NULL) {
return NGX_CONF_ERROR;
}
index = ngx_stream_get_variable_index(cf, &args[1]);
if (index == NGX_ERROR) {
return NGX_CONF_ERROR;
}
if (v->get_handler == NULL) {
v->get_handler = ngx_stream_set_var;
}
if (scf->commands.elts == NULL) {
if (ngx_array_init(&scf->commands, cf->pool, 1,
sizeof(ngx_stream_set_cmd_t))
!= NGX_OK)
{
return NGX_CONF_ERROR;
}
}
set_cmd = ngx_array_push(&scf->commands);
if (set_cmd == NULL) {
return NGX_CONF_ERROR;
}
set_cmd->index = index;
set_cmd->set_handler = v->set_handler;
set_cmd->data = v->data;
ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
ccv.cf = cf;
ccv.value = &args[2];
ccv.complex_value = &set_cmd->value;
if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}

View file

@ -45,6 +45,10 @@ static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post,
void *data);
static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf);
@ -68,6 +72,10 @@ static ngx_conf_enum_t ngx_stream_ssl_verify[] = {
};
static ngx_conf_post_t ngx_stream_ssl_conf_command_post =
{ ngx_stream_ssl_conf_command_check };
static ngx_command_t ngx_stream_ssl_commands[] = {
{ ngx_string("ssl_handshake_timeout"),
@ -196,6 +204,13 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
offsetof(ngx_stream_ssl_conf_t, crl),
NULL },
{ ngx_string("ssl_conf_command"),
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2,
ngx_conf_set_keyval_slot,
NGX_STREAM_SRV_CONF_OFFSET,
offsetof(ngx_stream_ssl_conf_t, conf_commands),
&ngx_stream_ssl_conf_command_post },
ngx_null_command
};
@ -595,6 +610,7 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf)
scf->certificates = NGX_CONF_UNSET_PTR;
scf->certificate_keys = NGX_CONF_UNSET_PTR;
scf->passwords = NGX_CONF_UNSET_PTR;
scf->conf_commands = NGX_CONF_UNSET_PTR;
scf->prefer_server_ciphers = NGX_CONF_UNSET;
scf->verify = NGX_CONF_UNSET_UINT;
scf->verify_depth = NGX_CONF_UNSET_UINT;
@ -650,6 +666,8 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);
conf->ssl.log = cf->log;
@ -811,6 +829,10 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
@ -1034,6 +1056,17 @@ invalid:
}
static char *
ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#else
return NGX_CONF_OK;
#endif
}
static ngx_int_t
ngx_stream_ssl_init(ngx_conf_t *cf)
{

View file

@ -46,6 +46,7 @@ typedef struct {
ngx_str_t ciphers;
ngx_array_t *passwords;
ngx_array_t *conf_commands;
ngx_shm_zone_t *shm_zone;

View file

@ -10,8 +10,8 @@
#include <ngx_stream.h>
#define ngx_stream_upstream_tries(p) ((p)->number \
+ ((p)->next ? (p)->next->number : 0))
#define ngx_stream_upstream_tries(p) ((p)->tries \
+ ((p)->next ? (p)->next->tries : 0))
static ngx_stream_upstream_rr_peer_t *ngx_stream_upstream_get_peer(
@ -38,7 +38,7 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
ngx_stream_upstream_srv_conf_t *us)
{
ngx_url_t u;
ngx_uint_t i, j, n, w;
ngx_uint_t i, j, n, w, t;
ngx_stream_upstream_server_t *server;
ngx_stream_upstream_rr_peer_t *peer, **peerp;
ngx_stream_upstream_rr_peers_t *peers, *backup;
@ -50,6 +50,7 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
n = 0;
w = 0;
t = 0;
for (i = 0; i < us->servers->nelts; i++) {
if (server[i].backup) {
@ -58,6 +59,10 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
n += server[i].naddrs;
w += server[i].naddrs * server[i].weight;
if (!server[i].down) {
t += server[i].naddrs;
}
}
if (n == 0) {
@ -81,6 +86,7 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
peers->number = n;
peers->weighted = (w != n);
peers->total_weight = w;
peers->tries = t;
peers->name = &us->host;
n = 0;
@ -116,6 +122,7 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
n = 0;
w = 0;
t = 0;
for (i = 0; i < us->servers->nelts; i++) {
if (!server[i].backup) {
@ -124,6 +131,10 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
n += server[i].naddrs;
w += server[i].naddrs * server[i].weight;
if (!server[i].down) {
t += server[i].naddrs;
}
}
if (n == 0) {
@ -145,6 +156,7 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
backup->number = n;
backup->weighted = (w != n);
backup->total_weight = w;
backup->tries = t;
backup->name = &us->host;
n = 0;
@ -220,6 +232,7 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
peers->number = n;
peers->weighted = 0;
peers->total_weight = n;
peers->tries = n;
peers->name = &us->host;
peerp = &peers->peer;
@ -342,6 +355,7 @@ ngx_stream_upstream_create_round_robin_peer(ngx_stream_session_t *s,
peers->single = (ur->naddrs == 1);
peers->number = ur->naddrs;
peers->tries = ur->naddrs;
peers->name = &ur->host;
if (ur->sockaddr) {

View file

@ -66,6 +66,7 @@ struct ngx_stream_upstream_rr_peers_s {
#endif
ngx_uint_t total_weight;
ngx_uint_t tries;
unsigned single:1;
unsigned weighted:1;

View file

@ -234,7 +234,8 @@ ngx_stream_write_filter(ngx_stream_session_t *s, ngx_chain_t *in,
if (size == 0
&& !(c->buffered & NGX_LOWLEVEL_BUFFERED)
&& !(last && c->need_last_buf))
&& !(last && c->need_last_buf)
&& !(c->type == SOCK_DGRAM && flush))
{
if (last || flush || sync) {
for (cl = *out; cl; /* void */) {