+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
+éÚÍÅÎÅÎÉÑ × 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,
#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"
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)) {
{
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
{
switch (c->log_error) {
+ case NGX_ERROR_IGNORE_EINVAL:
case NGX_ERROR_IGNORE_ECONNRESET:
case NGX_ERROR_INFO:
level = NGX_LOG_INFO;
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;
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;
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;
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;
}
return;
}
- ngx_log_abort(err, ngx_lock_fd_n " failed");
+ ngx_log_abort(err, ngx_lock_fd_n " %s failed", mtx->name);
}
return;
}
- ngx_log_abort(err, ngx_unlock_fd_n " failed");
+ ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name);
}
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;
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;
{ 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 },
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;
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;
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);
}
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;
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;
+}
path.len = e.pos - path.data;
- *e.pos++ = '\0';
+ *e.pos = '\0';
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.7.41';
+our $VERSION = '0.7.42';
require XSLoader;
XSLoader::load('nginx', $VERSION);
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;
}
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);
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;
+ }
}
}
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) {
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)
{
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;
#if (NGX_HTTP_SSL)
unsigned ssl:1;
#endif
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+ unsigned ipv6only:2;
+#endif
int backlog;
int rcvbuf;
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;
#if (NGX_PCRE)
if (vn->nregex) {
+ size_t ncaptures;
ngx_int_t n;
ngx_uint_t i;
ngx_str_t name;
(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;
}