summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2009-03-16 07:24:30 +0000
committerJonathan Kolb <jon@b0g.us>2009-03-16 07:24:30 +0000
commitf7282cf06b6d8c64ca160877c5f46a6043e0f78a (patch)
tree3a9492920f77d4bddd1bd9c2359c954f3ffb8ee3
parentd3c9e5f56459032d10c0c86e04472fc97621999f (diff)
downloadnginx-0.7.42.tar.gz
Changes with nginx 0.7.42 16 Mar 2009v0.7.42
*) Change: now the "Invalid argument" error returned by setsockopt(TCP_NODELAY) on Solaris, is ignored. *) Change: now if a file specified in a "auth_basic_user_file" directive is absent, then the 405 error is returned instead of the 500 one. *) Feature: the "auth_basic_user_file" directive supports variables. Thanks to Kirill A. Korinskiy. *) Feature: the "listen" directive supports the "ipv6only" parameter. Thanks to Zhang Hua. *) Bugfix: in an "alias" directive with references to captures of regular expressions; the bug had appeared in 0.7.40. *) Bugfix: compatibility with Tru64 UNIX. Thanks to Dustin Marquess. *) Bugfix: nginx could not be built without PCRE library; the bug had appeared in 0.7.41.
-rw-r--r--CHANGES25
-rw-r--r--CHANGES.ru24
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_connection.c28
-rw-r--r--src/core/ngx_connection.h11
-rw-r--r--src/core/ngx_shmtx.h14
-rw-r--r--src/http/modules/ngx_http_auth_basic_module.c120
-rw-r--r--src/http/modules/ngx_http_index_module.c2
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http.c4
-rw-r--r--src/http/ngx_http_core_module.c55
-rw-r--r--src/http/ngx_http_core_module.h3
-rw-r--r--src/http/ngx_http_request.c9
13 files changed, 260 insertions, 39 deletions
diff --git a/CHANGES b/CHANGES
index 8129db739..7000d57f9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,29 @@
+Changes with nginx 0.7.42 16 Mar 2009
+
+ *) Change: now the "Invalid argument" error returned by
+ setsockopt(TCP_NODELAY) on Solaris, is ignored.
+
+ *) Change: now if a file specified in a "auth_basic_user_file"
+ directive is absent, then the 405 error is returned instead of the
+ 500 one.
+
+ *) Feature: the "auth_basic_user_file" directive supports variables.
+ Thanks to Kirill A. Korinskiy.
+
+ *) Feature: the "listen" directive supports the "ipv6only" parameter.
+ Thanks to Zhang Hua.
+
+ *) Bugfix: in an "alias" directive with references to captures of
+ regular expressions; the bug had appeared in 0.7.40.
+
+ *) Bugfix: compatibility with Tru64 UNIX.
+ Thanks to Dustin Marquess.
+
+ *) Bugfix: nginx could not be built without PCRE library; the bug had
+ appeared in 0.7.41.
+
+
Changes with nginx 0.7.41 11 Mar 2009
*) Bugfix: a segmentation fault might occur in worker process, if a
diff --git a/CHANGES.ru b/CHANGES.ru
index 575fa6c8c..d44de1157 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,28 @@
+Изменения в nginx 0.7.42 16.03.2009
+
+ *) Изменение: ошибка "Invalid argument", возвращаемая
+ setsockopt(TCP_NODELAY) на Solaris, теперь игнорируется.
+
+ *) Изменение: при отсутствии файла, указанного в директиве
+ auth_basic_user_file, теперь возвращается ошибка 403 вместо 500.
+
+ *) Добавление: директива auth_basic_user_file поддерживает переменные.
+ Спасибо Кириллу Коринскому.
+
+ *) Добавление: директива listen поддерживает параметр ipv6only.
+ Спасибо Zhang Hua.
+
+ *) Исправление: в директиве alias со ссылками на выделения в регулярных
+ выражениях; ошибка появилась в 0.7.40.
+
+ *) Исправление: совместимость с Tru64 UNIX.
+ Спасибо Dustin Marquess.
+
+ *) Исправление: nginx не собирался без библиотеки PCRE; ошибка
+ появилась в 0.7.41.
+
+
Изменения в nginx 0.7.41 11.03.2009
*) Исправление: в рабочем процессе мог произойти segmentation fault,
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 2c0406ca6..cc0945b53 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.7.41"
+#define NGINX_VERSION "0.7.42"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index f48eefbb0..f413ffbe8 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -282,6 +282,23 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
return NGX_ERROR;
}
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+
+ if (ls[i].sockaddr->sa_family == AF_INET6 && ls[i].ipv6only) {
+ int ipv6only;
+
+ ipv6only = (ls[i].ipv6only == 1);
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (const void *) &ipv6only, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
+ "setsockopt(IPV6_V6ONLY) %V failed, ignored",
+ &ls[i].addr_text);
+ }
+ }
+#endif
/* TODO: close on exit */
if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {
@@ -782,11 +799,15 @@ ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
{
ngx_uint_t level;
- if (err == NGX_ECONNRESET
- && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
- {
+ if (err == NGX_ECONNRESET && c->log_error == NGX_ERROR_IGNORE_ECONNRESET) {
+ return 0;
+ }
+
+#if (NGX_SOLARIS)
+ if (err == NGX_EINVAL && c->log_error == NGX_ERROR_IGNORE_EINVAL) {
return 0;
}
+#endif
if (err == 0
|| err == NGX_ECONNRESET
@@ -803,6 +824,7 @@ ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
{
switch (c->log_error) {
+ case NGX_ERROR_IGNORE_EINVAL:
case NGX_ERROR_IGNORE_ECONNRESET:
case NGX_ERROR_INFO:
level = NGX_LOG_INFO;
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index d9b80f941..cc6a92989 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -56,6 +56,10 @@ struct ngx_listening_s {
unsigned shared:1; /* shared between threads or processes */
unsigned addr_ntop:1;
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+ unsigned ipv6only:2;
+#endif
+
#if (NGX_HAVE_DEFERRED_ACCEPT)
unsigned deferred_accept:1;
unsigned delete_deferred:1;
@@ -69,10 +73,11 @@ struct ngx_listening_s {
typedef enum {
- NGX_ERROR_CRIT = 0,
+ NGX_ERROR_ALERT = 0,
NGX_ERROR_ERR,
NGX_ERROR_INFO,
- NGX_ERROR_IGNORE_ECONNRESET
+ NGX_ERROR_IGNORE_ECONNRESET,
+ NGX_ERROR_IGNORE_EINVAL
} ngx_connection_log_error_e;
@@ -131,7 +136,7 @@ struct ngx_connection_s {
unsigned buffered:8;
- unsigned log_error:2; /* ngx_connection_log_error_e */
+ unsigned log_error:3; /* ngx_connection_log_error_e */
unsigned single_connection:1;
unsigned unexpected_eof:1;
diff --git a/src/core/ngx_shmtx.h b/src/core/ngx_shmtx.h
index e6fb6aa31..57fe0b9f5 100644
--- a/src/core/ngx_shmtx.h
+++ b/src/core/ngx_shmtx.h
@@ -57,7 +57,15 @@ ngx_shmtx_trylock(ngx_shmtx_t *mtx)
return 0;
}
- ngx_log_abort(err, ngx_trylock_fd_n " failed");
+#if __osf__ /* Tru64 UNIX */
+
+ if (err == NGX_EACCESS) {
+ return 0;
+ }
+
+#endif
+
+ ngx_log_abort(err, ngx_trylock_fd_n " %s failed", mtx->name);
return 0;
}
@@ -74,7 +82,7 @@ ngx_shmtx_lock(ngx_shmtx_t *mtx)
return;
}
- ngx_log_abort(err, ngx_lock_fd_n " failed");
+ ngx_log_abort(err, ngx_lock_fd_n " %s failed", mtx->name);
}
@@ -89,7 +97,7 @@ ngx_shmtx_unlock(ngx_shmtx_t *mtx)
return;
}
- ngx_log_abort(err, ngx_unlock_fd_n " failed");
+ ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name);
}
diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c
index 1c2333990..7506f7fbe 100644
--- a/src/http/modules/ngx_http_auth_basic_module.c
+++ b/src/http/modules/ngx_http_auth_basic_module.c
@@ -13,13 +13,15 @@
typedef struct {
- ngx_str_t passwd;
+ ngx_str_t passwd;
} ngx_http_auth_basic_ctx_t;
typedef struct {
- ngx_str_t realm;
- ngx_str_t user_file;
+ ngx_str_t realm;
+ ngx_str_t user_file;
+ ngx_array_t *user_file_lengths;
+ ngx_array_t *user_file_values;
} ngx_http_auth_basic_loc_conf_t;
@@ -34,6 +36,8 @@ static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_http_auth_basic_init(ngx_conf_t *cf);
static char *ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data);
+static char *ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static ngx_conf_post_handler_pt ngx_http_auth_basic_p = ngx_http_auth_basic;
@@ -51,7 +55,7 @@ static ngx_command_t ngx_http_auth_basic_commands[] = {
{ ngx_string("auth_basic_user_file"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
+ ngx_http_auth_basic_user_file,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_auth_basic_loc_conf_t, user_file),
NULL },
@@ -98,8 +102,9 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
ssize_t n;
ngx_fd_t fd;
ngx_int_t rc;
- ngx_str_t pwd;
- ngx_uint_t i, login, left, passwd;
+ ngx_err_t err;
+ ngx_str_t pwd, user_file;
+ ngx_uint_t i, level, login, left, passwd;
ngx_file_t file;
ngx_http_auth_basic_ctx_t *ctx;
ngx_http_auth_basic_loc_conf_t *alcf;
@@ -137,18 +142,44 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- fd = ngx_open_file(alcf->user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
+ if (alcf->user_file_lengths) {
+ if (ngx_http_script_run(r, &user_file, alcf->user_file_lengths->elts, 1,
+ alcf->user_file_values->elts)
+ == NULL)
+ {
+ return NGX_ERROR;
+ }
+
+ user_file.data[--user_file.len] = '\0';
+
+ } else {
+ user_file = alcf->user_file;
+ }
+
+ fd = ngx_open_file(user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
if (fd == NGX_INVALID_FILE) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- ngx_open_file_n " \"%s\" failed", alcf->user_file.data);
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ err = ngx_errno;
+
+ if (err == NGX_ENOENT) {
+ level = NGX_LOG_ERR;
+ rc = NGX_HTTP_FORBIDDEN;
+
+ } else {
+ level = NGX_LOG_CRIT;
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ ngx_log_error(level, r->connection->log, err,
+ ngx_open_file_n " \"%s\" failed", user_file.data);
+
+ return rc;
}
ngx_memzero(&file, sizeof(ngx_file_t));
file.fd = fd;
- file.name = alcf->user_file;
+ file.name = user_file;
file.log = r->connection->log;
state = sw_login;
@@ -255,7 +286,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"user \"%V\" was not found in \"%V\"",
- &r->headers_in.user, &alcf->user_file);
+ &r->headers_in.user, &user_file);
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
}
@@ -370,13 +401,10 @@ ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->realm = prev->realm;
}
- if (conf->user_file.data) {
- if (ngx_conf_full_name(cf->cycle, &conf->user_file, 1) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- } else {
+ if (conf->user_file.data == NULL) {
conf->user_file = prev->user_file;
+ conf->user_file_lengths = prev->user_file_lengths;
+ conf->user_file_values = prev->user_file_values;
}
return NGX_CONF_OK;
@@ -433,3 +461,59 @@ ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data)
return NGX_CONF_OK;
}
+
+
+static char *
+ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_auth_basic_loc_conf_t *alcf = conf;
+
+ ngx_str_t *value;
+ ngx_uint_t n;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_script_compile_t sc;
+
+ clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+
+ if (alcf->user_file.data) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ alcf->user_file = value[1];
+
+ if (alcf->user_file.len == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid parameter \"%V\"", &alcf->user_file);
+ return NGX_CONF_ERROR;
+ }
+
+ if (alcf->user_file.data[0] != '$') {
+ if (ngx_conf_full_name(cf->cycle, &alcf->user_file, 1) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ n = ngx_http_script_variables_count(&alcf->user_file);
+
+ if (n == 0) {
+ return NGX_CONF_OK;
+ }
+
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = cf;
+ sc.source = &alcf->user_file;
+ sc.lengths = &alcf->user_file_lengths;
+ sc.values = &alcf->user_file_values;
+ sc.variables = n;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index f9ce84944..fd201056a 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -198,7 +198,7 @@ ngx_http_index_handler(ngx_http_request_t *r)
path.len = e.pos - path.data;
- *e.pos++ = '\0';
+ *e.pos = '\0';
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index a780ee43b..9979a727a 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.7.41';
+our $VERSION = '0.7.42';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 626686ca8..d519bf981 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1768,6 +1768,10 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
ls->deferred_accept = addr->listen_conf->deferred_accept;
#endif
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+ ls->ipv6only = addr->listen_conf->ipv6only;
+#endif
+
return ls;
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index a2d4e8688..66698d525 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1122,7 +1122,7 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r,
path.len = e.pos - path.data;
- *e.pos++ = '\0';
+ *e.pos = '\0';
if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) {
ngx_memcpy(name, name + alias, len - alias);
@@ -1378,13 +1378,15 @@ ngx_http_core_find_location(ngx_http_request_t *r)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"test location: ~ \"%V\"", &(*clcfp)->name);
- if ((*clcfp)->captures && r->captures == NULL) {
+ if ((*clcfp)->captures) {
len = (NGX_HTTP_MAX_CAPTURES + 1) * 3;
- r->captures = ngx_palloc(r->pool, len * sizeof(int));
if (r->captures == NULL) {
- return NGX_ERROR;
+ r->captures = ngx_palloc(r->pool, len * sizeof(int));
+ if (r->captures == NULL) {
+ return NGX_ERROR;
+ }
}
}
@@ -1672,13 +1674,11 @@ ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
return NULL;
}
- reserved += r->uri.len - alias + 1;
-
if (clcf->root_lengths == NULL) {
*root_length = clcf->root.len;
- path->len = clcf->root.len + reserved;
+ path->len = clcf->root.len + reserved + r->uri.len - alias + 1;
path->data = ngx_pnalloc(r->pool, path->len);
if (path->data == NULL) {
@@ -1688,7 +1688,7 @@ ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
last = ngx_copy(path->data, clcf->root.data, clcf->root.len);
} else {
- if (ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
+ if (ngx_http_script_run(r, path, clcf->root_lengths->elts, ++reserved,
clcf->root_values->elts)
== NULL)
{
@@ -3332,6 +3332,45 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue;
}
+ if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) {
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *) ls->sockaddr;
+
+ if (sa->sa_family == AF_INET6) {
+
+ if (ngx_strcmp(&value[n].data[10], "n") == 0) {
+ ls->conf.ipv6only = 1;
+
+ } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) {
+ ls->conf.ipv6only = 2;
+
+ } else {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid ipv6only flags \"%s\"",
+ &value[n].data[9]);
+ return NGX_CONF_ERROR;
+ }
+
+ ls->conf.bind = 1;
+
+ } else {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "ipv6only is not supported "
+ "on addr \"%s\", ignored",
+ ls->conf.addr);
+ }
+
+ continue;
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "bind ipv6only is not supported "
+ "on this platform");
+ return NGX_CONF_ERROR;
+#endif
+ }
+
if (ngx_strcmp(value[n].data, "ssl") == 0) {
#if (NGX_HTTP_SSL)
ls->conf.ssl = 1;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 7ad18edd2..705659d0a 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -44,6 +44,9 @@ typedef struct {
#if (NGX_HTTP_SSL)
unsigned ssl:1;
#endif
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+ unsigned ipv6only:2;
+#endif
int backlog;
int rcvbuf;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index c018d6868..0280c6380 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1611,7 +1611,6 @@ static ngx_int_t
ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len)
{
u_char *server;
- size_t ncaptures;
ngx_uint_t hash;
ngx_http_virtual_names_t *vn;
ngx_http_core_loc_conf_t *clcf;
@@ -1646,6 +1645,7 @@ ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len)
#if (NGX_PCRE)
if (vn->nregex) {
+ size_t ncaptures;
ngx_int_t n;
ngx_uint_t i;
ngx_str_t name;
@@ -2421,8 +2421,15 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
(const void *) &tcp_nodelay, sizeof(int))
== -1)
{
+#if (NGX_SOLARIS)
+ /* Solaris returns EINVAL if a socket has been shut down */
+ c->log_error = NGX_ERROR_IGNORE_EINVAL;
+#endif
+
ngx_connection_error(c, ngx_socket_errno,
"setsockopt(TCP_NODELAY) failed");
+
+ c->log_error = NGX_ERROR_INFO;
ngx_http_close_connection(c);
return;
}