summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES67
-rw-r--r--CHANGES.ru71
-rw-r--r--auto/init15
-rw-r--r--conf/mime.types1
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_conf_file.c2
-rw-r--r--src/core/ngx_conf_file.h4
-rw-r--r--src/core/ngx_connection.c4
-rw-r--r--src/core/ngx_inet.c8
-rw-r--r--src/core/ngx_string.c36
-rw-r--r--src/core/ngx_string.h1
-rw-r--r--src/event/modules/ngx_devpoll_module.c76
-rw-r--r--src/event/modules/ngx_kqueue_module.c2
-rw-r--r--src/event/ngx_event.c19
-rw-r--r--src/event/ngx_event.h30
-rw-r--r--src/event/ngx_event_connect.c2
-rw-r--r--src/event/ngx_event_openssl.c2
-rw-r--r--src/http/modules/ngx_http_access_module.c10
-rw-r--r--src/http/modules/ngx_http_autoindex_module.c5
-rw-r--r--src/http/modules/ngx_http_empty_gif_module.c6
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c5
-rw-r--r--src/http/modules/ngx_http_geo_module.c19
-rw-r--r--src/http/modules/ngx_http_headers_filter_module.c388
-rw-r--r--src/http/modules/ngx_http_limit_zone_module.c2
-rw-r--r--src/http/modules/ngx_http_log_module.c5
-rw-r--r--src/http/modules/ngx_http_map_module.c2
-rw-r--r--src/http/modules/ngx_http_proxy_module.c5
-rw-r--r--src/http/modules/ngx_http_realip_module.c10
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/modules/perl/nginx.xs2
-rw-r--r--src/http/ngx_http.c4
-rw-r--r--src/http/ngx_http_core_module.c28
-rw-r--r--src/http/ngx_http_core_module.h4
-rw-r--r--src/http/ngx_http_request.c77
-rw-r--r--src/http/ngx_http_script.c2
-rw-r--r--src/http/ngx_http_upstream.c19
-rw-r--r--src/http/ngx_http_upstream.h2
-rw-r--r--src/http/ngx_http_upstream_round_robin.c12
-rw-r--r--src/http/ngx_http_write_filter_module.c6
-rw-r--r--src/mail/ngx_mail.c2
-rw-r--r--src/mail/ngx_mail.h83
-rw-r--r--src/mail/ngx_mail_auth_http_module.c57
-rw-r--r--src/mail/ngx_mail_core_module.c100
-rw-r--r--src/mail/ngx_mail_handler.c450
-rw-r--r--src/mail/ngx_mail_parse.c60
-rw-r--r--src/os/unix/ngx_freebsd_config.h3
-rw-r--r--src/os/unix/ngx_linux_config.h3
-rw-r--r--src/os/unix/ngx_posix_config.h3
-rw-r--r--src/os/unix/ngx_process_cycle.c101
-rw-r--r--src/os/unix/ngx_solaris_config.h3
50 files changed, 1389 insertions, 433 deletions
diff --git a/CHANGES b/CHANGES
index ccef82589..b44431335 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,71 @@
+Changes with nginx 0.5.32 24 Sep 2007
+
+ *) Change: now nginx tries to set the "worker_priority",
+ "worker_rlimit_nofile", "worker_rlimit_core", and
+ "worker_rlimit_sigpending" without super-user privileges.
+
+ *) Change: now nginx escapes space and "%" in request to a mail proxy
+ authentication server.
+
+ *) Change: now nginx escapes "%" in $memcached_key variable.
+
+ *) Change: the special make target "upgrade1" was defined for online
+ upgrade of 0.1.x versions.
+
+ *) Feature: the "add_header Last-Modified ..." directive changes the
+ "Last-Modified" response header line.
+
+ *) Feature: the mail proxy supports AUTHENTICATE in IMAP mode.
+ Thanks to Maxim Dounin.
+
+ *) Feature: the mail proxy supports STARTTLS in SMTP mode.
+ Thanks to Maxim Dounin.
+
+ *) Bugfix: nginx did not close directory file on HEAD request if
+ autoindex was used.
+ Thanks to Arkadiusz Patyk.
+
+ *) Bugfix: the "proxy_hide_header" and "fastcgi_hide_header" directives
+ did not hide response header lines whose name was longer than 32
+ characters.
+ Thanks to Manlio Perillo.
+
+ *) Bugfix: active connection counter always increased if mail proxy was
+ used.
+
+ *) Bugfix: if backend returned response header only using non-buffered
+ proxy, then nginx closed backend connection on timeout.
+
+ *) Bugfix: nginx did not support several "Connection" request header
+ lines.
+
+ *) Bugfix: a charset set by the "charset" directive was not appended to
+ the "Content-Type" header set by $r->send_http_header().
+
+ *) Bugfix: a segmentation fault might occur in worker process if
+ /dev/poll method was used.
+
+ *) Bugfix: nginx did not work on FreeBSD/sparc64.
+
+ *) Bugfix: a segmentation fault occurred in worker process if invalid
+ address was set in the "auth_http" directive.
+
+ *) Bugfix: now nginx uses default listen backlog value 511 on all
+ platforms except FreeBSD.
+ Thanks to Jiang Hong.
+
+ *) Bugfix: now Solaris sendfilev() is not used to transfer the client
+ request body to FastCGI-server via the unix domain socket.
+
+ *) Bugfix: if the same host without specified port was used as backend
+ for HTTP and HTTPS, then nginx used only one port - 80 or 443.
+
+ *) Bugfix: the "proxy_ignore_client_abort" and
+ "fastcgi_ignore_client_abort" directives did not work; bug appeared
+ in 0.5.13.
+
+
Changes with nginx 0.5.31 15 Aug 2007
*) Feature: named locations.
diff --git a/CHANGES.ru b/CHANGES.ru
index 6f35d1391..369365db1 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,75 @@
+Изменения в nginx 0.5.32 24.09.2007
+
+ *) Изменение: теперь nginx пытается установить директивы
+ worker_priority, worker_rlimit_nofile, worker_rlimit_core,
+ worker_rlimit_sigpending без привилегий root'а.
+
+ *) Изменение: теперь nginx экранирует символы пробела и "%" при
+ передаче запроса серверу аутентификации почтового прокси-сервера.
+
+ *) Изменение: теперь nginx экранирует символ "%" в переменной
+ $memcached_key.
+
+ *) Изменение: для обновления на лету версий 0.1.x создан специальный
+ сценарий make upgrade1.
+
+ *) Добавление: директива "add_header Last-Modified ..." меняет строку
+ "Last-Modified" в заголовке ответа.
+
+ *) Добавление: почтовый прокси-сервер поддерживает AUTHENTICATE в
+ режиме IMAP.
+ Спасибо Максиму Дунину.
+
+ *) Добавление: почтовый прокси-сервер поддерживает STARTTLS в режиме
+ SMTP.
+ Спасибо Максиму Дунину.
+
+ *) Исправление: nginx не закрывал файл каталога для запроса HEAD, если
+ использовался autoindex
+ Спасибо Arkadiusz Patyk.
+
+ *) Исправление: директивы proxy_hide_header и fastcgi_hide_header не
+ скрывали строки заголовка ответа с именем больше 32 символов.
+ Спасибо Manlio Perillo.
+
+ *) Исправление: счётчик активных соединений всегда рос при
+ использовании почтового прокси-сервера.
+
+ *) Исправление: если бэкенд возвращал только заголовок ответа при
+ небуферизированном проксировании, то nginx закрывал соединение с
+ бэкендом по таймауту.
+
+ *) Исправление: nginx не поддерживал несколько строк "Connection" в
+ заголовке запроса.
+
+ *) Исправление: В строку заголовка ответа "Content-Type", указанную в
+ методе $r->send_http_header(), не добавлялась кодировка, указанная в
+ директиве charset.
+
+ *) Исправление: при использовании метода /dev/poll в рабочем процессе
+ мог произойти segmentation fault.
+
+ *) Исправление: nginx не работал на FreeBSD/sparc64.
+
+ *) Исправление: если в директиве auth_http был задан неправильный
+ адрес, то в рабочем процессе происходил segmentation fault.
+
+ *) Исправление: теперь по умолчанию nginx использует значение 511 для
+ listen backlog на всех платформах, кроме FreeBSD.
+ Спасибо Jiang Hong.
+
+ *) Исправление: sendfilev() в Solaris теперь не используется при
+ передаче тела запроса FastCGI-серверу через unix domain сокет.
+
+ *) Исправление: при использовании одного хоста в качестве бэкендов для
+ протоколов HTTP и HTTPS без явного указания портов, nginx
+ использовал только один порт - 80 или 443.
+
+ *) Исправление: директивы proxy_ignore_client_abort и
+ fastcgi_ignore_client_abort не работали; ошибка появилась в 0.5.13.
+
+
Изменения в nginx 0.5.31 15.08.2007
*) Добавление: именованные location'ы.
diff --git a/auto/init b/auto/init
index 6c52c21a2..e18044114 100644
--- a/auto/init
+++ b/auto/init
@@ -55,15 +55,24 @@ clean:
upgrade:
$NGX_SBIN_PATH -t
- # upgrade compatibility from 0.1.x to 0.2.x
+ kill -USR2 \`cat $NGX_PID_PATH\`
+ sleep 1
+ test -f $NGX_PID_PATH.oldbin
+
+ kill -QUIT \`cat $NGX_PID_PATH.oldbin\`
+
+upgrade1:
+ # upgrade 0.1.x to 0.2+
+
+ $NGX_SBIN_PATH -t
+
cp $NGX_PID_PATH $NGX_PID_PATH.oldbin
kill -USR2 \`cat $NGX_PID_PATH\`
sleep 1
test -f $NGX_PID_PATH.oldbin
- # upgrade compatibility from 0.1.x to 0.2.x
cp $NGX_PID_PATH $NGX_PID_PATH.newbin
- kill -WINCH \`cat $NGX_PID_PATH.oldbin\`
+ kill -QUIT \`cat $NGX_PID_PATH.oldbin\`
END
diff --git a/conf/mime.types b/conf/mime.types
index f1714338b..3031cf6d7 100644
--- a/conf/mime.types
+++ b/conf/mime.types
@@ -20,6 +20,7 @@ types {
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
+ image/svg+xml svg;
application/java-archive jar war ear;
application/mac-binhex40 hqx;
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 3e7c4a1ce..128d48bcd 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.5.31"
+#define NGINX_VERSION "0.5.32"
#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 a68192fe0..ad60ce4a1 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -366,7 +366,7 @@ not_allowed:
invalid:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid number arguments in \"%s\" directive",
+ "invalid number of arguments in \"%s\" directive",
name->data);
return NGX_ERROR;
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index 7d5112919..c065384b0 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -257,8 +257,8 @@ char *ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data);
}
#define ngx_conf_merge_ptr_value(conf, prev, default) \
- if (conf == NULL) { \
- conf = (prev == NULL) ? default : prev; \
+ if (conf == NGX_CONF_UNSET_PTR) { \
+ conf = (prev == NGX_CONF_UNSET_PTR) ? default : prev; \
}
#define ngx_conf_merge_uint_value(conf, prev, default) \
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 9d22ac60b..af2f25cd8 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -123,7 +123,7 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
ntohs(sin->sin_port))
- ls[i].addr_text.data;
- ls[i].backlog = -1;
+ ls[i].backlog = NGX_LISTEN_BACKLOG;
olen = sizeof(int);
@@ -735,7 +735,7 @@ ngx_close_connection(ngx_connection_t *c)
/* 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_close_socket_n " failed");
+ ngx_close_socket_n " %d failed", fd);
}
}
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index de4cae280..31094ba59 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -214,7 +214,13 @@ ngx_ptocidr(ngx_str_t *text, void *cidr)
in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - m))));
- return NGX_OK;
+ if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) {
+ return NGX_OK;
+ }
+
+ in_cidr->addr &= in_cidr->mask;
+
+ return NGX_DONE;
}
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index a07dbebeb..508158c8b 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -59,8 +59,9 @@ ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src)
* %P ngx_pid_t
* %M ngx_msec_t
* %r rlim_t
- * %p pointer
- * %V pointer to ngx_str_t
+ * %p void *
+ * %V ngx_str_t *
+ * %v ngx_variable_value_t *
* %s null-terminated string
* %Z '\0'
* %N '\n'
@@ -117,7 +118,8 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
uint64_t ui64;
ngx_msec_t ms;
ngx_uint_t width, sign, hexadecimal, max_width;
- ngx_variable_value_t *v;
+ ngx_str_t *v;
+ ngx_variable_value_t *vv;
static u_char hex[] = "0123456789abcdef";
static u_char HEX[] = "0123456789ABCDEF";
@@ -188,7 +190,7 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
switch (*fmt) {
case 'V':
- v = va_arg(args, ngx_variable_value_t *);
+ v = va_arg(args, ngx_str_t *);
len = v->len;
len = (buf + len < last) ? len : (size_t) (last - buf);
@@ -198,6 +200,17 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
continue;
+ case 'v':
+ vv = va_arg(args, ngx_variable_value_t *);
+
+ len = vv->len;
+ len = (buf + len < last) ? len : (size_t) (last - buf);
+
+ buf = ngx_cpymem(buf, vv->data, len);
+ fmt++;
+
+ continue;
+
case 's':
p = va_arg(args, u_char *);
@@ -1019,7 +1032,7 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
- /* " ", """, "%", "'", %00-%1F, %7F-%FF */
+ /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */
static uint32_t html[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
@@ -1039,13 +1052,13 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
- /* " ", """, "'", %00-%1F, %7F-%FF */
+ /* " ", """, "%", "'", %00-%1F, %7F-%FF */
static uint32_t refresh[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
- 0x00000085, /* 0000 0000 0000 0000 0000 0000 1000 0101 */
+ 0x000000a5, /* 0000 0000 0000 0000 0000 0000 1010 0101 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
@@ -1059,13 +1072,13 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
- /* " ", %00-%1F */
+ /* " ", "%", %00-%1F */
static uint32_t memcached[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
- 0x00000001, /* 0000 0000 0000 0000 0000 0000 0000 0001 */
+ 0x00000021, /* 0000 0000 0000 0000 0000 0000 0010 0001 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
@@ -1079,7 +1092,10 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
};
- static uint32_t *map[] = { uri, args, html, refresh, memcached };
+ /* mail_auth is the same as memcached */
+
+ static uint32_t *map[] =
+ { uri, args, html, refresh, memcached, memcached };
escape = map[type];
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index b4a96c543..42d50a46c 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -155,6 +155,7 @@ u_char *ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n);
#define NGX_ESCAPE_HTML 2
#define NGX_ESCAPE_REFRESH 3
#define NGX_ESCAPE_MEMCACHED 4
+#define NGX_ESCAPE_MAIL_AUTH 5
#define NGX_UNESCAPE_URI 1
diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c
index d7ea99b0c..0ce003f9e 100644
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -15,6 +15,7 @@
#define POLLREMOVE 0x0800
#define DP_POLL 0xD001
+#define DP_ISPOLLED 0xD002
struct dvpoll {
struct pollfd *dp_fds;
@@ -252,10 +253,16 @@ ngx_devpoll_del_event(ngx_event_t *ev, int event, u_int flags)
ev->active = 0;
if (flags & NGX_CLOSE_EVENT) {
+ e = (event == POLLIN) ? c->write : c->read;
+
+ if (e) {
+ e->active = 0;
+ }
+
return NGX_OK;
}
- /* restore the paired event if it exists */
+ /* restore the pair event if it exists */
if (event == POLLIN) {
e = c->write;
@@ -327,13 +334,15 @@ ngx_int_t
ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_uint_t flags)
{
- int events, revents;
+ int events, revents, rc;
size_t n;
+ ngx_fd_t fd;
ngx_err_t err;
ngx_int_t i;
ngx_uint_t level;
ngx_event_t *rev, *wev, **queue;
ngx_connection_t *c;
+ struct pollfd pfd;
struct dvpoll dvp;
/* NGX_TIMER_INFINITE == INFTIM */
@@ -398,34 +407,77 @@ ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_mutex_lock(ngx_posted_events_mutex);
for (i = 0; i < events; i++) {
- c = ngx_cycle->files[event_list[i].fd];
- if (c->fd == -1) {
- if (c->read->closed) {
- continue;
+ fd = event_list[i].fd;
+ revents = event_list[i].revents;
+
+ c = ngx_cycle->files[fd];
+
+ if (c == NULL || c->fd == -1) {
+
+ pfd.fd = fd;
+ pfd.events = 0;
+ pfd.revents = 0;
+
+ rc = ioctl(dp, DP_ISPOLLED, &pfd);
+
+ switch (rc) {
+
+ case -1:
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "ioctl(DP_ISPOLLED) failed for socket %d, event",
+ fd, revents);
+ break;
+
+ case 0:
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+ "phantom event %04Xd for closed and removed socket %d",
+ revents, fd);
+ break;
+
+ default:
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+ "unexpected event %04Xd for closed and removed socket %d, ",
+ "ioctl(DP_ISPOLLED) returned rc:%d, fd:%d, event %04Xd",
+ revents, fd, rc, pfd.fd, pfd.revents);
+
+ pfd.fd = fd;
+ pfd.events = POLLREMOVE;
+ pfd.revents = 0;
+
+ if (write(dp, &pfd, sizeof(struct pollfd))
+ != (ssize_t) sizeof(struct pollfd))
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "write(/dev/poll) for %d failed, fd");
+ }
+
+ if (close(fd) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "close(%d) failed", fd);
+ }
+
+ break;
}
- ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");
continue;
}
- revents = event_list[i].revents;
-
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"devpoll: fd:%d, ev:%04Xd, rev:%04Xd",
- event_list[i].fd, event_list[i].events, revents);
+ fd, event_list[i].events, revents);
if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"ioctl(DP_POLL) error fd:%d ev:%04Xd rev:%04Xd",
- event_list[i].fd, event_list[i].events, revents);
+ fd, event_list[i].events, revents);
}
if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"strange ioctl(DP_POLL) events "
"fd:%d ev:%04Xd rev:%04Xd",
- event_list[i].fd, event_list[i].events, revents);
+ fd, event_list[i].events, revents);
}
if ((revents & (POLLERR|POLLHUP|POLLNVAL))
diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c
index af9167593..aec08b992 100644
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -404,7 +404,7 @@ ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
c = ev->data;
- ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"kevent set event: %d: ft:%d fl:%04Xd",
c->fd, filter, flags);
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index 91efde009..9be0b1ab3 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -1038,8 +1038,9 @@ ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#if (NGX_DEBUG)
ngx_event_conf_t *ecf = conf;
- ngx_event_debug_t *dc;
+ ngx_int_t rc;
ngx_str_t *value;
+ ngx_event_debug_t *dc;
struct hostent *h;
ngx_inet_cidr_t in_cidr;
@@ -1056,13 +1057,21 @@ ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (dc->addr != INADDR_NONE) {
dc->mask = 0xffffffff;
- return NGX_OK;
+ return NGX_CONF_OK;
+ }
+
+ rc = ngx_ptocidr(&value[1], &in_cidr);
+
+ if (rc == NGX_DONE) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "low address bits of %V are meaningless", &value[1]);
+ rc = NGX_OK;
}
- if (ngx_ptocidr(&value[1], &in_cidr) == NGX_OK) {
+ if (rc == NGX_OK) {
dc->mask = in_cidr.mask;
dc->addr = in_cidr.addr;
- return NGX_OK;
+ return NGX_CONF_OK;
}
h = gethostbyname((char *) value[1].data);
@@ -1084,7 +1093,7 @@ ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
- return NGX_OK;
+ return NGX_CONF_OK;
}
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index e1388d5f0..438a36052 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -41,7 +41,7 @@ struct ngx_event_s {
unsigned accept:1;
- /* used to detect the stale events in kqueue, rt signals and epoll */
+ /* used to detect the stale events in kqueue, rtsig, and epoll */
unsigned instance:1;
/*
@@ -247,8 +247,7 @@ extern ngx_event_actions_t ngx_event_actions;
#define NGX_USE_LOWAT_EVENT 0x00000010
/*
- * The event filter requires to do i/o operation until EAGAIN:
- * epoll, rt signals.
+ * The event filter requires to do i/o operation until EAGAIN: epoll, rtsig.
*/
#define NGX_USE_GREEDY_EVENT 0x00000020
@@ -258,7 +257,7 @@ extern ngx_event_actions_t ngx_event_actions;
#define NGX_USE_EPOLL_EVENT 0x00000040
/*
- * No need to add or delete the event filters: rt signals.
+ * No need to add or delete the event filters: rtsig.
*/
#define NGX_USE_RTSIG_EVENT 0x00000080
@@ -276,13 +275,13 @@ extern ngx_event_actions_t ngx_event_actions;
/*
* The event filter has no opaque data and requires file descriptors table:
- * poll, /dev/poll, rt signals.
+ * poll, /dev/poll, rtsig.
*/
#define NGX_USE_FD_EVENT 0x00000400
/*
* The event module handles periodic or absolute timer event by itself:
- * kqueue in FreeBSD 4.4 and NetBSD 2.0, Solaris 10's event ports.
+ * kqueue in FreeBSD 4.4, NetBSD 2.0, and MacOSX 10.4, Solaris 10's event ports.
*/
#define NGX_USE_TIMER_EVENT 0x00000800
@@ -290,17 +289,26 @@ extern ngx_event_actions_t ngx_event_actions;
* All event filters on file descriptor are deleted after a notification:
* Solaris 10's event ports.
*/
-#define NGX_USE_EVENTPORT_EVENT 0x00001000
+#define NGX_USE_EVENTPORT_EVENT 0x00001000
/*
- * The event filter is deleted before the closing file.
- * Has no meaning for select, poll, kqueue, epoll.
- * /dev/poll: we need to flush POLLREMOVE event before closing file
+ * The event filter is deleted just before the closing file.
+ * Has no meaning for select and poll.
+ * kqueue, epoll, rtsig, eventport: allows to avoid explicit delete,
+ * because filter automatically is deleted
+ * on file close,
+ *
+ * /dev/poll: we need to flush POLLREMOVE event
+ * before closing file.
*/
-
#define NGX_CLOSE_EVENT 1
+
+/*
+ * disable temporarily event filter, this may avoid locks
+ * in kernel malloc()/free(): kqueue.
+ */
#define NGX_DISABLE_EVENT 2
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c
index fae9c8c86..a2042c7c9 100644
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -85,6 +85,8 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
c->recv_chain = ngx_recv_chain;
c->send_chain = ngx_send_chain;
+ c->sendfile = 1;
+
c->log_error = pc->log_error;
if (pc->sockaddr->sa_family != AF_INET) {
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index d31196887..39164eaa2 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1588,7 +1588,7 @@ ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
}
if (n++ != 0 && sess_id->expire > tp->sec) {
- break;
+ return;
}
sess_id->next->prev = sess_id->prev;
diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c
index 2cd8a8f24..e4e87b243 100644
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -137,6 +137,7 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_access_loc_conf_t *alcf = conf;
+ ngx_int_t rc;
ngx_str_t *value;
ngx_inet_cidr_t in_cidr;
ngx_http_access_rule_t *rule;
@@ -173,12 +174,19 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK;
}
- if (ngx_ptocidr(&value[1], &in_cidr) == NGX_ERROR) {
+ rc = ngx_ptocidr(&value[1], &in_cidr);
+
+ if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
&value[1]);
return NGX_CONF_ERROR;
}
+ if (rc == NGX_DONE) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "low address bits of %V are meaningless", &value[1]);
+ }
+
rule->mask = in_cidr.mask;
rule->addr = in_cidr.addr;
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index e08e63c8f..ae9eaabbb 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -236,6 +236,11 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
+ if (ngx_close_dir(&dir) == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+ ngx_close_dir_n " \"%V\" failed", &path);
+ }
+
return rc;
}
diff --git a/src/http/modules/ngx_http_empty_gif_module.c b/src/http/modules/ngx_http_empty_gif_module.c
index 050e75912..03ca8021b 100644
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -128,11 +128,7 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
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;
- }
+ return ngx_http_send_header(r);
}
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index c1ce79ce7..c63c0f382 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1135,7 +1135,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
} else {
for (i = 0; i < h->key.len; i++) {
- h->lowcase_key[i] = ngx_tolower(h->lowcase_key[i]);
+ h->lowcase_key[i] = ngx_tolower(h->key.data[i]);
}
}
@@ -1640,7 +1640,6 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
* conf->upstream.hide_headers_hash = { NULL, 0 };
* conf->upstream.hide_headers = NULL;
* conf->upstream.pass_headers = NULL;
- * conf->upstream.catch_stderr = NULL;
* conf->upstream.schema = { 0, NULL };
* conf->upstream.uri = { 0, NULL };
* conf->upstream.location = NULL;
@@ -1675,6 +1674,8 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
/* "fastcgi_cyclic_temp_file" is disabled */
conf->upstream.cyclic_temp_file = 0;
+ conf->catch_stderr = NGX_CONF_UNSET_PTR;
+
return conf;
}
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index 62ef72cf9..038479f8b 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -86,7 +86,7 @@ ngx_http_geo_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
*v = *vv;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo: %V %V", &r->connection->addr_text, v);
+ "http geo: %V %v", &r->connection->addr_text, v);
return NGX_OK;
}
@@ -100,8 +100,8 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_conf_t save;
ngx_pool_t *pool;
ngx_radix_tree_t *tree;
+ ngx_http_variable_t *var;
ngx_http_geo_conf_ctx_t ctx;
- ngx_http_variable_t *var;
value = cf->args->elts;
@@ -212,12 +212,20 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
cidrin.mask = 0;
} else {
- if (ngx_ptocidr(&value[0], &cidrin) == NGX_ERROR) {
+ rc = ngx_ptocidr(&value[0], &cidrin);
+
+ if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid parameter \"%V\"", &value[0]);
return NGX_CONF_ERROR;
}
+ if (rc == NGX_DONE) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "low address bits of %V are meaningless",
+ &value[0]);
+ }
+
cidrin.addr = ntohl(cidrin.addr);
cidrin.mask = ntohl(cidrin.mask);
}
@@ -277,9 +285,8 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
ngx_radix32tree_find(ctx->tree, cidrin.addr & cidrin.mask);
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "duplicate parameter \"%V\", value: \"%V\", "
- "old value: \"%V\"",
- &value[0], var, old);
+ "duplicate parameter \"%V\", value: \"%v\", old value: \"%v\"",
+ &value[0], var, old);
rc = ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask);
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index 599bd14b7..81f4eb171 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -9,17 +9,31 @@
#include <ngx_http.h>
+typedef struct ngx_http_header_val_s ngx_http_header_val_t;
+
+typedef ngx_int_t (*ngx_http_set_header_pt)(ngx_http_request_t *r,
+ ngx_http_header_val_t *hv, ngx_str_t *value);
+
+
typedef struct {
- ngx_table_elt_t value;
- ngx_array_t *lengths;
- ngx_array_t *values;
-} ngx_http_header_val_t;
+ ngx_str_t name;
+ ngx_uint_t offset;
+ ngx_http_set_header_pt handler;
+} ngx_http_set_header_t;
+
+
+struct ngx_http_header_val_s {
+ ngx_table_elt_t value;
+ ngx_uint_t offset;
+ ngx_http_set_header_pt handler;
+ ngx_array_t *lengths;
+ ngx_array_t *values;
+};
typedef struct {
- time_t expires;
- ngx_str_t cache_control;
- ngx_array_t *headers;
+ time_t expires;
+ ngx_array_t *headers;
} ngx_http_headers_conf_t;
@@ -29,6 +43,13 @@ typedef struct {
#define NGX_HTTP_EXPIRES_MAX -2147483644
+static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r,
+ ngx_http_headers_conf_t *conf);
+static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r,
+ ngx_http_header_val_t *hv, ngx_str_t *value);
+static ngx_int_t ngx_http_set_last_modified(ngx_http_request_t *r,
+ ngx_http_header_val_t *hv, ngx_str_t *value);
+
static void *ngx_http_headers_create_conf(ngx_conf_t *cf);
static char *ngx_http_headers_merge_conf(ngx_conf_t *cf,
void *parent, void *child);
@@ -39,6 +60,18 @@ static char *ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static ngx_http_set_header_t ngx_http_set_headers[] = {
+
+ { ngx_string("Cache-Control"), 0, ngx_http_add_cache_control },
+
+ { ngx_string("Last-Modified"),
+ offsetof(ngx_http_headers_out_t, last_modified),
+ ngx_http_set_last_modified },
+
+ { ngx_null_string, 0, NULL }
+};
+
+
static ngx_command_t ngx_http_headers_filter_commands[] = {
{ ngx_string("expires"),
@@ -98,13 +131,15 @@ static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_int_t
ngx_http_headers_filter(ngx_http_request_t *r)
{
- size_t len;
+ ngx_str_t value;
ngx_uint_t i;
- ngx_table_elt_t *expires, *cc, **ccp, *out;
ngx_http_header_val_t *h;
ngx_http_headers_conf_t *conf;
- if (r != r->main
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
+
+ if ((conf->expires == NGX_HTTP_EXPIRES_OFF && conf->headers == NULL)
+ || r != r->main
|| (r->headers_out.status != NGX_HTTP_OK
&& r->headers_out.status != NGX_HTTP_NO_CONTENT
&& r->headers_out.status != NGX_HTTP_MOVED_PERMANENTLY
@@ -114,124 +149,73 @@ ngx_http_headers_filter(ngx_http_request_t *r)
return ngx_http_next_header_filter(r);
}
- conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
-
if (conf->expires != NGX_HTTP_EXPIRES_OFF) {
-
- expires = r->headers_out.expires;
-
- if (expires == NULL) {
-
- expires = ngx_list_push(&r->headers_out.headers);
- if (expires == NULL) {
- return NGX_ERROR;
- }
-
- r->headers_out.expires = expires;
-
- expires->hash = 1;
- expires->key.len = sizeof("Expires") - 1;
- expires->key.data = (u_char *) "Expires";
+ if (ngx_http_set_expires(r, conf) != NGX_OK) {
+ return NGX_ERROR;
}
+ }
- len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
- expires->value.len = len - 1;
-
- ccp = r->headers_out.cache_control.elts;
-
- if (ccp == NULL) {
+ if (conf->headers) {
+ h = conf->headers->elts;
+ for (i = 0; i < conf->headers->nelts; i++) {
- if (ngx_array_init(&r->headers_out.cache_control, r->pool,
- 1, sizeof(ngx_table_elt_t *))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
+ if (h[i].lengths == NULL) {
+ value = h[i].value.value;
- ccp = ngx_array_push(&r->headers_out.cache_control);
- if (ccp == NULL) {
- return NGX_ERROR;
+ } else {
+ if (ngx_http_script_run(r, &value, h[i].lengths->elts, 0,
+ h[i].values->elts)
+ == NULL)
+ {
+ return NGX_ERROR;
+ }
}
- cc = ngx_list_push(&r->headers_out.headers);
- if (cc == NULL) {
+ if (h[i].handler(r, &h[i], &value) != NGX_OK) {
return NGX_ERROR;
}
-
- cc->hash = 1;
- cc->key.len = sizeof("Cache-Control") - 1;
- cc->key.data = (u_char *) "Cache-Control";
-
- *ccp = cc;
-
- } else {
- for (i = 1; i < r->headers_out.cache_control.nelts; i++) {
- ccp[i]->hash = 0;
- }
-
- cc = ccp[0];
}
+ }
- if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) {
- expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
+ return ngx_http_next_header_filter(r);
+}
- cc->value.len = sizeof("no-cache") - 1;
- cc->value.data = (u_char *) "no-cache";
- } else if (conf->expires == NGX_HTTP_EXPIRES_MAX) {
- expires->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT";
+static ngx_int_t
+ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
+{
+ size_t len;
+ ngx_uint_t i;
+ ngx_table_elt_t *expires, *cc, **ccp;
- /* 10 years */
- cc->value.len = sizeof("max-age=315360000") - 1;
- cc->value.data = (u_char *) "max-age=315360000";
+ expires = r->headers_out.expires;
- } else {
- expires->value.data = ngx_palloc(r->pool, len);
- if (expires->value.data == NULL) {
- return NGX_ERROR;
- }
+ if (expires == NULL) {
- if (conf->expires == 0) {
- ngx_memcpy(expires->value.data, ngx_cached_http_time.data,
- ngx_cached_http_time.len + 1);
+ expires = ngx_list_push(&r->headers_out.headers);
+ if (expires == NULL) {
+ return NGX_ERROR;
+ }
- cc->value.len = sizeof("max-age=0") - 1;
- cc->value.data = (u_char *) "max-age=0";
+ r->headers_out.expires = expires;
- } else {
- ngx_http_time(expires->value.data, ngx_time() + conf->expires);
-
- if (conf->expires < 0) {
- cc->value.len = sizeof("no-cache") - 1;
- cc->value.data = (u_char *) "no-cache";
-
- } else {
- cc->value.data = ngx_palloc(r->pool, sizeof("max-age=")
- + NGX_TIME_T_LEN + 1);
- if (cc->value.data == NULL) {
- return NGX_ERROR;
- }
-
- cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T",
- conf->expires)
- - cc->value.data;
- }
- }
- }
+ expires->hash = 1;
+ expires->key.len = sizeof("Expires") - 1;
+ expires->key.data = (u_char *) "Expires";
}
- if (conf->cache_control.len) {
+ len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
+ expires->value.len = len - 1;
- ccp = r->headers_out.cache_control.elts;
+ ccp = r->headers_out.cache_control.elts;
- if (ccp == NULL) {
+ if (ccp == NULL) {
- if (ngx_array_init(&r->headers_out.cache_control, r->pool,
- 1, sizeof(ngx_table_elt_t *))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
+ if (ngx_array_init(&r->headers_out.cache_control, r->pool,
+ 1, sizeof(ngx_table_elt_t *))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
}
ccp = ngx_array_push(&r->headers_out.cache_control);
@@ -247,37 +231,161 @@ ngx_http_headers_filter(ngx_http_request_t *r)
cc->hash = 1;
cc->key.len = sizeof("Cache-Control") - 1;
cc->key.data = (u_char *) "Cache-Control";
- cc->value = conf->cache_control;
*ccp = cc;
+
+ } else {
+ for (i = 1; i < r->headers_out.cache_control.nelts; i++) {
+ ccp[i]->hash = 0;
+ }
+
+ cc = ccp[0];
}
- if (conf->headers) {
- h = conf->headers->elts;
- for (i = 0; i < conf->headers->nelts; i++) {
- out = ngx_list_push(&r->headers_out.headers);
- if (out == NULL) {
- return NGX_ERROR;
- }
+ if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) {
+ expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
- out->hash = h[i].value.hash;
- out->key = h[i].value.key;
+ cc->value.len = sizeof("no-cache") - 1;
+ cc->value.data = (u_char *) "no-cache";
- if (h[i].lengths == NULL) {
- out->value = h[i].value.value;
- continue;
- }
+ return NGX_OK;
+ }
- if (ngx_http_script_run(r, &out->value, h[i].lengths->elts, 0,
- h[i].values->elts)
- == NULL)
- {
- return NGX_ERROR;
- }
+ if (conf->expires == NGX_HTTP_EXPIRES_MAX) {
+ expires->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT";
+
+ /* 10 years */
+ cc->value.len = sizeof("max-age=315360000") - 1;
+ cc->value.data = (u_char *) "max-age=315360000";
+
+ return NGX_OK;
+ }
+
+ expires->value.data = ngx_palloc(r->pool, len);
+ if (expires->value.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (conf->expires == 0) {
+ ngx_memcpy(expires->value.data, ngx_cached_http_time.data,
+ ngx_cached_http_time.len + 1);
+
+ cc->value.len = sizeof("max-age=0") - 1;
+ cc->value.data = (u_char *) "max-age=0";
+
+ return NGX_OK;
+ }
+
+ ngx_http_time(expires->value.data, ngx_time() + conf->expires);
+
+ if (conf->expires < 0) {
+ cc->value.len = sizeof("no-cache") - 1;
+ cc->value.data = (u_char *) "no-cache";
+
+ return NGX_OK;
+ }
+
+ cc->value.data = ngx_palloc(r->pool,
+ sizeof("max-age=") + NGX_TIME_T_LEN + 1);
+ if (cc->value.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T", conf->expires)
+ - cc->value.data;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_add_header(ngx_http_request_t *r, ngx_http_header_val_t *hv,
+ ngx_str_t *value)
+{
+ ngx_table_elt_t *h;
+
+ h = ngx_list_push(&r->headers_out.headers);
+ if (h == NULL) {
+ return NGX_ERROR;
+ }
+
+ h->hash = hv->value.hash;
+ h->key = hv->value.key;
+ h->value = *value;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_add_cache_control(ngx_http_request_t *r, ngx_http_header_val_t *hv,
+ ngx_str_t *value)
+{
+ ngx_table_elt_t *cc, **ccp;
+
+ ccp = r->headers_out.cache_control.elts;
+
+ if (ccp == NULL) {
+
+ if (ngx_array_init(&r->headers_out.cache_control, r->pool,
+ 1, sizeof(ngx_table_elt_t *))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
}
}
- return ngx_http_next_header_filter(r);
+ ccp = ngx_array_push(&r->headers_out.cache_control);
+ if (ccp == NULL) {
+ return NGX_ERROR;
+ }
+
+ cc = ngx_list_push(&r->headers_out.headers);
+ if (cc == NULL) {
+ return NGX_ERROR;
+ }
+
+ cc->hash = 1;
+ cc->key.len = sizeof("Cache-Control") - 1;
+ cc->key.data = (u_char *) "Cache-Control";
+ cc->value = *value;
+
+ *ccp = cc;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_set_last_modified(ngx_http_request_t *r, ngx_http_header_val_t *hv,
+ ngx_str_t *value)
+{
+ ngx_table_elt_t *h, **old;
+
+ if (hv->offset) {
+ old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
+
+ } else {
+ old = NULL;
+ }
+
+ if (old == NULL || *old == NULL) {
+ h = ngx_list_push(&r->headers_out.headers);
+ if (h == NULL) {
+ return NGX_ERROR;
+ }
+
+ } else {
+ h = *old;
+ }
+
+ h->hash = hv->value.hash;
+ h->key = hv->value.key;
+ h->value = *value;
+
+ r->headers_out.last_modified_time = -1;
+
+ return NGX_OK;
}
@@ -294,8 +402,6 @@ ngx_http_headers_create_conf(ngx_conf_t *cf)
/*
* set by ngx_pcalloc():
*
- * conf->cache_control.len = 0;
- * conf->cache_control.data = NULL;
* conf->headers = NULL;
*/
@@ -313,11 +419,7 @@ ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
conf->expires = (prev->expires == NGX_HTTP_EXPIRES_UNSET) ?
- NGX_HTTP_EXPIRES_OFF : prev->expires;
- }
-
- if (conf->cache_control.data == NULL) {
- conf->cache_control = prev->cache_control;
+ NGX_HTTP_EXPIRES_OFF : prev->expires;
}
if (conf->headers == NULL) {
@@ -406,16 +508,13 @@ ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_int_t n;
ngx_str_t *value;
+ ngx_uint_t i;
ngx_http_header_val_t *h;
+ ngx_http_set_header_t *sh;
ngx_http_script_compile_t sc;
value = cf->args->elts;
- if (ngx_strcasecmp(value[1].data, (u_char *) "cache-control") == 0) {
- hcf->cache_control = value[2];
- return NGX_CONF_OK;
- }
-
if (hcf->headers == NULL) {
hcf->headers = ngx_array_create(cf->pool, 1,
sizeof(ngx_http_header_val_t));
@@ -432,9 +531,22 @@ ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
h->value.hash = 1;
h->value.key = value[1];
h->value.value = value[2];
+ h->offset = 0;
+ h->handler = ngx_http_add_header;
h->lengths = NULL;
h->values = NULL;
+ sh = ngx_http_set_headers;
+ for (i = 0; sh[i].name.len; i++) {
+ if (ngx_strcasecmp(value[1].data, sh[i].name.data) != 0) {
+ continue;
+ }
+
+ h->offset = sh[i].offset;
+ h->handler = sh[i].handler;
+ break;
+ }
+
n = ngx_http_script_variables_count(&value[2]);
if (n == 0) {
diff --git a/src/http/modules/ngx_http_limit_zone_module.c b/src/http/modules/ngx_http_limit_zone_module.c
index 17643e174..a0be6f107 100644
--- a/src/http/modules/ngx_http_limit_zone_module.c
+++ b/src/http/modules/ngx_http_limit_zone_module.c
@@ -141,7 +141,7 @@ ngx_http_limit_zone_handler(ngx_http_request_t *r)
if (len > 255) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"the value of the \"%V\" variable "
- "is more than 255 bytes: \"%V\"",
+ "is more than 255 bytes: \"%v\"",
&ctx->var, vv);
return NGX_DECLINED;
}
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index d3ebca4f1..c06e556e4 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -423,6 +423,11 @@ ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
}
+/*
+ * although there is a real $body_bytes_sent variable,
+ * this log operation code function is more optimized for logging
+ */
+
static u_char *
ngx_http_log_body_bytes_sent(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op)
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c
index fb8e8ee60..219482a5f 100644
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -167,7 +167,7 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
}
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http map: \"%V\" \"%V\"", vv, v);
+ "http map: \"%v\" \"%v\"", vv, v);
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index c8dca82ae..298d766a3 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -553,7 +553,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
} else {
unparsed_uri = 0;
- if (r->quoted_uri) {
+ if (r->quoted_uri || r->internal) {
escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
r->uri.len - loc_len, NGX_ESCAPE_URI);
}
@@ -1141,7 +1141,7 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
} else {
for (i = 0; i < h->key.len; i++) {
- h->lowcase_key[i] = ngx_tolower(h->lowcase_key[i]);
+ h->lowcase_key[i] = ngx_tolower(h->key.data[i]);
}
}
@@ -2237,6 +2237,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (port == 80) {
plcf->port.len = sizeof("80") - 1;
plcf->port.data = (u_char *) "80";
+
} else {
plcf->port.len = sizeof("443") - 1;
plcf->port.data = (u_char *) "443";
diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c
index ffb2028bf..4de4c1317 100644
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -188,6 +188,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_realip_loc_conf_t *rlcf = conf;
+ ngx_int_t rc;
ngx_str_t *value;
ngx_inet_cidr_t in_cidr;
ngx_http_realip_from_t *from;
@@ -215,12 +216,19 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK;
}
- if (ngx_ptocidr(&value[1], &in_cidr) == NGX_ERROR) {
+ rc = ngx_ptocidr(&value[1], &in_cidr);
+
+ if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
&value[1]);
return NGX_CONF_ERROR;
}
+ if (rc == NGX_DONE) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "low address bits of %V are meaningless", &value[1]);
+ }
+
from->mask = in_cidr.mask;
from->addr = in_cidr.addr;
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index b87a33ef0..6c6658b9d 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.5.31';
+our $VERSION = '0.5.32';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index dd01f3b3c..d6ba70a28 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -131,6 +131,8 @@ send_http_header(r, ...)
XSRETURN_EMPTY;
}
+ r->headers_out.content_type_len = r->headers_out.content_type.len;
+
} else {
if (ngx_http_set_content_type(r) != NGX_OK) {
XSRETURN_EMPTY;
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 6c5acd94d..51667d138 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -551,8 +551,8 @@ 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 %V:%d",
- &lscf[l].file_name, lscf[l].line);
+ "the duplicate default server in %s:%ui",
+ &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 696c10b34..347cf01b7 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -620,6 +620,8 @@ ngx_int_t
ngx_http_core_find_config_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
{
+ u_char *p;
+ size_t len;
ngx_int_t rc;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
@@ -680,7 +682,25 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r,
* r->headers_out.location->key fields
*/
- r->headers_out.location->value = clcf->name;
+ if (r->args.len == 0) {
+ r->headers_out.location->value = clcf->name;
+
+ } else {
+ len = clcf->name.len + 1 + r->args.len;
+ p = ngx_palloc(r->pool, len);
+
+ if (p == NULL) {
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_OK;
+ }
+
+ r->headers_out.location->value.len = len;
+ r->headers_out.location->value.data = p;
+
+ p = ngx_cpymem(p, clcf->name.data, clcf->name.len);
+ *p++ = '?';
+ ngx_memcpy(p, r->args.data, r->args.len);
+ }
ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY);
return NGX_OK;
@@ -2226,7 +2246,7 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
#endif
ls->family = AF_INET;
- ls->conf.backlog = -1;
+ ls->conf.backlog = NGX_LISTEN_BACKLOG;
ls->conf.rcvbuf = -1;
ls->conf.sndbuf = -1;
}
@@ -2575,9 +2595,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ls->family = AF_INET;
ls->addr = u.addr.in_addr;
ls->port = u.port;
- ls->file_name = cf->conf_file->file.name;
+ ls->file_name = cf->conf_file->file.name.data;
ls->line = cf->conf_file->line;
- ls->conf.backlog = -1;
+ ls->conf.backlog = NGX_LISTEN_BACKLOG;
ls->conf.rcvbuf = -1;
ls->conf.sndbuf = -1;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 5e9b48327..2ddbd7573 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -38,8 +38,8 @@ typedef struct {
in_port_t port;
int family;
- ngx_str_t file_name;
- ngx_int_t line;
+ u_char *file_name;
+ ngx_uint_t line;
ngx_http_listen_conf_t conf;
} ngx_http_listen_t;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 0306bf656..7bfa8284d 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -21,6 +21,8 @@ static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
@@ -34,6 +36,7 @@ static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
static void ngx_http_writer(ngx_http_request_t *r);
static void ngx_http_block_read(ngx_http_request_t *r);
+static void ngx_http_test_read(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);
@@ -71,11 +74,11 @@ ngx_http_header_t ngx_http_headers_in[] = {
ngx_http_process_unique_header_line },
{ ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
- ngx_http_process_unique_header_line },
+ ngx_http_process_connection },
{ ngx_string("If-Modified-Since"),
offsetof(ngx_http_headers_in_t, if_modified_since),
- ngx_http_process_header_line },
+ ngx_http_process_unique_header_line },
{ ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
ngx_http_process_header_line },
@@ -836,7 +839,7 @@ ngx_http_process_request_headers(ngx_event_t *rev)
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent too long header line: \"%V\"",
&header);
- ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
}
@@ -948,7 +951,7 @@ ngx_http_process_request_headers(ngx_event_t *rev)
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent invalid header line: \"%V\\r...\"",
&header);
- ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
}
@@ -1199,6 +1202,21 @@ ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
static ngx_int_t
+ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ if (ngx_strstr(h->value.data, "close")) {
+ r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
+
+ } else if (ngx_strstr(h->value.data, "keep-alive")) {
+ r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
@@ -1294,7 +1312,7 @@ ngx_http_process_request_header(ngx_http_request_t *r)
return NGX_ERROR;
}
- if (r->method & (NGX_HTTP_TRACE)) {
+ if (r->method & NGX_HTTP_TRACE) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent TRACE method");
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
@@ -1317,26 +1335,11 @@ ngx_http_process_request_header(ngx_http_request_t *r)
return NGX_ERROR;
}
- if (r->headers_in.connection) {
- if (r->headers_in.connection->value.len == 5
- && ngx_strcasecmp(r->headers_in.connection->value.data,
- (u_char *) "close")
- == 0)
- {
- r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
-
- } else if (r->headers_in.connection->value.len == 10
- && ngx_strcasecmp(r->headers_in.connection->value.data,
- (u_char *) "keep-alive")
- == 0)
- {
- r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
-
- if (r->headers_in.keep_alive) {
- r->headers_in.keep_alive_n =
- ngx_atotm(r->headers_in.keep_alive->value.data,
- r->headers_in.keep_alive->value.len);
- }
+ if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
+ if (r->headers_in.keep_alive) {
+ r->headers_in.keep_alive_n =
+ ngx_atotm(r->headers_in.keep_alive->value.data,
+ r->headers_in.keep_alive->value.len);
}
}
@@ -1710,7 +1713,7 @@ ngx_http_set_write_handler(ngx_http_request_t *r)
r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
- r->read_event_handler = ngx_http_block_read;
+ r->read_event_handler = ngx_http_test_read;
r->write_event_handler = ngx_http_writer;
wev = r->connection->write;
@@ -1823,6 +1826,26 @@ ngx_http_writer(ngx_http_request_t *r)
static void
ngx_http_block_read(ngx_http_request_t *r)
{
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http read blocked");
+
+ /* aio does not call this handler */
+
+ if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
+ && r->connection->read->active)
+ {
+ if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
+ == NGX_ERROR)
+ {
+ ngx_http_close_request(r, 0);
+ }
+ }
+}
+
+
+static void
+ngx_http_test_read(ngx_http_request_t *r)
+{
int n;
char buf[1];
ngx_err_t err;
@@ -1832,7 +1855,7 @@ ngx_http_block_read(ngx_http_request_t *r)
c = r->connection;
rev = c->read;
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http read blocked");
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test read");
#if (NGX_HAVE_KQUEUE)
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 63959498b..945602178 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -1191,7 +1191,7 @@ ngx_http_script_var_code(ngx_http_script_engine_t *e)
if (value && !value->not_found) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script var: \"%V\"", value);
+ "http script var: \"%v\"", value);
*e->sp = *value;
e->sp++;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 376b85fcd..a662e353a 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -581,7 +581,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
c->write->handler = ngx_http_upstream_send_request_handler;
c->read->handler = ngx_http_upstream_process_header;
- c->sendfile = r->connection->sendfile;
+ c->sendfile &= r->connection->sendfile;
c->pool = r->pool;
c->read->log = c->write->log = c->log = r->connection->log;
@@ -1288,6 +1288,7 @@ ngx_http_upstream_test_connect(ngx_connection_t *c)
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
if (c->write->pending_eof) {
+ c->log->action = "connecting to upstream";
(void) ngx_connection_error(c, c->write->kq_errno,
"kevent() reported that connect() failed");
return NGX_ERROR;
@@ -1311,6 +1312,7 @@ ngx_http_upstream_test_connect(ngx_connection_t *c)
}
if (err) {
+ c->log->action = "connecting to upstream";
(void) ngx_connection_error(c, err, "connect() failed");
return NGX_ERROR;
}
@@ -1488,6 +1490,11 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
ngx_http_upstream_finalize_request(r, u, 0);
return;
}
+
+ if (u->peer.connection->read->ready) {
+ ngx_http_upstream_process_non_buffered_body(
+ u->peer.connection->read);
+ }
}
return;
@@ -3201,7 +3208,7 @@ ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
"upstream \"%V\" may not have port %d in %s:%ui",
&u->host, uscfp[i]->port,
- uscfp[i]->file_name.data, uscfp[i]->line);
+ uscfp[i]->file_name, uscfp[i]->line);
return NULL;
}
@@ -3209,6 +3216,12 @@ ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
continue;
}
+ if (uscfp[i]->default_port && u->default_port
+ && uscfp[i]->default_port != u->default_port)
+ {
+ continue;
+ }
+
return uscfp[i];
}
@@ -3219,7 +3232,7 @@ ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
uscf->flags = flags;
uscf->host = u->host;
- uscf->file_name = cf->conf_file->file.name;
+ uscf->file_name = cf->conf_file->file.name.data;
uscf->line = cf->conf_file->line;
uscf->port = u->port;
uscf->default_port = u->default_port;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index b3bb1b4fd..010a10c7c 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -91,7 +91,7 @@ struct ngx_http_upstream_srv_conf_s {
ngx_uint_t flags;
ngx_str_t host;
- ngx_str_t file_name;
+ u_char *file_name;
ngx_uint_t line;
in_port_t port;
in_port_t default_port;
diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c
index af90d1d59..36917a0b2 100644
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -64,7 +64,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
if (us->port == 0 && us->default_port == 0) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no port in upstream \"%V\" in %s:%ui",
- &us->host, us->file_name.data, us->line);
+ &us->host, us->file_name, us->line);
return NGX_ERROR;
}
@@ -77,7 +77,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
if (u.err) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"%s in upstream \"%V\" in %s:%ui",
- u.err, &us->host, us->file_name.data, us->line);
+ u.err, &us->host, us->file_name, us->line);
}
return NGX_ERROR;
@@ -428,8 +428,8 @@ ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc,
rc = ngx_ssl_set_session(pc->connection, ssl_session);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "set session: %p:%d",
- ssl_session, ssl_session ? ssl_session->references : 0);
+ "set session: %p:%d",
+ ssl_session, ssl_session ? ssl_session->references : 0);
/* ngx_unlock_mutex(rrp->peers->mutex); */
@@ -453,7 +453,7 @@ ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,
}
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "save session: %p:%d", ssl_session, ssl_session->references);
+ "save session: %p:%d", ssl_session, ssl_session->references);
peer = &rrp->peers->peer[rrp->current];
@@ -468,7 +468,7 @@ ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,
if (old_ssl_session) {
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "old session: %p:%d",
+ "old session: %p:%d",
old_ssl_session, old_ssl_session->references);
/* TODO: may block */
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index 944593ae4..e5a26f003 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -249,7 +249,11 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
c->write->delayed = 1;
ngx_add_timer(c->write, (ngx_msec_t) (sent * 1000 / r->limit_rate + 1));
- } else if (c->write->ready && clcf->sendfile_max_chunk) {
+ } else if (c->write->ready
+ && clcf->sendfile_max_chunk
+ && (size_t) (c->sent - sent)
+ >= clcf->sendfile_max_chunk - 2 * ngx_pagesize)
+ {
c->write->delayed = 1;
ngx_add_timer(c->write, 1);
}
diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c
index ec74e6f03..a39bec4a4 100644
--- a/src/mail/ngx_mail.c
+++ b/src/mail/ngx_mail.c
@@ -300,7 +300,7 @@ ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- ls->backlog = -1;
+ ls->backlog = NGX_LISTEN_BACKLOG;
ls->rcvbuf = -1;
ls->sndbuf = -1;
diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h
index 478662a04..a00f306a3 100644
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -92,12 +92,15 @@ typedef struct {
ngx_str_t imap_starttls_only_capability;
ngx_str_t smtp_capability;
+ ngx_str_t smtp_starttls_capability;
+ ngx_str_t smtp_starttls_only_capability;
ngx_str_t server_name;
ngx_str_t smtp_server_name;
ngx_str_t smtp_greeting;
ngx_uint_t pop3_auth_methods;
+ ngx_uint_t imap_auth_methods;
ngx_uint_t smtp_auth_methods;
ngx_array_t pop3_capabilities;
@@ -132,6 +135,10 @@ typedef enum {
typedef enum {
ngx_imap_start = 0,
+ ngx_imap_auth_login_username,
+ ngx_imap_auth_login_password,
+ ngx_imap_auth_plain,
+ ngx_imap_auth_cram_md5,
ngx_imap_login,
ngx_imap_user,
ngx_imap_passwd
@@ -214,39 +221,47 @@ typedef struct {
} ngx_mail_log_ctx_t;
-#define NGX_POP3_USER 1
-#define NGX_POP3_PASS 2
-#define NGX_POP3_CAPA 3
-#define NGX_POP3_QUIT 4
-#define NGX_POP3_NOOP 5
-#define NGX_POP3_STLS 6
-#define NGX_POP3_APOP 7
-#define NGX_POP3_AUTH 8
-#define NGX_POP3_STAT 9
-#define NGX_POP3_LIST 10
-#define NGX_POP3_RETR 11
-#define NGX_POP3_DELE 12
-#define NGX_POP3_RSET 13
-#define NGX_POP3_TOP 14
-#define NGX_POP3_UIDL 15
-
-
-#define NGX_IMAP_LOGIN 1
-#define NGX_IMAP_LOGOUT 2
-#define NGX_IMAP_CAPABILITY 3
-#define NGX_IMAP_NOOP 4
-#define NGX_IMAP_STARTTLS 5
-
-#define NGX_IMAP_NEXT 6
-
-
-#define NGX_SMTP_HELO 1
-#define NGX_SMTP_EHLO 2
-#define NGX_SMTP_AUTH 3
-#define NGX_SMTP_QUIT 4
-#define NGX_SMTP_NOOP 5
-#define NGX_SMTP_MAIL 6
-#define NGX_SMTP_RSET 7
+#define NGX_POP3_USER 1
+#define NGX_POP3_PASS 2
+#define NGX_POP3_CAPA 3
+#define NGX_POP3_QUIT 4
+#define NGX_POP3_NOOP 5
+#define NGX_POP3_STLS 6
+#define NGX_POP3_APOP 7
+#define NGX_POP3_AUTH 8
+#define NGX_POP3_STAT 9
+#define NGX_POP3_LIST 10
+#define NGX_POP3_RETR 11
+#define NGX_POP3_DELE 12
+#define NGX_POP3_RSET 13
+#define NGX_POP3_TOP 14
+#define NGX_POP3_UIDL 15
+
+
+#define NGX_IMAP_LOGIN 1
+#define NGX_IMAP_LOGOUT 2
+#define NGX_IMAP_CAPABILITY 3
+#define NGX_IMAP_NOOP 4
+#define NGX_IMAP_STARTTLS 5
+
+#define NGX_IMAP_NEXT 6
+
+#define NGX_IMAP_AUTHENTICATE 7
+
+
+#define NGX_SMTP_HELO 1
+#define NGX_SMTP_EHLO 2
+#define NGX_SMTP_AUTH 3
+#define NGX_SMTP_QUIT 4
+#define NGX_SMTP_NOOP 5
+#define NGX_SMTP_MAIL 6
+#define NGX_SMTP_RSET 7
+#define NGX_SMTP_RCPT 8
+#define NGX_SMTP_DATA 9
+#define NGX_SMTP_VRFY 10
+#define NGX_SMTP_EXPN 11
+#define NGX_SMTP_HELP 12
+#define NGX_SMTP_STARTTLS 13
#define NGX_MAIL_AUTH_PLAIN 0
@@ -285,6 +300,8 @@ typedef struct {
#define ngx_mail_conf_get_module_main_conf(cf, module) \
((ngx_mail_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
+#define ngx_mail_conf_get_module_srv_conf(cf, module) \
+ ((ngx_mail_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index]
void ngx_mail_init_connection(ngx_connection_t *c);
diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c
index c7e0fc038..906152ce8 100644
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -21,6 +21,9 @@ typedef struct {
ngx_str_t header;
ngx_array_t *headers;
+
+ u_char *file;
+ ngx_uint_t line;
} ngx_mail_auth_http_conf_t;
@@ -1248,18 +1251,10 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
static ngx_int_t
ngx_mail_auth_http_escape(ngx_pool_t *pool, ngx_str_t *text, ngx_str_t *escaped)
{
- u_char ch, *p;
- ngx_uint_t i, n;
-
- n = 0;
-
- for (i = 0; i < text->len; i++) {
- ch = text->data[i];
+ u_char *p;
+ uintptr_t n;
- if (ch == CR || ch == LF) {
- n++;
- }
- }
+ n = ngx_escape_uri(NULL, text->data, text->len, NGX_ESCAPE_MAIL_AUTH);
if (n == 0) {
*escaped = *text;
@@ -1273,27 +1268,9 @@ ngx_mail_auth_http_escape(ngx_pool_t *pool, ngx_str_t *text, ngx_str_t *escaped)
return NGX_ERROR;
}
- escaped->data = p;
-
- for (i = 0; i < text->len; i++) {
- ch = text->data[i];
-
- if (ch == CR) {
- *p++ = '%';
- *p++ = '0';
- *p++ = 'D';
- continue;
- }
-
- if (ch == LF) {
- *p++ = '%';
- *p++ = '0';
- *p++ = 'A';
- continue;
- }
+ (void) ngx_escape_uri(p, text->data, text->len, NGX_ESCAPE_MAIL_AUTH);
- *p++ = ch;
- }
+ escaped->data = p;
return NGX_OK;
}
@@ -1311,6 +1288,9 @@ ngx_mail_auth_http_create_conf(ngx_conf_t *cf)
ahcf->timeout = NGX_CONF_UNSET_MSEC;
+ ahcf->file = cf->conf_file->file.name.data;
+ ahcf->line = cf->conf_file->line;
+
return ahcf;
}
@@ -1330,6 +1310,14 @@ ngx_mail_auth_http_merge_conf(ngx_conf_t *cf, void *parent, void *child)
conf->peer = prev->peer;
conf->host_header = prev->host_header;
conf->uri = prev->uri;
+
+ if (conf->peer == NULL) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no \"http_auth\" is defined for server in %s:%ui",
+ conf->file, conf->line);
+
+ return NGX_CONF_ERROR;
+ }
}
ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
@@ -1383,11 +1371,18 @@ ngx_mail_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
u.uri_part = 1;
u.one_addr = 1;
+ if (ngx_strncmp(u.url.data, "http://", 7) == 0) {
+ u.url.len -= 7;
+ u.url.data += 7;
+ }
+
if (ngx_parse_url(cf, &u) != NGX_OK) {
if (u.err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"%s in auth_http \"%V\"", u.err, &u.url);
}
+
+ return NGX_CONF_ERROR;
}
ahcf->peer = u.addrs;
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
index ba62d5553..9b9e20f65 100644
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -54,6 +54,14 @@ static ngx_conf_bitmask_t ngx_pop3_auth_methods[] = {
};
+static ngx_conf_bitmask_t ngx_imap_auth_methods[] = {
+ { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED },
+ { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED },
+ { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED },
+ { ngx_null_string, 0 }
+};
+
+
static ngx_conf_bitmask_t ngx_smtp_auth_methods[] = {
{ ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED },
{ ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED },
@@ -62,6 +70,14 @@ static ngx_conf_bitmask_t ngx_smtp_auth_methods[] = {
};
+static ngx_str_t ngx_imap_auth_methods_names[] = {
+ ngx_string("AUTH=PLAIN"),
+ ngx_string("AUTH=LOGIN"),
+ ngx_null_string, /* APOP */
+ ngx_string("AUTH=CRAM-MD5")
+};
+
+
static ngx_str_t ngx_smtp_auth_methods_names[] = {
ngx_string("PLAIN"),
ngx_string("LOGIN"),
@@ -172,6 +188,13 @@ static ngx_command_t ngx_mail_core_commands[] = {
offsetof(ngx_mail_core_srv_conf_t, pop3_auth_methods),
&ngx_pop3_auth_methods },
+ { ngx_string("imap_auth"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
+ ngx_conf_set_bitmask_slot,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_core_srv_conf_t, imap_auth_methods),
+ &ngx_imap_auth_methods },
+
{ ngx_string("smtp_auth"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
ngx_conf_set_bitmask_slot,
@@ -278,7 +301,7 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_mail_core_srv_conf_t *prev = parent;
ngx_mail_core_srv_conf_t *conf = child;
- u_char *p;
+ u_char *p, *auth;
size_t size, stls_only_size;
ngx_str_t *c, *d;
ngx_uint_t i, m;
@@ -297,6 +320,11 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
(NGX_CONF_BITMASK_SET
|NGX_MAIL_AUTH_PLAIN_ENABLED));
+ ngx_conf_merge_bitmask_value(conf->imap_auth_methods,
+ prev->imap_auth_methods,
+ (NGX_CONF_BITMASK_SET
+ |NGX_MAIL_AUTH_PLAIN_ENABLED));
+
ngx_conf_merge_bitmask_value(conf->smtp_auth_methods,
prev->smtp_auth_methods,
(NGX_CONF_BITMASK_SET
@@ -463,6 +491,15 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
size += 1 + c[i].len;
}
+ for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
+ m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
+ m <<= 1, i++)
+ {
+ if (m & conf->imap_auth_methods) {
+ size += 1 + ngx_imap_auth_methods_names[i].len;
+ }
+ }
+
p = ngx_palloc(cf->pool, size);
if (p == NULL) {
return NGX_CONF_ERROR;
@@ -478,6 +515,19 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
p = ngx_cpymem(p, c[i].data, c[i].len);
}
+ auth = p;
+
+ for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
+ m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
+ m <<= 1, i++)
+ {
+ if (m & conf->imap_auth_methods) {
+ *p++ = ' ';
+ p = ngx_cpymem(p, ngx_imap_auth_methods_names[i].data,
+ ngx_imap_auth_methods_names[i].len);
+ }
+ }
+
*p++ = CR; *p = LF;
@@ -497,7 +547,8 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
*p++ = CR; *p = LF;
- size += sizeof(" LOGINDISABLED") - 1;
+ size = (auth - conf->imap_capability.data) + sizeof(CRLF) - 1
+ + sizeof(" STARTTLS LOGINDISABLED") - 1;
p = ngx_palloc(cf->pool, size);
if (p == NULL) {
@@ -507,9 +558,10 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
conf->imap_starttls_only_capability.len = size;
conf->imap_starttls_only_capability.data = p;
- p = ngx_cpymem(p, conf->imap_starttls_capability.data,
- conf->imap_starttls_capability.len - (sizeof(CRLF) - 1));
- p = ngx_cpymem(p, " LOGINDISABLED", sizeof(" LOGINDISABLED") - 1);
+ p = ngx_cpymem(p, conf->imap_capability.data,
+ auth - conf->imap_capability.data);
+ p = ngx_cpymem(p, " STARTTLS LOGINDISABLED",
+ sizeof(" STARTTLS LOGINDISABLED") - 1);
*p++ = CR; *p = LF;
@@ -582,6 +634,8 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
*p++ = CR; *p++ = LF;
}
+ auth = p;
+
*p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' ';
*p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H';
@@ -598,6 +652,42 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
*p++ = CR; *p = LF;
+ size += sizeof("250 STARTTLS" CRLF) - 1;
+
+ p = ngx_palloc(cf->pool, size);
+ if (p == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ conf->smtp_starttls_capability.len = size;
+ conf->smtp_starttls_capability.data = p;
+
+ p = ngx_cpymem(p, conf->smtp_capability.data,
+ conf->smtp_capability.len);
+
+ p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1);
+ *p++ = CR; *p = LF;
+
+ p = conf->smtp_starttls_capability.data
+ + (auth - conf->smtp_capability.data) + 3;
+ *p = '-';
+
+ size = (auth - conf->smtp_capability.data)
+ + sizeof("250 STARTTLS" CRLF) - 1;
+
+ p = ngx_palloc(cf->pool, size);
+ if (p == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ conf->smtp_starttls_only_capability.len = size;
+ conf->smtp_starttls_only_capability.data = p;
+
+ p = ngx_cpymem(p, conf->smtp_capability.data,
+ auth - conf->smtp_capability.data);
+
+ ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1);
+
return NGX_CONF_OK;
}
diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c
index 8fee001bb..9c83bdbc8 100644
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -280,6 +280,9 @@ ngx_mail_init_session(ngx_connection_t *c)
&& (cscf->pop3_auth_methods
& (NGX_MAIL_AUTH_APOP_ENABLED|NGX_MAIL_AUTH_CRAM_MD5_ENABLED)))
+ || (s->protocol == NGX_MAIL_IMAP_PROTOCOL
+ && (cscf->imap_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED))
+
|| (s->protocol == NGX_MAIL_SMTP_PROTOCOL
&& (cscf->smtp_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)))
{
@@ -985,7 +988,7 @@ ngx_imap_auth_state(ngx_event_t *rev)
{
u_char *p, *last, *text, *dst, *src, *end;
ssize_t text_len, last_len;
- ngx_str_t *arg;
+ ngx_str_t *arg, salt;
ngx_int_t rc;
ngx_uint_t tag, i;
ngx_connection_t *c;
@@ -1055,113 +1058,342 @@ ngx_imap_auth_state(ngx_event_t *rev)
s->backslash = 0;
}
- switch (s->command) {
+ switch (s->mail_state) {
+
+ case ngx_imap_start:
+
+ switch (s->command) {
- case NGX_IMAP_LOGIN:
+ case NGX_IMAP_LOGIN:
#if (NGX_MAIL_SSL)
- if (c->ssl == NULL) {
- sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
- if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
- rc = NGX_MAIL_PARSE_INVALID_COMMAND;
- break;
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
}
- }
#endif
- arg = s->args.elts;
+ arg = s->args.elts;
- if (s->args.nelts == 2 && arg[0].len) {
+ if (s->args.nelts == 2 && arg[0].len) {
- s->login.len = arg[0].len;
- s->login.data = ngx_palloc(c->pool, s->login.len);
- if (s->login.data == NULL) {
- ngx_mail_session_internal_server_error(s);
- return;
- }
+ s->login.len = arg[0].len;
+ s->login.data = ngx_palloc(c->pool, s->login.len);
+ if (s->login.data == NULL) {
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
- ngx_memcpy(s->login.data, arg[0].data, s->login.len);
+ ngx_memcpy(s->login.data, arg[0].data, s->login.len);
- s->passwd.len = arg[1].len;
- s->passwd.data = ngx_palloc(c->pool, s->passwd.len);
- if (s->passwd.data == NULL) {
- ngx_mail_session_internal_server_error(s);
- return;
- }
+ s->passwd.len = arg[1].len;
+ s->passwd.data = ngx_palloc(c->pool, s->passwd.len);
+ if (s->passwd.data == NULL) {
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
- ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len);
+ ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len);
#if (NGX_DEBUG_MAIL_PASSWD)
- ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
- "imap login:\"%V\" passwd:\"%V\"",
- &s->login, &s->passwd);
+ ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap login:\"%V\" passwd:\"%V\"",
+ &s->login, &s->passwd);
#else
- ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
- "imap login:\"%V\"", &s->login);
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap login:\"%V\"", &s->login);
#endif
- ngx_mail_do_auth(s);
- return;
- }
+ ngx_mail_do_auth(s);
+ return;
+ }
- rc = NGX_MAIL_PARSE_INVALID_COMMAND;
- break;
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
- case NGX_IMAP_CAPABILITY:
- cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+ case NGX_IMAP_AUTHENTICATE:
#if (NGX_MAIL_SSL)
- if (c->ssl == NULL) {
- sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+ }
+#endif
- if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
- text_len = cscf->imap_starttls_capability.len;
- text = cscf->imap_starttls_capability.data;
+ if (s->args.nelts != 1) {
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
break;
}
- if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
- text_len = cscf->imap_starttls_only_capability.len;
- text = cscf->imap_starttls_only_capability.data;
+ arg = s->args.elts;
+
+ if (arg[0].len == 5) {
+
+ if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5)
+ == 0)
+ {
+
+ s->mail_state = ngx_imap_auth_login_username;
+
+ last_len = sizeof(pop3_username) - 1;
+ last = pop3_username;
+ tag = 0;
+
+ break;
+
+ } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN",
+ 5)
+ == 0)
+ {
+
+ s->mail_state = ngx_imap_auth_plain;
+
+ last_len = sizeof(pop3_next) - 1;
+ last = pop3_next;
+ tag = 0;
+
+ break;
+ }
+
+ } else if (arg[0].len == 8
+ && ngx_strncasecmp(arg[0].data,
+ (u_char *) "CRAM-MD5", 8)
+ == 0)
+ {
+ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+ if (!(cscf->imap_auth_methods
+ & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)
+ || s->args.nelts != 1)
+ {
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+ s->mail_state = ngx_imap_auth_cram_md5;
+
+ last = ngx_palloc(c->pool,
+ sizeof("+ " CRLF) - 1
+ + ngx_base64_encoded_length(s->salt.len));
+ if (last == NULL) {
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ last[0] = '+'; last[1]= ' ';
+ salt.data = &last[2];
+ s->salt.len -= 2;
+
+ ngx_encode_base64(&salt, &s->salt);
+
+ s->salt.len += 2;
+ last_len = 2 + salt.len;
+ last[last_len++] = CR; last[last_len++] = LF;
+ tag = 0;
+
break;
}
- }
+
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+
+ case NGX_IMAP_CAPABILITY:
+ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+#if (NGX_MAIL_SSL)
+
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
+ text_len = cscf->imap_starttls_capability.len;
+ text = cscf->imap_starttls_capability.data;
+ break;
+ }
+
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+ text_len = cscf->imap_starttls_only_capability.len;
+ text = cscf->imap_starttls_only_capability.data;
+ break;
+ }
+ }
#endif
- text_len = cscf->imap_capability.len;
- text = cscf->imap_capability.data;
- break;
+ text_len = cscf->imap_capability.len;
+ text = cscf->imap_capability.data;
+ break;
- case NGX_IMAP_LOGOUT:
- s->quit = 1;
- text = imap_bye;
- text_len = sizeof(imap_bye) - 1;
- break;
+ case NGX_IMAP_LOGOUT:
+ s->quit = 1;
+ text = imap_bye;
+ text_len = sizeof(imap_bye) - 1;
+ break;
- case NGX_IMAP_NOOP:
- break;
+ case NGX_IMAP_NOOP:
+ break;
#if (NGX_MAIL_SSL)
- case NGX_IMAP_STARTTLS:
- if (c->ssl == NULL) {
- sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
- if (sslcf->starttls) {
- c->read->handler = ngx_mail_starttls_handler;
- break;
+ case NGX_IMAP_STARTTLS:
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+ if (sslcf->starttls) {
+ c->read->handler = ngx_mail_starttls_handler;
+ break;
+ }
}
+
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+#endif
+
+ default:
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+ break;
+
+ case ngx_imap_auth_login_username:
+ arg = s->args.elts;
+ s->mail_state = ngx_imap_auth_login_password;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth login username: \"%V\"", &arg[0]);
+
+ s->login.data = ngx_palloc(c->pool,
+ ngx_base64_decoded_length(arg[0].len));
+ if (s->login.data == NULL){
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent invalid base64 encoding "
+ "in AUTH LOGIN command");
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
}
- rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth login username: \"%V\"", &s->login);
+
+ last_len = sizeof(pop3_password) - 1;
+ last = pop3_password;
+ tag = 0;
+
break;
+
+ case ngx_imap_auth_login_password:
+ arg = s->args.elts;
+
+#if (NGX_DEBUG_MAIL_PASSWD)
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth login password: \"%V\"", &arg[0]);
+#endif
+
+ s->passwd.data = ngx_palloc(c->pool,
+ ngx_base64_decoded_length(arg[0].len));
+ if (s->passwd.data == NULL){
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent invalid base64 encoding "
+ "in AUTH LOGIN command");
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+#if (NGX_DEBUG_MAIL_PASSWD)
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth login password: \"%V\"", &s->passwd);
#endif
- default:
- rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ ngx_mail_do_auth(s);
+ return;
+
+ case ngx_imap_auth_plain:
+ arg = s->args.elts;
+
+ rc = ngx_mail_decode_auth_plain(s, &arg[0]);
+
+ if (rc == NGX_OK) {
+ ngx_mail_do_auth(s);
+ return;
+ }
+
+ if (rc == NGX_ERROR) {
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ /* rc == NGX_MAIL_PARSE_INVALID_COMMAND */
+
break;
+
+ case ngx_imap_auth_cram_md5:
+ arg = s->args.elts;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth cram-md5: \"%V\"", &arg[0]);
+
+ s->login.data = ngx_palloc(c->pool,
+ ngx_base64_decoded_length(arg[0].len));
+ if (s->login.data == NULL){
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent invalid base64 encoding "
+ "in AUTH CRAM-MD5 command");
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+ p = s->login.data;
+ last = p + s->login.len;
+
+ while (p < last) {
+ if (*p++ == ' ') {
+ s->login.len = p - s->login.data - 1;
+ s->passwd.len = last - p;
+ s->passwd.data = p;
+ break;
+ }
+ }
+
+ if (s->passwd.len != 32) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent invalid CRAM-MD5 hash "
+ "in AUTH CRAM-MD5 command");
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth cram-md5: \"%V\" \"%V\"",
+ &s->login, &s->passwd);
+
+ s->auth_method = NGX_MAIL_AUTH_CRAM_MD5;
+
+ ngx_mail_do_auth(s);
+ return;
}
} else if (rc == NGX_IMAP_NEXT) {
@@ -1171,6 +1403,8 @@ ngx_imap_auth_state(ngx_event_t *rev)
}
if (rc == NGX_MAIL_PARSE_INVALID_COMMAND) {
+ s->mail_state = ngx_imap_start;
+ s->state = 0;
last = imap_invalid_command;
last_len = sizeof(imap_invalid_command) - 1;
}
@@ -1209,9 +1443,18 @@ ngx_imap_auth_state(ngx_event_t *rev)
if (rc != NGX_IMAP_NEXT) {
s->args.nelts = 0;
- s->buffer->pos = s->buffer->start;
- s->buffer->last = s->buffer->start;
- s->tag.len = 0;
+
+ if (s->state) {
+ /* preserve tag */
+ s->arg_start = s->buffer->start + s->tag.len;
+ s->buffer->pos = s->arg_start;
+ s->buffer->last = s->arg_start;
+
+ } else {
+ s->buffer->pos = s->buffer->start;
+ s->buffer->last = s->buffer->start;
+ s->tag.len = 0;
+ }
}
ngx_mail_send(c->write);
@@ -1229,6 +1472,9 @@ ngx_smtp_auth_state(ngx_event_t *rev)
ngx_connection_t *c;
ngx_mail_session_t *s;
ngx_mail_core_srv_conf_t *cscf;
+#if (NGX_MAIL_SSL)
+ ngx_mail_ssl_conf_t *sslcf;
+#endif
c = rev->data;
s = c->data;
@@ -1295,6 +1541,26 @@ ngx_smtp_auth_state(ngx_event_t *rev)
} else {
s->esmtp = 1;
+
+#if (NGX_MAIL_SSL)
+
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
+ size = cscf->smtp_starttls_capability.len;
+ text = cscf->smtp_starttls_capability.data;
+ break;
+ }
+
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+ size = cscf->smtp_starttls_only_capability.len;
+ text = cscf->smtp_starttls_only_capability.data;
+ break;
+ }
+ }
+#endif
+
size = cscf->smtp_capability.len;
text = cscf->smtp_capability.data;
}
@@ -1303,6 +1569,18 @@ ngx_smtp_auth_state(ngx_event_t *rev)
case NGX_SMTP_AUTH:
+#if (NGX_MAIL_SSL)
+
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+ }
+#endif
+
if (s->args.nelts == 0) {
text = smtp_invalid_argument;
size = sizeof(smtp_invalid_argument) - 1;
@@ -1453,6 +1731,38 @@ ngx_smtp_auth_state(ngx_event_t *rev)
text = smtp_ok;
size = sizeof(smtp_ok) - 1;
break;
+
+#if (NGX_MAIL_SSL)
+
+ case NGX_SMTP_STARTTLS:
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s,
+ ngx_mail_ssl_module);
+ if (sslcf->starttls) {
+ c->read->handler = ngx_mail_starttls_handler;
+
+ /*
+ * RFC3207 requires us to discard any knowledge
+ * obtained from client before STARTTLS.
+ */
+
+ s->smtp_helo.len = 0;
+ s->smtp_helo.data = NULL;
+
+ text = smtp_ok;
+ size = sizeof(smtp_ok) - 1;
+
+ break;
+ }
+ }
+
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+#endif
+
+ default:
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
}
break;
@@ -1790,6 +2100,10 @@ ngx_mail_close_connection(ngx_connection_t *c)
#endif
+#if (NGX_STAT_STUB)
+ ngx_atomic_fetch_add(ngx_stat_active, -1);
+#endif
+
c->destroyed = 1;
pool = c->pool;
diff --git a/src/mail/ngx_mail_parse.c b/src/mail/ngx_mail_parse.c
index 7bab21b57..c959b44b2 100644
--- a/src/mail/ngx_mail_parse.c
+++ b/src/mail/ngx_mail_parse.c
@@ -354,6 +354,27 @@ ngx_int_t ngx_imap_parse_command(ngx_mail_session_t *s)
}
break;
+ case 12:
+ if ((c[0] == 'A'|| c[0] == 'a')
+ && (c[1] == 'U'|| c[1] == 'u')
+ && (c[2] == 'T'|| c[2] == 't')
+ && (c[3] == 'H'|| c[3] == 'h')
+ && (c[4] == 'E'|| c[4] == 'e')
+ && (c[5] == 'N'|| c[5] == 'n')
+ && (c[6] == 'T'|| c[6] == 't')
+ && (c[7] == 'I'|| c[7] == 'i')
+ && (c[8] == 'C'|| c[8] == 'c')
+ && (c[9] == 'A'|| c[9] == 'a')
+ && (c[10] == 'T'|| c[10] == 't')
+ && (c[11] == 'E'|| c[11] == 'e'))
+ {
+ s->command = NGX_IMAP_AUTHENTICATE;
+
+ } else {
+ goto invalid;
+ }
+ break;
+
default:
goto invalid;
}
@@ -413,6 +434,10 @@ ngx_int_t ngx_imap_parse_command(ngx_mail_session_t *s)
break;
case sw_argument:
+ if (ch == ' ' && s->quoted) {
+ break;
+ }
+
switch (ch) {
case '"':
if (!s->quoted) {
@@ -573,7 +598,7 @@ done:
s->literal_len = 0;
}
- s->state = sw_start;
+ s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument;
return NGX_OK;
@@ -646,10 +671,43 @@ ngx_int_t ngx_smtp_parse_command(ngx_mail_session_t *s)
{
s->command = NGX_SMTP_RSET;
+ } else if (c0 == 'R' && c1 == 'C' && c2 == 'P' && c3 == 'T')
+ {
+ s->command = NGX_SMTP_RCPT;
+
+ } else if (c0 == 'V' && c1 == 'R' && c2 == 'F' && c3 == 'Y')
+ {
+ s->command = NGX_SMTP_VRFY;
+
+ } else if (c0 == 'E' && c1 == 'X' && c2 == 'P' && c3 == 'N')
+ {
+ s->command = NGX_SMTP_EXPN;
+
+ } else if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'P')
+ {
+ s->command = NGX_SMTP_HELP;
+
} else {
goto invalid;
}
+#if (NGX_MAIL_SSL)
+ } else if (p - c == 8) {
+ if ((c[0] == 'S'|| c[0] == 's')
+ && (c[1] == 'T'|| c[1] == 't')
+ && (c[2] == 'A'|| c[2] == 'a')
+ && (c[3] == 'R'|| c[3] == 'r')
+ && (c[4] == 'T'|| c[4] == 't')
+ && (c[5] == 'T'|| c[5] == 't')
+ && (c[6] == 'L'|| c[6] == 'l')
+ && (c[7] == 'S'|| c[7] == 's'))
+ {
+ s->command = NGX_SMTP_STARTTLS;
+
+ } else {
+ goto invalid;
+ }
+#endif
} else {
goto invalid;
}
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index a4e973dc3..06cdb863c 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -77,6 +77,9 @@
#endif
+#define NGX_LISTEN_BACKLOG -1
+
+
#if (defined SO_ACCEPTFILTER && !defined NGX_HAVE_DEFERRED_ACCEPT)
#define NGX_HAVE_DEFERRED_ACCEPT 1
#endif
diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h
index 980e05d67..3e0475ffc 100644
--- a/src/os/unix/ngx_linux_config.h
+++ b/src/os/unix/ngx_linux_config.h
@@ -78,6 +78,9 @@ extern ssize_t sendfile(int s, int fd, int32_t *offset, size_t size);
#endif
+#define NGX_LISTEN_BACKLOG 511
+
+
#if defined TCP_DEFER_ACCEPT && !defined NGX_HAVE_DEFERRED_ACCEPT
#define NGX_HAVE_DEFERRED_ACCEPT 1
#endif
diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h
index 8a9509960..f79657654 100644
--- a/src/os/unix/ngx_posix_config.h
+++ b/src/os/unix/ngx_posix_config.h
@@ -88,6 +88,9 @@
#endif
+#define NGX_LISTEN_BACKLOG 511
+
+
#if (__FreeBSD__) && (__FreeBSD_version < 400017)
#include <sys/param.h> /* ALIGN() */
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index 90993966d..26eb1e1fb 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -62,6 +62,11 @@ u_long cpu_affinity;
static u_char master_process[] = "master process";
+static ngx_cycle_t ngx_exit_cycle;
+static ngx_log_t ngx_exit_log;
+static ngx_open_file_t ngx_exit_log_file;
+
+
void
ngx_master_process_cycle(ngx_cycle_t *cycle)
{
@@ -649,13 +654,21 @@ ngx_master_process_exit(ngx_cycle_t *cycle)
}
/*
- * we do not destroy cycle->pool here because a signal handler
- * that uses cycle->log can be called at this point
+ * Copy ngx_cycle->log related data to the special static exit cycle,
+ * log, and log file structures enough to allow a signal handler to log.
+ * The handler may be called when standard ngx_cycle->log allocated from
+ * ngx_cycle->pool is already destroyed.
*/
-#if 0
+ ngx_exit_log_file.fd = ngx_cycle->log->file->fd;
+
+ ngx_exit_log = *ngx_cycle->log;
+ ngx_exit_log.file = &ngx_exit_log_file;
+
+ ngx_exit_cycle.log = &ngx_exit_log;
+ ngx_cycle = &ngx_exit_cycle;
+
ngx_destroy_pool(cycle->pool);
-#endif
exit(0);
}
@@ -792,49 +805,49 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority)
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
- if (geteuid() == 0) {
- if (priority && ccf->priority != 0) {
- if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
- "setpriority(%d) failed", ccf->priority);
- }
+ if (priority && ccf->priority != 0) {
+ if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "setpriority(%d) failed", ccf->priority);
}
+ }
- if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
- rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
- rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;
+ if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
+ rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
+ rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;
- if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
- "setrlimit(RLIMIT_NOFILE, %i) failed",
- ccf->rlimit_nofile);
- }
+ if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "setrlimit(RLIMIT_NOFILE, %i) failed",
+ ccf->rlimit_nofile);
}
+ }
- if (ccf->rlimit_core != NGX_CONF_UNSET_SIZE) {
- rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
- rlmt.rlim_max = (rlim_t) ccf->rlimit_core;
+ if (ccf->rlimit_core != NGX_CONF_UNSET_SIZE) {
+ rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
+ rlmt.rlim_max = (rlim_t) ccf->rlimit_core;
- if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
- "setrlimit(RLIMIT_CORE, %i) failed",
- ccf->rlimit_core);
- }
+ if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "setrlimit(RLIMIT_CORE, %i) failed",
+ ccf->rlimit_core);
}
+ }
#ifdef RLIMIT_SIGPENDING
- if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
- rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
- rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;
-
- if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
- "setrlimit(RLIMIT_SIGPENDING, %i) failed",
- ccf->rlimit_sigpending);
- }
+ if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
+ rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
+ rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;
+
+ if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "setrlimit(RLIMIT_SIGPENDING, %i) failed",
+ ccf->rlimit_sigpending);
}
+ }
#endif
+ if (geteuid() == 0) {
if (setgid(ccf->group) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"setgid(%d) failed", ccf->group);
@@ -996,13 +1009,23 @@ ngx_worker_process_exit(ngx_cycle_t *cycle)
}
/*
- * we do not destroy cycle->pool here because a signal handler
- * that uses cycle->log can be called at this point
+ * Copy ngx_cycle->log related data to the special static exit cycle,
+ * log, and log file structures enough to allow a signal handler to log.
+ * The handler may be called when standard ngx_cycle->log allocated from
+ * ngx_cycle->pool is already destroyed.
*/
-#if 0
+ ngx_exit_log_file.fd = ngx_cycle->log->file->fd;
+
+ ngx_exit_log = *ngx_cycle->log;
+ ngx_exit_log.file = &ngx_exit_log_file;
+
+ ngx_exit_cycle.log = &ngx_exit_log;
+ ngx_cycle = &ngx_exit_cycle;
+
ngx_destroy_pool(cycle->pool);
-#endif
+
+ ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "exit");
exit(0);
}
diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h
index 9183bb360..989a30e2c 100644
--- a/src/os/unix/ngx_solaris_config.h
+++ b/src/os/unix/ngx_solaris_config.h
@@ -82,6 +82,9 @@
#endif
+#define NGX_LISTEN_BACKLOG 511
+
+
#ifndef NGX_HAVE_INHERITED_NONBLOCK
#define NGX_HAVE_INHERITED_NONBLOCK 1
#endif