summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2008-03-12 13:27:41 +0000
committerJonathan Kolb <jon@b0g.us>2008-03-12 13:27:41 +0000
commitae7289106bcf680f72d586197d099b0dff29a753 (patch)
tree870ec711f5b30298f9935aca0d272a659ef015b4
parent2ef4ceba25a749bcf048b03863a4424ff64eb466 (diff)
downloadnginx-ae7289106bcf680f72d586197d099b0dff29a753.tar.gz
Changes with nginx 0.6.27 12 Mar 2008v0.6.27
*) Change: now by default the rtsig method is not built on Linux 2.6.18+. *) Change: now a request method is not changed while redirection to a named location via an "error_page" directive. *) Feature: the "resolver" and "resolver_timeout" directives in SMTP proxy. *) Feature: the "post_action" directive supports named locations. *) Bugfix: a segmentation fault occurred in worker process, if a request was redirected from proxy, FastCGI, or memcached location to static named locations. *) Bugfix: browsers did not repeat SSL handshake if there is no valid client certificate in first handshake. Thanks to Alexander V. Inyukhin. *) Bugfix: if response code 495-497 was redirected via an "error_page" directive without code change, then nginx tried to allocate too many memory. *) Bugfix: memory leak in long-lived non buffered connections. *) Bugfix: memory leak in resolver. *) Bugfix: a segmentation fault occurred in worker process, if a request was redirected from proxy, FastCGI, or memcached location to static named locations. *) Bugfix: in the $proxy_host and $proxy_port variables caching. Thanks to Sergey Bochenkov. *) Bugfix: a "proxy_pass" directive with variables used incorrectly the same port as in another "proxy_pass" directive with the same host name and without variables. Thanks to Sergey Bochenkov. *) Bugfix: an alert "sendmsg() failed (9: Bad file descriptor)" on some 64-bit platforms while reconfiguration. *) Bugfix: a segmentation fault occurred in worker process, if empty stub block was used second time in SSI. *) Bugfix: in copying URI part contained escaped symbols into arguments.
-rw-r--r--CHANGES50
-rw-r--r--CHANGES.ru56
-rw-r--r--auto/os/linux10
-rw-r--r--conf/nginx.conf1
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_conf_file.c7
-rw-r--r--src/core/ngx_connection.c32
-rw-r--r--src/core/ngx_file.c2
-rw-r--r--src/core/ngx_file.h2
-rw-r--r--src/core/ngx_resolver.c124
-rw-r--r--src/core/ngx_resolver.h3
-rw-r--r--src/event/ngx_event.h1
-rw-r--r--src/event/ngx_event_openssl.c13
-rw-r--r--src/event/ngx_event_openssl.h1
-rw-r--r--src/http/modules/ngx_http_dav_module.c2
-rw-r--r--src/http/modules/ngx_http_memcached_module.c1
-rw-r--r--src/http/modules/ngx_http_proxy_module.c5
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c1
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/modules/perl/nginx.xs13
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c54
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.h4
-rw-r--r--src/http/ngx_http.c2
-rw-r--r--src/http/ngx_http_core_module.c41
-rw-r--r--src/http/ngx_http_request.c15
-rw-r--r--src/http/ngx_http_script.c25
-rw-r--r--src/http/ngx_http_script.h2
-rw-r--r--src/http/ngx_http_special_response.c7
-rw-r--r--src/http/ngx_http_upstream.c7
-rw-r--r--src/http/ngx_http_upstream.h1
-rw-r--r--src/mail/ngx_mail.h6
-rw-r--r--src/mail/ngx_mail_core_module.c67
-rw-r--r--src/mail/ngx_mail_proxy_module.c15
-rw-r--r--src/mail/ngx_mail_smtp_handler.c172
-rw-r--r--src/os/unix/ngx_channel.c4
-rw-r--r--src/os/unix/ngx_freebsd_config.h7
-rw-r--r--src/os/unix/ngx_linux_init.c15
-rw-r--r--src/os/unix/ngx_posix_config.h7
-rw-r--r--src/os/unix/ngx_process_cycle.c15
39 files changed, 688 insertions, 106 deletions
diff --git a/CHANGES b/CHANGES
index 1b24142ac..236f430e1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,54 @@
+Changes with nginx 0.6.27 12 Mar 2008
+
+ *) Change: now by default the rtsig method is not built on
+ Linux 2.6.18+.
+
+ *) Change: now a request method is not changed while redirection to a
+ named location via an "error_page" directive.
+
+ *) Feature: the "resolver" and "resolver_timeout" directives in SMTP
+ proxy.
+
+ *) Feature: the "post_action" directive supports named locations.
+
+ *) Bugfix: a segmentation fault occurred in worker process, if a
+ request was redirected from proxy, FastCGI, or memcached location to
+ static named locations.
+
+ *) Bugfix: browsers did not repeat SSL handshake if there is no valid
+ client certificate in first handshake.
+ Thanks to Alexander V. Inyukhin.
+
+ *) Bugfix: if response code 495-497 was redirected via an "error_page"
+ directive without code change, then nginx tried to allocate too many
+ memory.
+
+ *) Bugfix: memory leak in long-lived non buffered connections.
+
+ *) Bugfix: memory leak in resolver.
+
+ *) Bugfix: a segmentation fault occurred in worker process, if a
+ request was redirected from proxy, FastCGI, or memcached location to
+ static named locations.
+
+ *) Bugfix: in the $proxy_host and $proxy_port variables caching.
+ Thanks to Sergey Bochenkov.
+
+ *) Bugfix: a "proxy_pass" directive with variables used incorrectly the
+ same port as in another "proxy_pass" directive with the same host
+ name and without variables.
+ Thanks to Sergey Bochenkov.
+
+ *) Bugfix: an alert "sendmsg() failed (9: Bad file descriptor)" on some
+ 64-bit platforms while reconfiguration.
+
+ *) Bugfix: a segmentation fault occurred in worker process, if empty
+ stub block was used second time in SSI.
+
+ *) Bugfix: in copying URI part contained escaped symbols into arguments.
+
+
Changes with nginx 0.6.26 11 Feb 2008
*) Bugfix: the "proxy_store" and "fastcgi_store" directives did not
diff --git a/CHANGES.ru b/CHANGES.ru
index f819f8262..fc3567f93 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,60 @@
+Изменения в nginx 0.6.27 12.03.2008
+
+ *) Изменение: теперь на Linux 2.6.18+ по умолчанию не собирается метод
+ rtsig.
+
+ *) Изменение: теперь при перенаправлении запроса в именованный location
+ с помощью директивы error_page метод запроса не изменяется.
+
+ *) Добавление: директивы resolver и resolver_timeout в SMTP
+ прокси-сервере.
+
+ *) Добавление: директива post_action поддерживает именованные
+ location'ы.
+
+ *) Исправление: при перенаправлении запроса из location'а c
+ обработчиком proxy, FastCGI или memcached в именованный location со
+ статическим обработчиком в рабочем процессе происходил segmentation
+ fault.
+
+ *) Исправление: браузеры не повторяли SSL handshake, если при первом
+ handshake не оказалось правильного клиентского сертификата.
+ Спасибо Александру Инюхину.
+
+ *) Исправление: при перенаправлении ошибок 495-497 с помощью директивы
+ error_page без изменения кода ошибки nginx пытался выделить очень
+ много памяти.
+
+ *) Исправление: утечки памяти в долгоживущих небуфферизированных
+ соединениях.
+
+ *) Исправление: утечки памяти в resolver'е.
+
+ *) Исправление: при перенаправлении запроса из location'а c
+ обработчиком proxy в другой location с обработчиком proxy в рабочем
+ процессе происходил segmentation fault.
+
+ *) Исправление: ошибки в кэшировании переменных $proxy_host и
+ $proxy_port.
+ Спасибо Сергею Боченкову.
+
+ *) Исправление: директива proxy_pass с переменными использовала порт,
+ описанной в другой директиве proxy_pass без переменных, но с таким
+ же именем хоста.
+ Спасибо Сергею Боченкову.
+
+ *) Исправление: во время переконфигурации на некоторых 64-битном
+ платформах в лог записывался alert "sendmsg() failed (9: Bad file
+ descriptor)".
+
+ *) Исправление: при повторном использовании в SSI пустого block'а в
+ качестве заглушки в рабочем процессе происходил segmentation fault.
+
+ *) Исправление: ошибки при копировании части URI, содержащего
+ экранированные символы, в аргументы.
+
+
Изменения в nginx 0.6.26 11.02.2008
*) Исправление: директивы proxy_store и fastcgi_store не проверяли
diff --git a/auto/os/linux b/auto/os/linux
index abf61f14a..3c2c8419d 100644
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -16,18 +16,18 @@ CC_AUX_FLAGS="$CC_AUX_FLAGS -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
# Linux kernel version
-version=`grep "#define LINUX_VERSION_CODE" /usr/include/linux/version.h \
- | sed -e 's/^.* \(.*\)$/\1/'`
+version=$((`uname -r \
+ | sed 's/^\([^.]*\)\.\([^.]*\)\.\([^.-]*\).*/\1*256*256+\2*256+\3/'`))
version=${version:-0}
-# enable the rt signals on Linux 2.2.19 and onward
+# enable the rt signals on Linux between 2.2.19 and 2.6.17
-if [ $version -ge 131609 -o $EVENT_RTSIG = YES ]; then
+if [ \( $version -ge 131603 -a $version -lt 132626 \) -o $EVENT_RTSIG = YES ]
+then
echo " + rt signals found"
have=NGX_HAVE_RTSIG . auto/have
- have=NGX_HAVE_POLL . auto/have
EVENT_MODULES="$EVENT_MODULES $RTSIG_MODULE"
CORE_SRCS="$CORE_SRCS $RTSIG_SRCS"
EVENT_FOUND=YES
diff --git a/conf/nginx.conf b/conf/nginx.conf
index 75dad9342..315245d14 100644
--- a/conf/nginx.conf
+++ b/conf/nginx.conf
@@ -63,6 +63,7 @@ http {
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
+ # root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
diff --git a/src/core/nginx.h b/src/core/nginx.h
index c62b15bd4..0645cc444 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.6.26"
+#define NGINX_VERSION "0.6.27"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index f00cf019b..54769fbe0 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -633,7 +633,7 @@ ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *rv;
ngx_int_t n;
- ngx_str_t *value, file;
+ ngx_str_t *value, file, name;
ngx_glob_t gl;
value = cf->args->elts;
@@ -659,12 +659,15 @@ ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
rv = NGX_CONF_OK;
for ( ;; ) {
- n = ngx_read_glob(&gl, &file);
+ n = ngx_read_glob(&gl, &name);
if (n != NGX_OK) {
break;
}
+ file.len = name.len++;
+ file.data = ngx_pstrdup(cf->pool, &name);
+
ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
rv = ngx_conf_parse(cf, &file);
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index b31daaa57..d22a08ed2 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -661,6 +661,8 @@ ngx_free_connection(ngx_connection_t *c)
void
ngx_close_connection(ngx_connection_t *c)
{
+ ngx_err_t err;
+ ngx_uint_t log_error, level;
ngx_socket_t fd;
if (c->fd == -1) {
@@ -733,6 +735,8 @@ ngx_close_connection(ngx_connection_t *c)
#endif
+ log_error = c->log_error;
+
ngx_free_connection(c);
fd = c->fd;
@@ -740,9 +744,31 @@ ngx_close_connection(ngx_connection_t *c)
if (ngx_close_socket(fd) == -1) {
+ err = ngx_socket_errno;
+
+ if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) {
+
+ switch (log_error) {
+
+ case NGX_ERROR_INFO:
+ level = NGX_LOG_INFO;
+ break;
+
+ case NGX_ERROR_ERR:
+ level = NGX_LOG_ERR;
+ break;
+
+ default:
+ level = NGX_LOG_CRIT;
+ }
+
+ } else {
+ level = NGX_LOG_CRIT;
+ }
+
/* we use ngx_cycle->log because c->log was in c->pool */
- ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
+ ngx_log_error(level, ngx_cycle->log, err,
ngx_close_socket_n " %d failed", fd);
}
}
@@ -784,11 +810,11 @@ ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
break;
default:
- level = NGX_LOG_CRIT;
+ level = NGX_LOG_ALERT;
}
} else {
- level = NGX_LOG_CRIT;
+ level = NGX_LOG_ALERT;
}
ngx_log_error(level, c->log, err, text);
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 37d12e1fd..b98108abe 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -554,7 +554,7 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext)
failed:
- if (ext->delete) {
+ if (ext->delete_file) {
if (ngx_delete_file(src->data) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
ngx_delete_file_n " \"%s\" failed", src->data);
diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h
index a5637bbc5..a254ca753 100644
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -63,7 +63,7 @@ typedef struct {
ngx_fd_t fd;
unsigned create_path:1;
- unsigned delete:1;
+ unsigned delete_file:1;
ngx_log_t *log;
} ngx_ext_rename_file_t;
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index ade500533..bbc40bae0 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -50,6 +50,8 @@ typedef struct {
ngx_int_t ngx_udp_connect(ngx_udp_connection_t *uc);
+static void ngx_resolver_cleanup(void *data);
+static void ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree);
static ngx_int_t ngx_resolve_name_locked(ngx_resolver_t *r,
ngx_resolver_ctx_t *ctx);
static void ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree,
@@ -81,6 +83,7 @@ static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name,
static void ngx_resolver_timeout_handler(ngx_event_t *ev);
static void ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn);
static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size);
+static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
static void ngx_resolver_free(ngx_resolver_t *r, void *p);
static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
@@ -89,17 +92,27 @@ static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
/* STUB: ngx_peer_addr_t * */
ngx_resolver_t *
-ngx_resolver_create(ngx_peer_addr_t *addr, ngx_log_t *log)
+ngx_resolver_create(ngx_conf_t *cf, ngx_peer_addr_t *addr)
{
ngx_resolver_t *r;
+ ngx_pool_cleanup_t *cln;
ngx_udp_connection_t *uc;
- r = ngx_calloc(sizeof(ngx_resolver_t), log);
+ cln = ngx_pool_cleanup_add(cf->pool, 0);
+ if (cln == NULL) {
+ return NULL;
+ }
+
+ cln->handler = ngx_resolver_cleanup;
+
+ r = ngx_calloc(sizeof(ngx_resolver_t), cf->log);
if (r == NULL) {
return NULL;
}
- r->event = ngx_calloc(sizeof(ngx_event_t), log);
+ cln->data = r;
+
+ r->event = ngx_calloc(sizeof(ngx_event_t), cf->log);
if (r->event == NULL) {
return NULL;
}
@@ -118,18 +131,18 @@ ngx_resolver_create(ngx_peer_addr_t *addr, ngx_log_t *log)
r->event->handler = ngx_resolver_resend_handler;
r->event->data = r;
- r->event->log = log;
+ r->event->log = cf->cycle->new_log;
r->ident = -1;
r->resend_timeout = 5;
r->expire = 30;
r->valid = 300;
- r->log = log;
+ r->log = cf->cycle->new_log;
r->log_level = NGX_LOG_ALERT;
if (addr) {
- uc = ngx_calloc(sizeof(ngx_udp_connection_t), log);
+ uc = ngx_calloc(sizeof(ngx_udp_connection_t), cf->log);
if (uc == NULL) {
return NULL;
}
@@ -139,13 +152,72 @@ ngx_resolver_create(ngx_peer_addr_t *addr, ngx_log_t *log)
uc->sockaddr = addr->sockaddr;
uc->socklen = addr->socklen;
uc->server = addr->name;
- uc->log = log;
+ uc->log = cf->cycle->new_log;
}
return r;
}
+static void
+ngx_resolver_cleanup(void *data)
+{
+ ngx_resolver_t *r = data;
+
+ if (r) {
+ ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
+ "cleanup resolver");
+
+ ngx_resolver_cleanup_tree(r, &r->name_rbtree);
+
+ ngx_resolver_cleanup_tree(r, &r->addr_rbtree);
+
+ if (r->event) {
+ ngx_free(r->event);
+ }
+
+ if (r->udp_connection) {
+ if (r->udp_connection->connection) {
+ ngx_close_connection(r->udp_connection->connection);
+ }
+
+ ngx_free(r->udp_connection);
+ }
+
+ ngx_free(r);
+ }
+}
+
+
+static void
+ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree)
+{
+ ngx_resolver_ctx_t *ctx, *next;
+ ngx_resolver_node_t *rn;
+
+ while (tree->root != tree->sentinel) {
+
+ rn = (ngx_resolver_node_t *) ngx_rbtree_min(tree->root, tree->sentinel);
+
+ ngx_queue_remove(&rn->queue);
+
+ for (ctx = rn->waiting; ctx; ctx = next) {
+ next = ctx->next;
+
+ if (ctx->event) {
+ ngx_resolver_free(r, ctx->event);
+ }
+
+ ngx_resolver_free(r, ctx);
+ }
+
+ ngx_rbtree_delete(tree, &rn->node);
+
+ ngx_resolver_free_node(r, rn);
+ }
+}
+
+
ngx_resolver_ctx_t *
ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
{
@@ -211,14 +283,13 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx)
return NGX_OK;
}
- /* lock alloc mutex */
+ /* NGX_ERROR */
if (ctx->event) {
- ngx_resolver_free_locked(r, ctx->event);
- ctx->event = NULL;
+ ngx_resolver_free(r, ctx->event);
}
- /* unlock alloc mutex */
+ ngx_resolver_free(r, ctx);
return NGX_ERROR;
}
@@ -279,7 +350,15 @@ done:
/* unlock name mutex */
- ngx_resolver_free(r, ctx);
+ /* lock alloc mutex */
+
+ if (ctx->event) {
+ ngx_resolver_free_locked(r, ctx->event);
+ }
+
+ ngx_resolver_free_locked(r, ctx);
+
+ /* unlock alloc mutex */
}
@@ -572,15 +651,11 @@ failed:
/* unlock addr mutex */
- /* lock alloc mutex */
-
if (ctx->event) {
- ngx_resolver_free_locked(r, ctx->event);
+ ngx_resolver_free(r, ctx->event);
}
- ngx_resolver_free_locked(r, ctx);
-
- /* unlock alloc mutex */
+ ngx_resolver_free(r, ctx);
return NGX_ERROR;
}
@@ -639,7 +714,15 @@ done:
/* unlock addr mutex */
- ngx_resolver_free(r, ctx);
+ /* lock alloc mutex */
+
+ if (ctx->event) {
+ ngx_resolver_free_locked(r, ctx->event);
+ }
+
+ ngx_resolver_free_locked(r, ctx);
+
+ /* unlock alloc mutex */
}
@@ -695,6 +778,7 @@ ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
uc->connection->data = r;
uc->connection->read->handler = ngx_resolver_read_response;
+ uc->connection->read->resolver = 1;
}
n = ngx_send(uc->connection, rn->query, rn->qlen);
@@ -1813,7 +1897,7 @@ ngx_resolver_alloc(ngx_resolver_t *r, size_t size)
}
-void *
+static void *
ngx_resolver_calloc(ngx_resolver_t *r, size_t size)
{
u_char *p;
diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h
index b1b8ede2c..8f8b06055 100644
--- a/src/core/ngx_resolver.h
+++ b/src/core/ngx_resolver.h
@@ -131,14 +131,13 @@ struct ngx_resolver_ctx_s {
};
-ngx_resolver_t *ngx_resolver_create(ngx_peer_addr_t *addr, ngx_log_t *log);
+ngx_resolver_t *ngx_resolver_create(ngx_conf_t *cf, ngx_peer_addr_t *addr);
ngx_resolver_ctx_t *ngx_resolve_start(ngx_resolver_t *r,
ngx_resolver_ctx_t *temp);
ngx_int_t ngx_resolve_name(ngx_resolver_ctx_t *ctx);
void ngx_resolve_name_done(ngx_resolver_ctx_t *ctx);
ngx_int_t ngx_resolve_addr(ngx_resolver_ctx_t *ctx);
void ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx);
-void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
char *ngx_resolver_strerror(ngx_int_t err);
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index a96b8bab9..33c8cdc2d 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -136,6 +136,7 @@ struct ngx_event_s {
/* to test on worker exit */
unsigned channel:1;
+ unsigned resolver:1;
#if (NGX_THREADS)
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 8ba3e8e39..9f964dabe 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1552,6 +1552,15 @@ done:
}
+void
+ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
+{
+ SSL_CTX_remove_session(ssl, sess);
+
+ ngx_ssl_remove_session(ssl, sess);
+}
+
+
static void
ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
{
@@ -1567,6 +1576,10 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
+ if (shm_zone == NULL) {
+ return;
+ }
+
cache = shm_zone->data;
id = sess->session_id;
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index e027dde86..b9771c121 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -105,6 +105,7 @@ ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
ngx_uint_t flags);
+void ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
ngx_int_t ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session);
#define ngx_ssl_get_session(c) SSL_get1_session(c->ssl->connection)
#define ngx_ssl_free_session SSL_SESSION_free
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index e597923e0..b1e0831b1 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -248,7 +248,7 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
ext.access = dlcf->access;
ext.time = -1;
ext.create_path = dlcf->create_full_put_path;
- ext.delete = 1;
+ ext.delete_file = 1;
ext.log = r->connection->log;
if (r->headers_in.date) {
diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c
index 1f156cd42..64592f3ae 100644
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -461,6 +461,7 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
cl->buf->pos = last;
b->last += bytes;
cl->buf->last = b->last;
+ cl->buf->tag = u->output.tag;
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
"memcached filter bytes:%z size:%z length:%z rest:%z",
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index d3f4c60ea..c559d3165 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -444,10 +444,10 @@ static ngx_str_t ngx_http_proxy_hide_headers[] = {
static ngx_http_variable_t ngx_http_proxy_vars[] = {
{ ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0,
- NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOHASH, 0 },
+ NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
{ ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0,
- NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOHASH, 0 },
+ NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
{ ngx_string("proxy_add_x_forwarded_for"), NULL,
ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
@@ -611,6 +611,7 @@ ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
r->upstream->resolved->host = u.host;
r->upstream->resolved->port = (in_port_t) (u.no_port ? u.default_port:
u.port);
+ r->upstream->resolved->default_port = u.default_port;
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 5e17cb59f..1d7730d56 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -1983,6 +1983,7 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
if (bl[i].count++) {
+ out = NULL;
ll = &out;
for (tl = bl[i].bufs; tl; tl = tl->next) {
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index f20be2e6e..cd25685a2 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.6.26';
+our $VERSION = '0.6.27';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index c665446e5..4524a8c40 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -933,19 +933,24 @@ void
sleep(r, sleep, next)
CODE:
- dXSTARG;
ngx_http_request_t *r;
+ ngx_msec_t sleep;
ngx_http_perl_ctx_t *ctx;
ngx_http_perl_set_request(r);
+ sleep = (ngx_msec_t) SvIV(ST(1));
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "perl sleep: %M", sleep);
+
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
- ctx->sleep = SvIV(ST(1));
ctx->next = SvRV(ST(2));
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl sleep: %d", ctx->sleep);
+ ngx_add_timer(r->connection->write, sleep);
+
+ r->write_event_handler = ngx_http_perl_sleep_handler;
void
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 07dad1c81..d8425b98f 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -41,7 +41,6 @@ static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);
#endif
-static void ngx_http_perl_sleep_handler(ngx_http_request_t *r);
static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf,
ngx_http_perl_main_conf_t *pmcf);
static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf,
@@ -49,7 +48,7 @@ static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf,
static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires,
ngx_log_t *log);
static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
- HV *nginx, SV *sub, ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv);
+ HV *nginx, SV *sub, SV **args, ngx_str_t *handler, ngx_str_t *rv);
static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);
static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf);
@@ -252,12 +251,6 @@ ngx_http_perl_handle_request(ngx_http_request_t *r)
ctx->filename.data = NULL;
ctx->redirect_uri.len = 0;
- if (ctx->sleep) {
- ngx_add_timer(r->connection->write, (ngx_msec_t) ctx->sleep);
- r->write_event_handler = ngx_http_perl_sleep_handler;
- ctx->sleep = 0;
- }
-
if (ctx->done || ctx->next) {
return;
}
@@ -276,7 +269,7 @@ ngx_http_perl_handle_request(ngx_http_request_t *r)
}
-static void
+void
ngx_http_perl_sleep_handler(ngx_http_request_t *r)
{
ngx_event_t *wev;
@@ -364,9 +357,10 @@ static ngx_int_t
ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
ngx_str_t **params)
{
- SV *sv;
+ SV *sv, **asv;
ngx_int_t rc;
- ngx_str_t *handler;
+ ngx_str_t *handler, **args;
+ ngx_uint_t i;
ngx_http_perl_ctx_t *ctx;
ngx_http_perl_main_conf_t *pmcf;
@@ -416,9 +410,31 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
sv = newSVpvn((char *) handler->data, handler->len);
- rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv,
- &params[NGX_HTTP_PERL_SSI_ARG],
- handler, NULL);
+ args = &params[NGX_HTTP_PERL_SSI_ARG];
+
+ if (args) {
+
+ for (i = 0; args[i]; i++) { /* void */ }
+
+ asv = ngx_pcalloc(r->pool, (i + 1) * sizeof(SV *));
+
+ if (asv == NULL) {
+ SvREFCNT_dec(sv);
+ return NGX_ERROR;
+ }
+
+ asv[0] = (SV *) i;
+
+ for (i = 0; args[i]; i++) {
+ asv[i + 1] = newSVpvn((char *) args[i]->data, args[i]->len);
+ }
+
+ } else {
+ asv = NULL;
+ }
+
+ rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv, asv, handler,
+ NULL);
SvREFCNT_dec(sv);
@@ -629,7 +645,7 @@ ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log)
static ngx_int_t
ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub,
- ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv)
+ SV **args, ngx_str_t *handler, ngx_str_t *rv)
{
SV *sv;
int n, status;
@@ -652,12 +668,10 @@ ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub,
XPUSHs(sv);
if (args) {
- for (i = 0; args[i]; i++) { /* void */ }
-
- EXTEND(sp, (int) i);
+ EXTEND(sp, (int) args[0]);
- for (i = 0; args[i]; i++) {
- PUSHs(sv_2mortal(newSVpvn((char *) args[i]->data, args[i]->len)));
+ for (i = 1; i <= (ngx_uint_t) args[0]; i++) {
+ PUSHs(sv_2mortal(args[i]));
}
}
diff --git a/src/http/modules/perl/ngx_http_perl_module.h b/src/http/modules/perl/ngx_http_perl_module.h
index 6ae63e820..23969bcd4 100644
--- a/src/http/modules/perl/ngx_http_perl_module.h
+++ b/src/http/modules/perl/ngx_http_perl_module.h
@@ -25,9 +25,8 @@ typedef struct {
ngx_str_t redirect_args;
SV *next;
- int sleep;
- ngx_uint_t done; /* unsigned done:1; */
+ ngx_uint_t done; /* unsigned done:1; */
ngx_array_t *variables; /* array of ngx_http_perl_var_t */
@@ -61,6 +60,7 @@ extern void boot_DynaLoader(pTHX_ CV* cv);
void ngx_http_perl_handle_request(ngx_http_request_t *r);
+void ngx_http_perl_sleep_handler(ngx_http_request_t *r);
#endif /* _NGX_HTTP_PERL_MODULE_H_INCLUDED_ */
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index e3583a4f8..22866639a 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -551,7 +551,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (in_addr[a].default_server) {
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
"the duplicate default server in %s:%ui",
- &lscf[l].file_name, lscf[l].line);
+ lscf[l].file_name, lscf[l].line);
return NGX_CONF_ERROR;
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 8a9a4769d..08c1d352b 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1916,7 +1916,7 @@ ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
"named location: %V \"%V?%V\"", name, &r->uri, &r->args);
r->internal = 1;
-
+ r->content_handler = NULL;
r->loc_conf = clcfp[i]->loc_conf;
ngx_http_update_location_config(r);
@@ -1924,6 +1924,7 @@ ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
r->phase_handler = cmcf->phase_engine.location_rewrite_index;
+
ngx_http_core_run_phases(r);
return NGX_DONE;
@@ -2907,14 +2908,21 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
prev->resolver_timeout, 30000);
if (conf->resolver == NULL) {
- conf->resolver = prev->resolver;
- if (conf->resolver == NULL) {
- conf->resolver = ngx_resolver_create(NULL, cf->cycle->new_log);
- if (conf->resolver == NULL) {
+ if (prev->resolver == NULL) {
+
+ /*
+ * create dummy resolver in http {} context
+ * to inherit it in all servers
+ */
+
+ prev->resolver = ngx_resolver_create(cf, NULL);
+ if (prev->resolver == NULL) {
return NGX_CONF_ERROR;
}
}
+
+ conf->resolver = prev->resolver;
}
ngx_conf_merge_path_value(conf->client_body_temp_path,
@@ -3551,7 +3559,22 @@ ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- err->overwrite = (overwrite >= 0) ? overwrite : err->status;
+ if (overwrite >= 0) {
+ err->overwrite = overwrite;
+
+ } else {
+ switch (err->status) {
+ case NGX_HTTP_TO_HTTPS:
+ case NGX_HTTPS_CERT_ERROR:
+ case NGX_HTTPS_NO_CERT:
+ err->overwrite = NGX_HTTP_BAD_REQUEST;
+ break;
+
+ default:
+ err->overwrite = err->status;
+ break;
+ }
+ }
err->uri = uri;
err->uri_lengths = uri_lengths;
@@ -3716,6 +3739,10 @@ ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_url_t u;
ngx_str_t *value;
+ if (clcf->resolver) {
+ return "is duplicate";
+ }
+
value = cf->args->elts;
ngx_memzero(&u, sizeof(ngx_url_t));
@@ -3728,7 +3755,7 @@ ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- clcf->resolver = ngx_resolver_create(&u.addrs[0], cf->cycle->new_log);
+ clcf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
if (clcf->resolver == NULL) {
return NGX_OK;
}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 4d21a002a..d87f77d54 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1430,6 +1430,10 @@ ngx_http_process_request(ngx_http_request_t *r)
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client SSL certificate verify error: (%l:%s)",
rc, X509_verify_cert_error_string(rc));
+
+ ngx_ssl_remove_cached_session(sscf->ssl.ctx,
+ (SSL_get0_session(c->ssl->connection)));
+
ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
return;
}
@@ -1439,6 +1443,10 @@ ngx_http_process_request(ngx_http_request_t *r)
{
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent no required SSL certificate");
+
+ ngx_ssl_remove_cached_session(sscf->ssl.ctx,
+ (SSL_get0_session(c->ssl->connection)));
+
ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
return;
}
@@ -2448,7 +2456,12 @@ ngx_http_post_action(ngx_http_request_t *r)
r->read_event_handler = ngx_http_block_reading;
- ngx_http_internal_redirect(r, &clcf->post_action, NULL);
+ if (clcf->post_action.data[0] == '/') {
+ ngx_http_internal_redirect(r, &clcf->post_action, NULL);
+
+ } else {
+ ngx_http_named_location(r, &clcf->post_action);
+ }
return NGX_OK;
}
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 0af34e32f..acd867fdb 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -221,6 +221,14 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc)
sc->args = 1;
sc->compile_args = 0;
+ code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t),
+ NULL);
+ if (code == NULL) {
+ return NGX_ERROR;
+ }
+
+ *code = (uintptr_t) ngx_http_script_mark_args_code;
+
code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
&sc->main);
if (code == NULL) {
@@ -504,7 +512,7 @@ ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
e->ip += sizeof(ngx_http_script_copy_capture_code_t);
if (code->n < e->ncaptures) {
- if ((e->args || e->quote)
+ if ((e->is_args || e->quote)
&& (e->request->quoted_uri || e->request->plus_in_uri))
{
return e->captures[code->n + 1] - e->captures[code->n]
@@ -531,7 +539,7 @@ ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
e->ip += sizeof(ngx_http_script_copy_capture_code_t);
if (code->n < e->ncaptures) {
- if ((e->args || e->quote)
+ if ((e->is_args || e->quote)
&& (e->request->quoted_uri || e->request->plus_in_uri))
{
e->pos = (u_char *) ngx_escape_uri(e->pos,
@@ -550,6 +558,16 @@ ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
}
+size_t
+ngx_http_script_mark_args_code(ngx_http_script_engine_t *e)
+{
+ e->is_args = 1;
+ e->ip += sizeof(uintptr_t);
+
+ return 1;
+}
+
+
void
ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
{
@@ -700,7 +718,7 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
le.ncaptures = e->ncaptures;
le.quote = code->redirect;
- len = 1; /* reserve 1 byte for possible "?" */
+ len = 0;
while (*(uintptr_t *) le.ip) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
@@ -708,6 +726,7 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
}
e->buf.len = len;
+ e->is_args = le.is_args;
}
if (code->add_args && r->args.len) {
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
index b865cdb76..37c8951f1 100644
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -27,6 +27,7 @@ typedef struct {
unsigned flushed:1;
unsigned skip:1;
unsigned quote:1;
+ unsigned is_args:1;
unsigned log:1;
int *captures;
@@ -194,6 +195,7 @@ size_t ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e);
void ngx_http_script_copy_var_code(ngx_http_script_engine_t *e);
size_t ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e);
void ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e);
+size_t ngx_http_script_mark_args_code(ngx_http_script_engine_t *e);
void ngx_http_script_start_args_code(ngx_http_script_engine_t *e);
#if (NGX_PCRE)
void ngx_http_script_regex_start_code(ngx_http_script_engine_t *e);
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 5671f9bb7..741a9b1d4 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -439,9 +439,6 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
r->err_status = err_page->overwrite;
- r->method = NGX_HTTP_GET;
- r->method_name = ngx_http_get_name;
-
r->zero_in_uri = 0;
args = NULL;
@@ -494,6 +491,10 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
}
if (uri->data[0] == '/') {
+
+ r->method = NGX_HTTP_GET;
+ r->method_name = ngx_http_get_name;
+
return ngx_http_internal_redirect(r, uri, args);
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 89240c0b1..7041514c8 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -392,6 +392,8 @@ ngx_http_upstream_init(ngx_http_request_t *r)
uscf = uscfp[i];
if (uscf->host.len == host->len
+ && ((uscf->port == 0 && u->resolved->default_port)
+ || uscf->port == u->resolved->port)
&& ngx_memcmp(uscf->host.data, host->data, host->len) == 0)
{
goto found;
@@ -420,13 +422,13 @@ ngx_http_upstream_init(ngx_http_request_t *r)
ctx->data = r;
ctx->timeout = clcf->resolver_timeout;
- u->resolved->ctx = ctx;
-
if (ngx_resolve_name(ctx) != NGX_OK) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
+ u->resolved->ctx = ctx;
+
return;
}
@@ -1936,6 +1938,7 @@ ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
cl->buf->pos = b->last;
b->last += bytes;
cl->buf->last = b->last;
+ cl->buf->tag = u->output.tag;
if (u->length == NGX_MAX_SIZE_T_VALUE) {
return NGX_OK;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 15615caec..2ed2797a2 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -201,6 +201,7 @@ typedef struct {
typedef struct {
ngx_str_t host;
in_port_t port;
+ ngx_uint_t default_port; /* unsigned default_port:1 */
ngx_uint_t naddrs;
in_addr_t *addrs;
ngx_resolver_ctx_t *ctx;
diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h
index a6b78a5aa..1efff5b51 100644
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -81,6 +81,7 @@ typedef struct {
ngx_mail_protocol_t *protocol;
ngx_msec_t timeout;
+ ngx_msec_t resolver_timeout;
ngx_flag_t so_keepalive;
@@ -89,6 +90,8 @@ typedef struct {
u_char *file_name;
ngx_int_t line;
+ ngx_resolver_t *resolver;
+
/* server ctx */
ngx_mail_conf_ctx_t *ctx;
} ngx_mail_core_srv_conf_t;
@@ -147,6 +150,8 @@ typedef struct {
void **main_conf;
void **srv_conf;
+ ngx_resolver_ctx_t *resolver_ctx;
+
ngx_mail_proxy_ctx_t *proxy;
ngx_uint_t mail_state;
@@ -171,6 +176,7 @@ typedef struct {
ngx_str_t text;
ngx_str_t *addr_text;
+ ngx_str_t host;
ngx_str_t smtp_helo;
ngx_uint_t command;
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
index 4f13703bf..03635fc43 100644
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -20,6 +20,8 @@ static char *ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static ngx_command_t ngx_mail_core_commands[] = {
@@ -66,6 +68,20 @@ static ngx_command_t ngx_mail_core_commands[] = {
offsetof(ngx_mail_core_srv_conf_t, server_name),
NULL },
+ { ngx_string("resolver"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_mail_core_resolver,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("resolver_timeout"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_core_srv_conf_t, resolver_timeout),
+ NULL },
+
ngx_null_command
};
@@ -141,8 +157,14 @@ ngx_mail_core_create_srv_conf(ngx_conf_t *cf)
*/
cscf->timeout = NGX_CONF_UNSET_MSEC;
+ cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
cscf->so_keepalive = NGX_CONF_UNSET;
+ cscf->resolver = NGX_CONF_UNSET_PTR;
+
+ cscf->file_name = cf->conf_file->file.name.data;
+ cscf->line = cf->conf_file->line;
+
return cscf;
}
@@ -154,6 +176,8 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_mail_core_srv_conf_t *conf = child;
ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
+ ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout,
+ 30000);
ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0);
@@ -184,6 +208,8 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
+ ngx_conf_merge_ptr_value(conf->resolver, prev->resolver, NULL);
+
return NGX_CONF_OK;
}
@@ -237,9 +263,6 @@ ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index];
cscf->ctx = ctx;
- cscf->file_name = cf->conf_file->file.name.data;
- cscf->line = cf->conf_file->line;
-
cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
cscfp = ngx_array_push(&cmcf->servers);
@@ -389,6 +412,44 @@ ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
+static char *
+ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_mail_core_srv_conf_t *cscf = conf;
+
+ ngx_url_t u;
+ ngx_str_t *value;
+
+ value = cf->args->elts;
+
+ if (cscf->resolver != NGX_CONF_UNSET_PTR) {
+ return "is duplicate";
+ }
+
+ if (ngx_strcmp(value[1].data, "off") == 0) {
+ cscf->resolver = NULL;
+ return NGX_CONF_OK;
+ }
+
+ ngx_memzero(&u, sizeof(ngx_url_t));
+
+ u.host = value[1];
+ u.port = 53;
+
+ if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
+ return NGX_CONF_ERROR;
+ }
+
+ cscf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
+ if (cscf->resolver == NULL) {
+ return NGX_CONF_OK;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
char *
ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c
index e6c2edc64..9f5a2f6cb 100644
--- a/src/mail/ngx_mail_proxy_module.c
+++ b/src/mail/ngx_mail_proxy_module.c
@@ -528,10 +528,10 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
s->connection->log->action = "sending XCLIENT to upstream";
- line.len = sizeof("XCLIENT PROTO=SMTP HELO= ADDR= LOGIN= "
- "NAME=[UNAVAILABLE]" CRLF) - 1
+ line.len = sizeof("XCLIENT PROTO=SMTP HELO= ADDR= LOGIN= NAME="
+ CRLF) - 1
+ s->esmtp + s->smtp_helo.len
- + s->connection->addr_text.len + s->login.len;
+ + s->connection->addr_text.len + s->login.len + s->host.len;
line.data = ngx_palloc(c->pool, line.len);
if (line.data == NULL) {
@@ -542,15 +542,14 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
if (s->smtp_helo.len) {
line.len = ngx_sprintf(line.data,
"XCLIENT PROTO=%sSMTP HELO=%V ADDR=%V LOGIN=%V "
- "NAME=[UNAVAILABLE]" CRLF,
+ "NAME=%V" CRLF,
(s->esmtp ? "E" : ""), &s->smtp_helo,
- &s->connection->addr_text, &s->login)
+ &s->connection->addr_text, &s->login, &s->host)
- line.data;
} else {
line.len = ngx_sprintf(line.data,
- "XCLIENT PROTO=SMTP ADDR=%V LOGIN=%V "
- "NAME=[UNAVAILABLE]" CRLF,
- &s->connection->addr_text, &s->login)
+ "XCLIENT PROTO=SMTP ADDR=%V LOGIN=%V NAME=%V" CRLF,
+ &s->connection->addr_text, &s->login, &s->host)
- line.data;
}
diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c
index 6a49a0ab7..6e944738f 100644
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -11,6 +11,9 @@
#include <ngx_mail_smtp_module.h>
+static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
+static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
+static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
ngx_connection_t *c);
@@ -40,13 +43,182 @@ static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF;
static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF;
+static ngx_str_t smtp_unavailable = ngx_string("[UNAVAILABLE]");
+static ngx_str_t smtp_tempunavail = ngx_string("[TEMPUNAVAIL]");
+
+
void
ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
{
+ struct sockaddr_in *sin;
+ ngx_resolver_ctx_t *ctx;
+ ngx_mail_core_srv_conf_t *cscf;
+
+ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+ if (cscf->resolver == NULL) {
+ s->host = smtp_unavailable;
+ ngx_mail_smtp_greeting(s, c);
+ return;
+ }
+
+ c->log->action = "in resolving client address";
+
+ ctx = ngx_resolve_start(cscf->resolver, NULL);
+ if (ctx == NULL) {
+ ngx_mail_close_connection(c);
+ return;
+ }
+
+ /* AF_INET only */
+
+ sin = (struct sockaddr_in *) c->sockaddr;
+
+ ctx->addr = sin->sin_addr.s_addr;
+ ctx->handler = ngx_mail_smtp_resolve_addr_handler;
+ ctx->data = s;
+ ctx->timeout = cscf->resolver_timeout;
+
+ if (ngx_resolve_addr(ctx) != NGX_OK) {
+ ngx_mail_close_connection(c);
+ }
+}
+
+
+static void
+ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
+{
+ ngx_connection_t *c;
+ ngx_mail_session_t *s;
+ ngx_mail_core_srv_conf_t *cscf;
+
+ s = ctx->data;
+ c = s->connection;
+
+ if (ctx->state) {
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
+ "%V could not be resolved (%i: %s)",
+ &c->addr_text, ctx->state,
+ ngx_resolver_strerror(ctx->state));
+
+ if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
+ s->host = smtp_unavailable;
+
+ } else {
+ s->host = smtp_tempunavail;
+ }
+
+ ngx_resolve_addr_done(ctx);
+
+ ngx_mail_smtp_greeting(s, s->connection);
+
+ return;
+ }
+
+ c->log->action = "in resolving client hostname";
+
+ s->host.data = ngx_pstrdup(c->pool, &ctx->name);
+ if (s->host.data == NULL) {
+ ngx_resolve_addr_done(ctx);
+ ngx_mail_close_connection(c);
+ return;
+ }
+
+ s->host.len = ctx->name.len;
+
+ ngx_resolve_addr_done(ctx);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "address resolved: %V", &s->host);
+
+ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+ ctx = ngx_resolve_start(cscf->resolver, NULL);
+ if (ctx == NULL) {
+ ngx_mail_close_connection(c);
+ return;
+ }
+
+ ctx->name = s->host;
+ ctx->type = NGX_RESOLVE_A;
+ ctx->handler = ngx_mail_smtp_resolve_name_handler;
+ ctx->data = s;
+ ctx->timeout = cscf->resolver_timeout;
+
+ if (ngx_resolve_name(ctx) != NGX_OK) {
+ ngx_mail_close_connection(c);
+ }
+}
+
+
+static void
+ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
+{
+ in_addr_t addr;
+ ngx_uint_t i;
+ ngx_connection_t *c;
+ struct sockaddr_in *sin;
+ ngx_mail_session_t *s;
+
+ s = ctx->data;
+ c = s->connection;
+
+ if (ctx->state) {
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
+ "%V could not be resolved (%i: %s)",
+ &ctx->name, ctx->state,
+ ngx_resolver_strerror(ctx->state));
+
+ if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
+ s->host = smtp_unavailable;
+
+ } else {
+ s->host = smtp_tempunavail;
+ }
+
+ } else {
+
+ /* AF_INET only */
+
+ sin = (struct sockaddr_in *) c->sockaddr;
+
+ for (i = 0; i < ctx->naddrs; i++) {
+
+ addr = ctx->addrs[i];
+
+ ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "name was resolved to %ud.%ud.%ud.%ud",
+ (ntohl(addr) >> 24) & 0xff,
+ (ntohl(addr) >> 16) & 0xff,
+ (ntohl(addr) >> 8) & 0xff,
+ ntohl(addr) & 0xff);
+
+ if (addr == sin->sin_addr.s_addr) {
+ goto found;
+ }
+ }
+
+ s->host = smtp_unavailable;
+ }
+
+found:
+
+ ngx_resolve_name_done(ctx);
+
+ ngx_mail_smtp_greeting(s, c);
+}
+
+
+static void
+ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
+{
ngx_msec_t timeout;
ngx_mail_core_srv_conf_t *cscf;
ngx_mail_smtp_srv_conf_t *sscf;
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "smtp greeting for \"%V\"", &s->host);
+
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
diff --git a/src/os/unix/ngx_channel.c b/src/os/unix/ngx_channel.c
index 62ea7cc30..f0f337d06 100644
--- a/src/os/unix/ngx_channel.c
+++ b/src/os/unix/ngx_channel.c
@@ -33,7 +33,7 @@ ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
msg.msg_control = (caddr_t) &cmsg;
msg.msg_controllen = sizeof(cmsg);
- cmsg.cm.cmsg_len = sizeof(cmsg);
+ cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
cmsg.cm.cmsg_level = SOL_SOCKET;
cmsg.cm.cmsg_type = SCM_RIGHTS;
*(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
@@ -138,7 +138,7 @@ ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log)
if (ch->command == NGX_CMD_OPEN_CHANNEL) {
- if (cmsg.cm.cmsg_len < (socklen_t) sizeof(cmsg)) {
+ if (cmsg.cm.cmsg_len < (socklen_t) CMSG_LEN(sizeof(int))) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"recvmsg() returned too small ancillary data");
return NGX_ERROR;
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index 818e230ba..24dcdcb46 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -48,11 +48,16 @@
#if __FreeBSD_version < 400017
-/* FreeBSD 3.x has no CMSG_SPACE() at all and has the broken CMSG_DATA() */
+/*
+ * FreeBSD 3.x has no CMSG_SPACE() and CMSG_LEN() and has the broken CMSG_DATA()
+ */
#undef CMSG_SPACE
#define CMSG_SPACE(l) (ALIGN(sizeof(struct cmsghdr)) + ALIGN(l))
+#undef CMSG_LEN
+#define CMSG_LEN(l) (ALIGN(sizeof(struct cmsghdr)) + (l))
+
#undef CMSG_DATA
#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + ALIGN(sizeof(struct cmsghdr)))
diff --git a/src/os/unix/ngx_linux_init.c b/src/os/unix/ngx_linux_init.c
index cb83cd3e8..277be9537 100644
--- a/src/os/unix/ngx_linux_init.c
+++ b/src/os/unix/ngx_linux_init.c
@@ -11,7 +11,7 @@
u_char ngx_linux_kern_ostype[50];
u_char ngx_linux_kern_osrelease[50];
-int ngx_linux_rtsig_max;
+int ngx_linux_rtsig_max;
static ngx_os_io_t ngx_linux_io = {
@@ -32,9 +32,6 @@ static ngx_os_io_t ngx_linux_io = {
ngx_int_t
ngx_os_specific_init(ngx_log_t *log)
{
- int name[2];
- size_t len;
- ngx_err_t err;
struct utsname u;
if (uname(&u) == -1) {
@@ -48,6 +45,12 @@ ngx_os_specific_init(ngx_log_t *log)
(void) ngx_cpystrn(ngx_linux_kern_osrelease, (u_char *) u.release,
sizeof(ngx_linux_kern_osrelease));
+#if (NGX_HAVE_RTSIG)
+ {
+ int name[2];
+ size_t len;
+ ngx_err_t err;
+
name[0] = CTL_KERN;
name[1] = KERN_RTSIGMAX;
len = sizeof(ngx_linux_rtsig_max);
@@ -65,6 +68,8 @@ ngx_os_specific_init(ngx_log_t *log)
ngx_linux_rtsig_max = 0;
}
+ }
+#endif
ngx_os_io = ngx_linux_io;
@@ -78,6 +83,8 @@ ngx_os_specific_status(ngx_log_t *log)
ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s",
ngx_linux_kern_ostype, ngx_linux_kern_osrelease);
+#if (NGX_HAVE_RTSIG)
ngx_log_error(NGX_LOG_NOTICE, log, 0, "sysctl(KERN_RTSIGMAX): %d",
ngx_linux_rtsig_max);
+#endif
}
diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h
index 49c3c4d6c..37176e0d2 100644
--- a/src/os/unix/ngx_posix_config.h
+++ b/src/os/unix/ngx_posix_config.h
@@ -110,11 +110,16 @@
#include <sys/param.h> /* ALIGN() */
-/* FreeBSD 3.x has no CMSG_SPACE() at all and has the broken CMSG_DATA() */
+/*
+ * FreeBSD 3.x has no CMSG_SPACE() and CMSG_LEN() and has the broken CMSG_DATA()
+ */
#undef CMSG_SPACE
#define CMSG_SPACE(l) (ALIGN(sizeof(struct cmsghdr)) + ALIGN(l))
+#undef CMSG_LEN
+#define CMSG_LEN(l) (ALIGN(sizeof(struct cmsghdr)) + (l))
+
#undef CMSG_DATA
#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + ALIGN(sizeof(struct cmsghdr)))
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index aa95e81d9..73b9d690a 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -994,18 +994,18 @@ ngx_worker_process_exit(ngx_cycle_t *cycle)
}
}
- if (ngx_quit) {
+ if (ngx_exiting) {
c = cycle->connections;
for (i = 0; i < cycle->connection_n; i++) {
if (c[i].fd != -1
&& c[i].read
&& !c[i].read->accept
- && !c[i].read->channel)
+ && !c[i].read->channel
+ && !c[i].read->resolver)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
- "open socket #%d left in %ui connection, "
- "aborting",
- c[i].fd, i);
+ "open socket #%d left in %ui connection %s",
+ c[i].fd, i, ngx_debug_quit ? ", aborting" : "");
ngx_debug_point();
}
}
@@ -1059,6 +1059,11 @@ ngx_channel_handler(ngx_event_t *ev)
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);
if (n == NGX_ERROR) {
+
+ if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
+ ngx_del_conn(c, 0);
+ }
+
ngx_close_connection(c);
return;
}