summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES45
-rw-r--r--CHANGES.ru46
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_resolver.c16
-rw-r--r--src/event/ngx_event.c39
-rw-r--r--src/event/ngx_event.h6
-rw-r--r--src/event/ngx_event_accept.c103
-rw-r--r--src/event/ngx_event_openssl.c1
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c30
-rw-r--r--src/http/modules/ngx_http_flv_module.c2
-rw-r--r--src/http/modules/ngx_http_geo_module.c136
-rw-r--r--src/http/modules/ngx_http_geoip_module.c160
-rw-r--r--src/http/modules/ngx_http_gzip_static_module.c2
-rw-r--r--src/http/modules/ngx_http_mp4_module.c2
-rw-r--r--src/http/modules/ngx_http_realip_module.c138
-rw-r--r--src/http/modules/ngx_http_scgi_module.c2
-rw-r--r--src/http/modules/ngx_http_stub_status_module.c2
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c2
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_core_module.c104
-rw-r--r--src/http/ngx_http_core_module.h3
-rw-r--r--src/http/ngx_http_parse.c20
-rw-r--r--src/http/ngx_http_request.c41
-rw-r--r--src/http/ngx_http_script.c1
-rw-r--r--src/http/ngx_http_upstream_round_robin.c242
-rw-r--r--src/http/ngx_http_upstream_round_robin.h1
-rw-r--r--src/os/unix/ngx_errno.h2
27 files changed, 716 insertions, 436 deletions
diff --git a/CHANGES b/CHANGES
index 75026b6bc..209542216 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,49 @@
+Changes with nginx 1.2.1 05 Jun 2012
+
+ *) Security: now nginx/Windows ignores trailing dot in URI path
+ component, and does not allow URIs with ":$" in it.
+ Thanks to Vladimir Kochetkov, Positive Research Center.
+
+ *) Feature: the "debug_connection" directive now supports IPv6 addresses
+ and the "unix:" parameter.
+
+ *) Feature: the "set_real_ip_from" directive and the "proxy" parameter
+ of the "geo" directive now support IPv6 addresses.
+
+ *) Feature: the "real_ip_recursive", "geoip_proxy", and
+ "geoip_proxy_recursive" directives.
+
+ *) Feature: the "proxy_recursive" parameter of the "geo" directive.
+
+ *) Bugfix: a segmentation fault might occur in a worker process if the
+ "resolver" directive was used.
+
+ *) Bugfix: a segmentation fault might occur in a worker process if the
+ "fastcgi_pass", "scgi_pass", or "uwsgi_pass" directives were used and
+ backend returned incorrect response.
+
+ *) Bugfix: a segmentation fault might occur in a worker process if the
+ "rewrite" directive was used and new request arguments in a
+ replacement used variables.
+
+ *) Bugfix: nginx might hog CPU if the open file resource limit was
+ reached.
+
+ *) Bugfix: nginx might loop infinitely over backends if the
+ "proxy_next_upstream" directive with the "http_404" parameter was
+ used and there were backup servers specified in an upstream block.
+
+ *) Bugfix: adding the "down" parameter of the "server" directive might
+ cause unneeded client redistribution among backend servers if the
+ "ip_hash" directive was used.
+
+ *) Bugfix: socket leak.
+ Thanks to Yichun Zhang.
+
+ *) Bugfix: in the ngx_http_fastcgi_module.
+
+
Changes with nginx 1.2.0 23 Apr 2012
*) Bugfix: a segmentation fault might occur in a worker process if the
diff --git a/CHANGES.ru b/CHANGES.ru
index 9d6268807..63ac53e3c 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,50 @@
+Изменения в nginx 1.2.1 05.06.2012
+
+ *) Безопасность: теперь nginx/Windows игнорирует точку в конце
+ компонента URI и не разрешает URI, содержащие последовательность
+ ":$".
+ Спасибо Владимиру Кочеткову, Positive Research Center.
+
+ *) Добавление: директива debug_connection теперь поддерживает
+ IPv6-адреса и параметр "unix:".
+
+ *) Добавление: директива set_real_ip_from и параметр proxy директивы geo
+ теперь поддерживают IPv6-адреса.
+
+ *) Добавление: директивы real_ip_recursive, geoip_proxy и
+ geoip_proxy_recursive.
+
+ *) Добавление: параметр proxy_recursive директивы geo.
+
+ *) Исправление: в рабочем процессе мог произойти segmentation fault,
+ если использовалась директива resolver.
+
+ *) Исправление: в рабочем процессе мог произойти segmentation fault,
+ если использовались директивы fastcgi_pass, scgi_pass или uwsgi_pass
+ и бэкенд возвращал некорректный ответ.
+
+ *) Исправление: в рабочем процессе мог произойти segmentation fault,
+ если использовалась директива rewrite и в новых аргументах запроса в
+ строке замены использовались переменные.
+
+ *) Исправление: nginx мог нагружать процессор, если было достигнуто
+ ограничение на количество открытых файлов.
+
+ *) Исправление: при использовании директивы proxy_next_upstream с
+ параметром http_404 nginx мог бесконечно перебирать бэкенды, если в
+ блоке upstream был хотя бы один сервер с флагом backup.
+
+ *) Исправление: при использовании директивы ip_hash установка параметра
+ down директивы server могла приводить к ненужному перераспределению
+ клиентов между бэкендами.
+
+ *) Исправление: утечки сокетов.
+ Спасибо Yichun Zhang.
+
+ *) Исправление: в модуле ngx_http_fastcgi_module.
+
+
Изменения в nginx 1.2.0 23.04.2012
*) Исправление: в рабочем процессе мог произойти segmentation fault,
diff --git a/src/core/nginx.h b/src/core/nginx.h
index ca777f6d5..df7ab91e6 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1002000
-#define NGINX_VERSION "1.2.0"
+#define nginx_version 1002001
+#define NGINX_VERSION "1.2.1"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 02c484da6..edc43dce2 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -513,8 +513,10 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
/* lock alloc mutex */
- ngx_resolver_free_locked(r, rn->query);
- rn->query = NULL;
+ if (rn->query) {
+ ngx_resolver_free_locked(r, rn->query);
+ rn->query = NULL;
+ }
if (rn->cnlen) {
ngx_resolver_free_locked(r, rn->u.cname);
@@ -1409,6 +1411,9 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
ngx_resolver_free(r, addrs);
}
+ ngx_resolver_free(r, rn->query);
+ rn->query = NULL;
+
return;
} else if (cname) {
@@ -1441,6 +1446,9 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
(void) ngx_resolve_name_locked(r, ctx);
}
+ ngx_resolver_free(r, rn->query);
+ rn->query = NULL;
+
return;
}
@@ -1834,6 +1842,10 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
p--;
*p-- = '\0';
+ if (ctx->name.len == 0) {
+ return NGX_DECLINED;
+ }
+
for (s = ctx->name.data + ctx->name.len - 1; s >= ctx->name.data; s--) {
if (*s != '.') {
*p = *s;
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index a0a9d743b..c584dd87d 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -1064,38 +1064,34 @@ ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_int_t rc;
ngx_str_t *value;
- ngx_event_debug_t *dc;
struct hostent *h;
- ngx_cidr_t cidr;
+ ngx_cidr_t *cidr;
value = cf->args->elts;
- dc = ngx_array_push(&ecf->debug_connection);
- if (dc == NULL) {
+ cidr = ngx_array_push(&ecf->debug_connection);
+ if (cidr == NULL) {
return NGX_CONF_ERROR;
}
- rc = ngx_ptocidr(&value[1], &cidr);
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ if (ngx_strcmp(value[1].data, "unix:") == 0) {
+ cidr->family = AF_UNIX;
+ return NGX_CONF_OK;
+ }
+
+#endif
+
+ rc = ngx_ptocidr(&value[1], 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;
+ return NGX_CONF_OK;
}
if (rc == NGX_OK) {
-
- /* AF_INET only */
-
- if (cidr.family != AF_INET) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"debug_connection\" supports IPv4 only");
- return NGX_CONF_ERROR;
- }
-
- dc->mask = cidr.u.in.mask;
- dc->addr = cidr.u.in.addr;
-
return NGX_CONF_OK;
}
@@ -1107,8 +1103,9 @@ ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- dc->mask = 0xffffffff;
- dc->addr = *(in_addr_t *)(h->h_addr_list[0]);
+ cidr->family = AF_INET;
+ cidr->u.in.mask = 0xffffffff;
+ cidr->u.in.addr = *(in_addr_t *)(h->h_addr_list[0]);
#else
@@ -1142,7 +1139,7 @@ ngx_event_core_create_conf(ngx_cycle_t *cycle)
#if (NGX_DEBUG)
if (ngx_array_init(&ecf->debug_connection, cycle->pool, 4,
- sizeof(ngx_event_debug_t)) == NGX_ERROR)
+ sizeof(ngx_cidr_t)) == NGX_ERROR)
{
return NULL;
}
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index 8cc87ebff..2096da234 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -222,12 +222,6 @@ struct ngx_event_aio_s {
typedef struct {
- in_addr_t mask;
- in_addr_t addr;
-} ngx_event_debug_t;
-
-
-typedef struct {
ngx_int_t (*add)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
ngx_int_t (*del)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index a45afeb1f..6087d60da 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -21,6 +21,7 @@ ngx_event_accept(ngx_event_t *ev)
socklen_t socklen;
ngx_err_t err;
ngx_log_t *log;
+ ngx_uint_t level;
ngx_socket_t s;
ngx_event_t *rev, *wev;
ngx_listening_t *ls;
@@ -31,6 +32,14 @@ ngx_event_accept(ngx_event_t *ev)
static ngx_uint_t use_accept4 = 1;
#endif
+ if (ev->timedout) {
+ if (ngx_enable_accept_events((ngx_cycle_t *) ngx_cycle) != NGX_OK) {
+ return;
+ }
+
+ ev->timedout = 0;
+ }
+
ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
@@ -70,10 +79,17 @@ ngx_event_accept(ngx_event_t *ev)
return;
}
+ level = NGX_LOG_ALERT;
+
+ if (err == NGX_ECONNABORTED) {
+ level = NGX_LOG_ERR;
+
+ } else if (err == NGX_EMFILE || err == NGX_ENFILE) {
+ level = NGX_LOG_CRIT;
+ }
+
#if (NGX_HAVE_ACCEPT4)
- ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
- NGX_LOG_ERR : NGX_LOG_ALERT),
- ev->log, err,
+ ngx_log_error(level, ev->log, err,
use_accept4 ? "accept4() failed" : "accept() failed");
if (use_accept4 && err == NGX_ENOSYS) {
@@ -82,9 +98,7 @@ ngx_event_accept(ngx_event_t *ev)
continue;
}
#else
- ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
- NGX_LOG_ERR : NGX_LOG_ALERT),
- ev->log, err, "accept() failed");
+ ngx_log_error(level, ev->log, err, "accept() failed");
#endif
if (err == NGX_ECONNABORTED) {
@@ -97,6 +111,26 @@ ngx_event_accept(ngx_event_t *ev)
}
}
+ if (err == NGX_EMFILE || err == NGX_ENFILE) {
+ if (ngx_disable_accept_events((ngx_cycle_t *) ngx_cycle)
+ != NGX_OK)
+ {
+ return;
+ }
+
+ if (ngx_use_accept_mutex) {
+ if (ngx_accept_mutex_held) {
+ ngx_shmtx_unlock(&ngx_accept_mutex);
+ ngx_accept_mutex_held = 0;
+ }
+
+ ngx_accept_disabled = 1;
+
+ } else {
+ ngx_add_timer(ev, ecf->accept_mutex_delay);
+ }
+ }
+
return;
}
@@ -252,17 +286,56 @@ ngx_event_accept(ngx_event_t *ev)
#if (NGX_DEBUG)
{
- in_addr_t i;
- ngx_event_debug_t *dc;
- struct sockaddr_in *sin;
+ struct sockaddr_in *sin;
+ ngx_cidr_t *cidr;
+ ngx_uint_t i;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+ ngx_uint_t n;
+#endif
- sin = (struct sockaddr_in *) sa;
- dc = ecf->debug_connection.elts;
+ cidr = ecf->debug_connection.elts;
for (i = 0; i < ecf->debug_connection.nelts; i++) {
- if ((sin->sin_addr.s_addr & dc[i].mask) == dc[i].addr) {
- log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL;
+ if (cidr[i].family != c->sockaddr->sa_family) {
+ goto next;
+ }
+
+ switch (cidr[i].family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) c->sockaddr;
+ for (n = 0; n < 16; n++) {
+ if ((sin6->sin6_addr.s6_addr[n]
+ & cidr[i].u.in6.mask.s6_addr[n])
+ != cidr[i].u.in6.addr.s6_addr[n])
+ {
+ goto next;
+ }
+ }
+ break;
+#endif
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+ case AF_UNIX:
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) c->sockaddr;
+ if ((sin->sin_addr.s_addr & cidr[i].u.in.mask)
+ != cidr[i].u.in.addr)
+ {
+ goto next;
+ }
break;
}
+
+ log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL;
+ break;
+
+ next:
+ continue;
}
}
@@ -344,6 +417,10 @@ ngx_enable_accept_events(ngx_cycle_t *cycle)
c = ls[i].connection;
+ if (c->read->active) {
+ continue;
+ }
+
if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
if (ngx_add_conn(c) == NGX_ERROR) {
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 21deefda9..7903eb64c 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -995,6 +995,7 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
}
in->buf->pos += n;
+ c->sent += n;
if (in->buf->pos == in->buf->last) {
in = in->next;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 3bc994a80..55c3aef29 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -619,6 +619,7 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
u->process_header = ngx_http_fastcgi_process_header;
u->abort_request = ngx_http_fastcgi_abort_request;
u->finalize_request = ngx_http_fastcgi_finalize_request;
+ r->state = 0;
u->buffering = 1;
@@ -1194,6 +1195,8 @@ ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
f->fastcgi_stdout = 0;
f->large_stderr = 0;
+ r->state = 0;
+
return NGX_OK;
}
@@ -1353,7 +1356,11 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
}
} else {
- f->state = ngx_http_fastcgi_st_version;
+ if (f->padding) {
+ f->state = ngx_http_fastcgi_st_padding;
+ } else {
+ f->state = ngx_http_fastcgi_st_version;
+ }
}
continue;
@@ -1686,7 +1693,12 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
}
if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
- f->state = ngx_http_fastcgi_st_version;
+
+ if (f->padding) {
+ f->state = ngx_http_fastcgi_st_padding;
+ } else {
+ f->state = ngx_http_fastcgi_st_version;
+ }
if (!flcf->keep_conn) {
p->upstream_done = 1;
@@ -1699,7 +1711,13 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
}
if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
- f->state = ngx_http_fastcgi_st_version;
+
+ if (f->padding) {
+ f->state = ngx_http_fastcgi_st_padding;
+ } else {
+ f->state = ngx_http_fastcgi_st_version;
+ }
+
p->upstream_done = 1;
if (flcf->keep_conn) {
@@ -1772,7 +1790,11 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
}
} else {
- f->state = ngx_http_fastcgi_st_version;
+ if (f->padding) {
+ f->state = ngx_http_fastcgi_st_padding;
+ } else {
+ f->state = ngx_http_fastcgi_st_version;
+ }
}
continue;
diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c
index 719a01124..03a746803 100644
--- a/src/http/modules/ngx_http_flv_module.c
+++ b/src/http/modules/ngx_http_flv_module.c
@@ -235,7 +235,7 @@ ngx_http_flv_handler(ngx_http_request_t *r)
b->file_last = of.size;
b->in_file = b->file_last ? 1: 0;
- b->last_buf = 1;
+ b->last_buf = (r == r->main) ? 1 : 0;
b->last_in_chain = 1;
b->file->fd = of.fd;
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index 30b0e35a9..e792cdb66 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -51,6 +51,7 @@ typedef struct {
unsigned outside_entries:1;
unsigned allow_binary_include:1;
unsigned binary_include:1;
+ unsigned proxy_recursive:1;
} ngx_http_geo_conf_ctx_t;
@@ -61,6 +62,7 @@ typedef struct {
} u;
ngx_array_t *proxies;
+ unsigned proxy_recursive:1;
ngx_int_t index;
} ngx_http_geo_ctx_t;
@@ -68,8 +70,8 @@ typedef struct {
static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r,
ngx_http_geo_ctx_t *ctx);
-static in_addr_t ngx_http_geo_real_addr(ngx_http_request_t *r,
- ngx_http_geo_ctx_t *ctx);
+static ngx_int_t ngx_http_geo_real_addr(ngx_http_request_t *r,
+ ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
@@ -212,87 +214,60 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
static in_addr_t
ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
{
- u_char *p, *ip;
- size_t len;
- in_addr_t addr;
- ngx_uint_t i, n;
- ngx_in_cidr_t *proxies;
- ngx_table_elt_t *xfwd;
+ ngx_addr_t addr;
+ ngx_table_elt_t *xfwd;
+ struct sockaddr_in *sin;
- addr = ngx_http_geo_real_addr(r, ctx);
+ if (ngx_http_geo_real_addr(r, ctx, &addr) != NGX_OK) {
+ return INADDR_NONE;
+ }
xfwd = r->headers_in.x_forwarded_for;
- if (xfwd == NULL || ctx->proxies == NULL) {
- return addr;
+ if (xfwd != NULL && ctx->proxies != NULL) {
+ (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
+ xfwd->value.len, ctx->proxies,
+ ctx->proxy_recursive);
}
- proxies = ctx->proxies->elts;
- n = ctx->proxies->nelts;
-
- for (i = 0; i < n; i++) {
- if ((addr & proxies[i].mask) == proxies[i].addr) {
+#if (NGX_HAVE_INET6)
- len = xfwd->value.len;
- ip = xfwd->value.data;
+ if (addr.sockaddr->sa_family == AF_INET6) {
+ struct in6_addr *inaddr6;
- for (p = ip + len - 1; p > ip; p--) {
- if (*p == ' ' || *p == ',') {
- p++;
- len -= p - ip;
- ip = p;
- break;
- }
- }
+ inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
- return ntohl(ngx_inet_addr(ip, len));
+ if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
+ return ntohl(*(in_addr_t *) &inaddr6->s6_addr[12]);
}
}
- return addr;
+#endif
+
+ if (addr.sockaddr->sa_family != AF_INET) {
+ return INADDR_NONE;
+ }
+
+ sin = (struct sockaddr_in *) addr.sockaddr;
+ return ntohl(sin->sin_addr.s_addr);
}
-static in_addr_t
-ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
+static ngx_int_t
+ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
+ ngx_addr_t *addr)
{
- struct sockaddr_in *sin;
ngx_http_variable_value_t *v;
-#if (NGX_HAVE_INET6)
- u_char *p;
- in_addr_t addr;
- struct sockaddr_in6 *sin6;
-#endif
if (ctx->index == -1) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http geo started: %V", &r->connection->addr_text);
- switch (r->connection->sockaddr->sa_family) {
-
- case AF_INET:
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- return ntohl(sin->sin_addr.s_addr);
-
-#if (NGX_HAVE_INET6)
-
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
-
- if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
- p = sin6->sin6_addr.s6_addr;
- addr = p[12] << 24;
- addr += p[13] << 16;
- addr += p[14] << 8;
- addr += p[15];
-
- return addr;
- }
+ addr->sockaddr = r->connection->sockaddr;
+ addr->socklen = r->connection->socklen;
+ /* addr->name = r->connection->addr_text; */
-#endif
- }
-
- return INADDR_NONE;
+ return NGX_OK;
}
v = ngx_http_get_flushed_variable(r, ctx->index);
@@ -301,13 +276,17 @@ ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http geo not found");
- return 0;
+ return NGX_ERROR;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http geo started: %v", v);
- return ntohl(ngx_inet_addr(v->data, v->len));
+ if (ngx_parse_addr(r->pool, addr, v->data, v->len) == NGX_OK) {
+ return NGX_OK;
+ }
+
+ return NGX_ERROR;
}
@@ -388,6 +367,7 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
*cf = save;
geo->proxies = ctx.proxies;
+ geo->proxy_recursive = ctx.proxy_recursive;
if (ctx.high.low) {
@@ -493,6 +473,12 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
goto done;
}
+
+ else if (ngx_strcmp(value[0].data, "proxy_recursive") == 0) {
+ ctx->proxy_recursive = 1;
+ rv = NGX_CONF_OK;
+ goto done;
+ }
}
if (cf->args->nelts != 2) {
@@ -926,6 +912,7 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
}
if (ngx_strcmp(value[0].data, "default") == 0) {
+ /* cidr.family = AF_INET; */
cidr.u.in.addr = 0;
cidr.u.in.mask = 0;
net = &value[0];
@@ -944,6 +931,15 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
return NGX_CONF_ERROR;
}
+ if (cidr.family != AF_INET) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"geo\" supports IPv4 only");
+ return NGX_CONF_ERROR;
+ }
+
+ cidr.u.in.addr = ntohl(cidr.u.in.addr);
+ cidr.u.in.mask = ntohl(cidr.u.in.mask);
+
if (del) {
if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
cidr.u.in.mask)
@@ -1052,10 +1048,10 @@ static char *
ngx_http_geo_add_proxy(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
ngx_cidr_t *cidr)
{
- ngx_in_cidr_t *c;
+ ngx_cidr_t *c;
if (ctx->proxies == NULL) {
- ctx->proxies = ngx_array_create(ctx->pool, 4, sizeof(ngx_in_cidr_t));
+ ctx->proxies = ngx_array_create(ctx->pool, 4, sizeof(ngx_cidr_t));
if (ctx->proxies == NULL) {
return NGX_CONF_ERROR;
}
@@ -1066,8 +1062,7 @@ ngx_http_geo_add_proxy(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
return NGX_CONF_ERROR;
}
- c->addr = cidr->u.in.addr;
- c->mask = cidr->u.in.mask;
+ *c = *cidr;
return NGX_CONF_OK;
}
@@ -1079,6 +1074,7 @@ ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
ngx_int_t rc;
if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
+ cidr->family = AF_INET;
cidr->u.in.addr = 0xffffffff;
cidr->u.in.mask = 0xffffffff;
@@ -1092,19 +1088,11 @@ ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
return NGX_ERROR;
}
- if (cidr->family != AF_INET) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"geo\" supports IPv4 only");
- return NGX_ERROR;
- }
-
if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless", net);
}
- cidr->u.in.addr = ntohl(cidr->u.in.addr);
- cidr->u.in.mask = ntohl(cidr->u.in.mask);
-
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_geoip_module.c b/src/http/modules/ngx_http_geoip_module.c
index 60d67574d..abc79cdfe 100644
--- a/src/http/modules/ngx_http_geoip_module.c
+++ b/src/http/modules/ngx_http_geoip_module.c
@@ -14,20 +14,24 @@
typedef struct {
- GeoIP *country;
- GeoIP *org;
- GeoIP *city;
+ GeoIP *country;
+ GeoIP *org;
+ GeoIP *city;
+ ngx_array_t *proxies; /* array of ngx_cidr_t */
+ ngx_flag_t proxy_recursive;
} ngx_http_geoip_conf_t;
typedef struct {
- ngx_str_t *name;
- uintptr_t data;
+ ngx_str_t *name;
+ uintptr_t data;
} ngx_http_geoip_var_t;
typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *, u_long addr);
+static u_long ngx_http_geoip_addr(ngx_http_request_t *r,
+ ngx_http_geoip_conf_t *gcf);
static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_geoip_org_variable(ngx_http_request_t *r,
@@ -44,12 +48,17 @@ static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
+static char *ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf);
static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+static ngx_int_t ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
+ ngx_cidr_t *cidr);
static void ngx_http_geoip_cleanup(void *data);
@@ -76,6 +85,20 @@ static ngx_command_t ngx_http_geoip_commands[] = {
0,
NULL },
+ { ngx_string("geoip_proxy"),
+ NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
+ ngx_http_geoip_proxy,
+ NGX_HTTP_MAIN_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("geoip_proxy_recursive"),
+ NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_MAIN_CONF_OFFSET,
+ offsetof(ngx_http_geoip_conf_t, proxy_recursive),
+ NULL },
+
ngx_null_command
};
@@ -85,7 +108,7 @@ static ngx_http_module_t ngx_http_geoip_module_ctx = {
NULL, /* postconfiguration */
ngx_http_geoip_create_conf, /* create main configuration */
- NULL, /* init main configuration */
+ ngx_http_geoip_init_conf, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
@@ -182,40 +205,44 @@ static ngx_http_variable_t ngx_http_geoip_vars[] = {
static u_long
-ngx_http_geoip_addr(ngx_http_request_t *r)
+ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
{
- struct sockaddr_in *sin;
-#if (NGX_HAVE_INET6)
- u_char *p;
- u_long addr;
- struct sockaddr_in6 *sin6;
-#endif
+ ngx_addr_t addr;
+ ngx_table_elt_t *xfwd;
+ struct sockaddr_in *sin;
- switch (r->connection->sockaddr->sa_family) {
+ addr.sockaddr = r->connection->sockaddr;
+ addr.socklen = r->connection->socklen;
+ /* addr.name = r->connection->addr_text; */
- case AF_INET:
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- return ntohl(sin->sin_addr.s_addr);
+ xfwd = r->headers_in.x_forwarded_for;
+
+ if (xfwd != NULL && gcf->proxies != NULL) {
+ (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
+ xfwd->value.len, gcf->proxies,
+ gcf->proxy_recursive);
+ }
#if (NGX_HAVE_INET6)
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
+ if (addr.sockaddr->sa_family == AF_INET6) {
+ struct in6_addr *inaddr6;
- if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
- p = sin6->sin6_addr.s6_addr;
- addr = p[12] << 24;
- addr += p[13] << 16;
- addr += p[14] << 8;
- addr += p[15];
+ inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
- return addr;
+ if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
+ return ntohl(*(in_addr_t *) &inaddr6->s6_addr[12]);
}
+ }
#endif
+
+ if (addr.sockaddr->sa_family != AF_INET) {
+ return INADDR_NONE;
}
- return INADDR_NONE;
+ sin = (struct sockaddr_in *) addr.sockaddr;
+ return ntohl(sin->sin_addr.s_addr);
}
@@ -235,7 +262,7 @@ ngx_http_geoip_country_variable(ngx_http_request_t *r,
goto not_found;
}
- val = handler(gcf->country, ngx_http_geoip_addr(r));
+ val = handler(gcf->country, ngx_http_geoip_addr(r, gcf));
if (val == NULL) {
goto not_found;
@@ -273,7 +300,7 @@ ngx_http_geoip_org_variable(ngx_http_request_t *r,
goto not_found;
}
- val = handler(gcf->org, ngx_http_geoip_addr(r));
+ val = handler(gcf->org, ngx_http_geoip_addr(r, gcf));
if (val == NULL) {
goto not_found;
@@ -453,7 +480,7 @@ ngx_http_geoip_get_city_record(ngx_http_request_t *r)
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
if (gcf->city) {
- return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r));
+ return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r, gcf));
}
return NULL;
@@ -490,6 +517,8 @@ ngx_http_geoip_create_conf(ngx_conf_t *cf)
return NULL;
}
+ conf->proxy_recursive = NGX_CONF_UNSET;
+
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
return NULL;
@@ -503,6 +532,17 @@ ngx_http_geoip_create_conf(ngx_conf_t *cf)
static char *
+ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf)
+{
+ ngx_http_geoip_conf_t *gcf = conf;
+
+ ngx_conf_init_value(gcf->proxy_recursive, 0);
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_geoip_conf_t *gcf = conf;
@@ -652,6 +692,66 @@ ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
+static char *
+ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_geoip_conf_t *gcf = conf;
+
+ ngx_str_t *value;
+ ngx_cidr_t cidr, *c;
+
+ value = cf->args->elts;
+
+ if (ngx_http_geoip_cidr_value(cf, &value[1], &cidr) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (gcf->proxies == NULL) {
+ gcf->proxies = ngx_array_create(cf->pool, 4, sizeof(ngx_cidr_t));
+ if (gcf->proxies == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ c = ngx_array_push(gcf->proxies);
+ if (c == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *c = cidr;
+
+ return NGX_CONF_OK;
+}
+
+static ngx_int_t
+ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
+{
+ ngx_int_t rc;
+
+ if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
+ cidr->family = AF_INET;
+ cidr->u.in.addr = 0xffffffff;
+ cidr->u.in.mask = 0xffffffff;
+
+ return NGX_OK;
+ }
+
+ rc = ngx_ptocidr(net, cidr);
+
+ if (rc == NGX_ERROR) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid network \"%V\"", net);
+ return NGX_ERROR;
+ }
+
+ if (rc == NGX_DONE) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "low address bits of %V are meaningless", net);
+ }
+
+ return NGX_OK;
+}
+
+
static void
ngx_http_geoip_cleanup(void *data)
{
diff --git a/src/http/modules/ngx_http_gzip_static_module.c b/src/http/modules/ngx_http_gzip_static_module.c
index 46ce8f3f3..b0183e0aa 100644
--- a/src/http/modules/ngx_http_gzip_static_module.c
+++ b/src/http/modules/ngx_http_gzip_static_module.c
@@ -245,7 +245,7 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
b->file_last = of.size;
b->in_file = b->file_last ? 1 : 0;
- b->last_buf = 1;
+ b->last_buf = (r == r->main) ? 1 : 0;
b->last_in_chain = 1;
b->file->fd = of.fd;
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c
index 433e118a2..2c8cfd171 100644
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -616,7 +616,7 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
b->file_last = of.size;
b->in_file = b->file_last ? 1 : 0;
- b->last_buf = 1;
+ b->last_buf = (r == r->main) ? 1 : 0;
b->last_in_chain = 1;
b->file->fd = of.fd;
diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c
index c54c2ffa1..4531ea51c 100644
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -16,13 +16,11 @@
typedef struct {
- ngx_array_t *from; /* array of ngx_in_cidr_t */
+ ngx_array_t *from; /* array of ngx_cidr_t */
ngx_uint_t type;
ngx_uint_t hash;
ngx_str_t header;
-#if (NGX_HAVE_UNIX_DOMAIN)
- ngx_uint_t unixsock; /* unsigned unixsock:2; */
-#endif
+ ngx_flag_t recursive;
} ngx_http_realip_loc_conf_t;
@@ -35,8 +33,8 @@ typedef struct {
static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip,
- size_t len);
+static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r,
+ ngx_addr_t *addr);
static void ngx_http_realip_cleanup(void *data);
static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -63,6 +61,13 @@ static ngx_command_t ngx_http_realip_commands[] = {
0,
NULL },
+ { ngx_string("real_ip_recursive"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_realip_loc_conf_t, recursive),
+ NULL },
+
ngx_null_command
};
@@ -105,10 +110,9 @@ ngx_http_realip_handler(ngx_http_request_t *r)
u_char *ip, *p;
size_t len;
ngx_uint_t i, hash;
+ ngx_addr_t addr;
ngx_list_part_t *part;
ngx_table_elt_t *header;
- struct sockaddr_in *sin;
- ngx_in_cidr_t *from;
ngx_connection_t *c;
ngx_http_realip_ctx_t *ctx;
ngx_http_realip_loc_conf_t *rlcf;
@@ -121,12 +125,7 @@ ngx_http_realip_handler(ngx_http_request_t *r)
rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module);
- if (rlcf->from == NULL
-#if (NGX_HAVE_UNIX_DOMAIN)
- && !rlcf->unixsock
-#endif
- )
- {
+ if (rlcf->from == NULL) {
return NGX_DECLINED;
}
@@ -152,15 +151,6 @@ ngx_http_realip_handler(ngx_http_request_t *r)
len = r->headers_in.x_forwarded_for->value.len;
ip = r->headers_in.x_forwarded_for->value.data;
- for (p = ip + len - 1; p > ip; p--) {
- if (*p == ' ' || *p == ',') {
- p++;
- len -= p - ip;
- ip = p;
- break;
- }
- }
-
break;
default: /* NGX_HTTP_REALIP_HEADER */
@@ -204,42 +194,27 @@ found:
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "realip: \"%s\"", ip);
- /* AF_INET only */
-
- if (c->sockaddr->sa_family == AF_INET) {
- sin = (struct sockaddr_in *) c->sockaddr;
-
- from = rlcf->from->elts;
- for (i = 0; i < rlcf->from->nelts; i++) {
+ addr.sockaddr = c->sockaddr;
+ addr.socklen = c->socklen;
+ /* addr.name = c->addr_text; */
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "realip: %08XD %08XD %08XD",
- sin->sin_addr.s_addr, from[i].mask, from[i].addr);
-
- if ((sin->sin_addr.s_addr & from[i].mask) == from[i].addr) {
- return ngx_http_realip_set_addr(r, ip, len);
- }
- }
- }
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
- if (c->sockaddr->sa_family == AF_UNIX && rlcf->unixsock) {
- return ngx_http_realip_set_addr(r, ip, len);
+ if (ngx_http_get_forwarded_addr(r, &addr, ip, len, rlcf->from,
+ rlcf->recursive)
+ == NGX_OK)
+ {
+ return ngx_http_realip_set_addr(r, &addr);
}
-#endif
-
return NGX_DECLINED;
}
static ngx_int_t
-ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
+ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr)
{
+ size_t len;
u_char *p;
- ngx_int_t rc;
- ngx_addr_t addr;
+ u_char text[NGX_SOCKADDR_STRLEN];
ngx_connection_t *c;
ngx_pool_cleanup_t *cln;
ngx_http_realip_ctx_t *ctx;
@@ -254,15 +229,9 @@ ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
c = r->connection;
- rc = ngx_parse_addr(c->pool, &addr, ip, len);
-
- switch (rc) {
- case NGX_DECLINED:
- return NGX_DECLINED;
- case NGX_ERROR:
+ len = ngx_sock_ntop(addr->sockaddr, text, NGX_SOCKADDR_STRLEN, 0);
+ if (len == 0) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
- default: /* NGX_OK */
- break;
}
p = ngx_pnalloc(c->pool, len);
@@ -270,7 +239,7 @@ ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- ngx_memcpy(p, ip, len);
+ ngx_memcpy(p, text, len);
cln->handler = ngx_http_realip_cleanup;
@@ -279,8 +248,8 @@ ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
ctx->socklen = c->socklen;
ctx->addr_text = c->addr_text;
- c->sockaddr = addr.sockaddr;
- c->socklen = addr.socklen;
+ c->sockaddr = addr->sockaddr;
+ c->socklen = addr->socklen;
c->addr_text.len = len;
c->addr_text.data = p;
@@ -310,34 +279,33 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_int_t rc;
ngx_str_t *value;
- ngx_cidr_t cidr;
- ngx_in_cidr_t *from;
+ ngx_cidr_t *cidr;
value = cf->args->elts;
-#if (NGX_HAVE_UNIX_DOMAIN)
-
- if (ngx_strcmp(value[1].data, "unix:") == 0) {
- rlcf->unixsock = 1;
- return NGX_CONF_OK;
- }
-
-#endif
-
if (rlcf->from == NULL) {
rlcf->from = ngx_array_create(cf->pool, 2,
- sizeof(ngx_in_cidr_t));
+ sizeof(ngx_cidr_t));
if (rlcf->from == NULL) {
return NGX_CONF_ERROR;
}
}
- from = ngx_array_push(rlcf->from);
- if (from == NULL) {
+ cidr = ngx_array_push(rlcf->from);
+ if (cidr == NULL) {
return NGX_CONF_ERROR;
}
- rc = ngx_ptocidr(&value[1], &cidr);
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ if (ngx_strcmp(value[1].data, "unix:") == 0) {
+ cidr->family = AF_UNIX;
+ return NGX_CONF_OK;
+ }
+
+#endif
+
+ rc = ngx_ptocidr(&value[1], cidr);
if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
@@ -345,20 +313,11 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if (cidr.family != AF_INET) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"set_real_ip_from\" supports IPv4 only");
- 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 = cidr.u.in.mask;
- from->addr = cidr.u.in.addr;
-
return NGX_CONF_OK;
}
@@ -409,9 +368,7 @@ ngx_http_realip_create_loc_conf(ngx_conf_t *cf)
*/
conf->type = NGX_CONF_UNSET_UINT;
-#if (NGX_HAVE_UNIX_DOMAIN)
- conf->unixsock = 2;
-#endif
+ conf->recursive = NGX_CONF_UNSET;
return conf;
}
@@ -427,13 +384,8 @@ ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->from = prev->from;
}
-#if (NGX_HAVE_UNIX_DOMAIN)
- if (conf->unixsock == 2) {
- conf->unixsock = (prev->unixsock == 2) ? 0 : prev->unixsock;
- }
-#endif
-
ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP);
+ ngx_conf_merge_value(conf->recursive, prev->recursive, 0);
if (conf->header.len == 0) {
conf->hash = prev->hash;
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 239da6b94..bf0cb8a9c 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -434,6 +434,7 @@ ngx_http_scgi_handler(ngx_http_request_t *r)
u->process_header = ngx_http_scgi_process_status_line;
u->abort_request = ngx_http_scgi_abort_request;
u->finalize_request = ngx_http_scgi_finalize_request;
+ r->state = 0;
u->buffering = scf->upstream.buffering;
@@ -843,6 +844,7 @@ ngx_http_scgi_reinit_request(ngx_http_request_t *r)
status->end = NULL;
r->upstream->process_header = ngx_http_scgi_process_status_line;
+ r->state = 0;
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_stub_status_module.c b/src/http/modules/ngx_http_stub_status_module.c
index f78086981..96abe928a 100644
--- a/src/http/modules/ngx_http_stub_status_module.c
+++ b/src/http/modules/ngx_http_stub_status_module.c
@@ -121,7 +121,7 @@ static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = b->last - b->pos;
- b->last_buf = 1;
+ b->last_buf = (r == r->main) ? 1 : 0;
rc = ngx_http_send_header(r);
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index 0c999ca62..ef8994c52 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -467,6 +467,7 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
u->process_header = ngx_http_uwsgi_process_status_line;
u->abort_request = ngx_http_uwsgi_abort_request;
u->finalize_request = ngx_http_uwsgi_finalize_request;
+ r->state = 0;
u->buffering = uwcf->upstream.buffering;
@@ -883,6 +884,7 @@ ngx_http_uwsgi_reinit_request(ngx_http_request_t *r)
status->end = NULL;
r->upstream->process_header = ngx_http_uwsgi_process_status_line;
+ r->state = 0;
return NGX_OK;
}
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 766b81017..117ffd837 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -50,7 +50,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '1.2.0';
+our $VERSION = '1.2.1';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 42dd6644e..31832ceb8 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -2599,6 +2599,7 @@ ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
r->phase_handler = cmcf->phase_engine.location_rewrite_index;
+ r->write_event_handler = ngx_http_core_run_phases;
ngx_http_core_run_phases(r);
return NGX_DONE;
@@ -2698,6 +2699,109 @@ ngx_http_set_disable_symlinks(ngx_http_request_t *r,
}
+ngx_int_t
+ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
+ u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive)
+{
+ u_char *p;
+ in_addr_t inaddr;
+ ngx_addr_t paddr;
+ ngx_cidr_t *cidr;
+ ngx_uint_t family, i;
+#if (NGX_HAVE_INET6)
+ ngx_uint_t n;
+ struct in6_addr *inaddr6;
+#endif
+
+#if (NGX_SUPPRESS_WARN)
+ inaddr = 0;
+#if (NGX_HAVE_INET6)
+ inaddr6 = NULL;
+#endif
+#endif
+
+ family = addr->sockaddr->sa_family;
+
+ if (family == AF_INET) {
+ inaddr = ((struct sockaddr_in *) addr->sockaddr)->sin_addr.s_addr;
+ }
+
+#if (NGX_HAVE_INET6)
+ else if (family == AF_INET6) {
+ inaddr6 = &((struct sockaddr_in6 *) addr->sockaddr)->sin6_addr;
+
+ if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
+ family = AF_INET;
+ inaddr = *(in_addr_t *) &inaddr6->s6_addr[12];
+ }
+ }
+#endif
+
+ for (cidr = proxies->elts, i = 0; i < proxies->nelts; i++) {
+ if (cidr[i].family != family) {
+ goto next;
+ }
+
+ switch (family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ for (n = 0; n < 16; n++) {
+ if ((inaddr6->s6_addr[n] & cidr[i].u.in6.mask.s6_addr[n])
+ != cidr[i].u.in6.addr.s6_addr[n])
+ {
+ goto next;
+ }
+ }
+ break;
+#endif
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+ case AF_UNIX:
+ break;
+#endif
+
+ default: /* AF_INET */
+ if ((inaddr & cidr[i].u.in.mask) != cidr[i].u.in.addr) {
+ goto next;
+ }
+ break;
+ }
+
+ for (p = xff + xfflen - 1; p > xff; p--, xfflen--) {
+ if (*p != ' ' && *p != ',') {
+ break;
+ }
+ }
+
+ for ( /* void */ ; p > xff; p--) {
+ if (*p == ' ' || *p == ',') {
+ p++;
+ break;
+ }
+ }
+
+ if (ngx_parse_addr(r->pool, &paddr, p, xfflen - (p - xff)) != NGX_OK) {
+ return NGX_DECLINED;
+ }
+
+ *addr = paddr;
+
+ if (recursive && p > xff) {
+ (void) ngx_http_get_forwarded_addr(r, addr, xff, p - 1 - xff,
+ proxies, 1);
+ }
+
+ return NGX_OK;
+
+ next:
+ continue;
+ }
+
+ return NGX_DECLINED;
+}
+
+
static char *
ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index bfa0b419e..e95d1e069 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -513,6 +513,9 @@ ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *chain);
ngx_int_t ngx_http_set_disable_symlinks(ngx_http_request_t *r,
ngx_http_core_loc_conf_t *clcf, ngx_str_t *path, ngx_open_file_info_t *of);
+ngx_int_t ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
+ u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive);
+
extern ngx_module_t ngx_http_core_module;
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 0a10a340e..be750edd0 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -543,6 +543,13 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
switch (ch) {
case '/':
+#if (NGX_WIN32)
+ if (r->uri_ext == p) {
+ r->complex_uri = 1;
+ state = sw_uri;
+ break;
+ }
+#endif
r->uri_ext = NULL;
state = sw_after_slash_in_uri;
break;
@@ -1117,6 +1124,12 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
switch(ch) {
#if (NGX_WIN32)
case '\\':
+ if (u - 2 >= r->uri.data
+ && *(u - 1) == '.' && *(u - 2) != '.')
+ {
+ u--;
+ }
+
r->uri_ext = NULL;
if (p == r->uri_start + r->uri.len) {
@@ -1134,6 +1147,13 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
break;
#endif
case '/':
+#if (NGX_WIN32)
+ if (u - 2 >= r->uri.data
+ && *(u - 1) == '.' && *(u - 2) != '.')
+ {
+ u--;
+ }
+#endif
r->uri_ext = NULL;
state = sw_slash;
*u++ = ch;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 052f379ac..b1877131c 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -812,7 +812,28 @@ ngx_http_process_request_line(ngx_event_t *rev)
#if (NGX_WIN32)
{
- u_char *p;
+ u_char *p, *last;
+
+ p = r->uri.data;
+ last = r->uri.data + r->uri.len;
+
+ while (p < last) {
+
+ if (*p++ == ':') {
+
+ /*
+ * this check covers "::$data", "::$index_allocation" and
+ * ":$i30:$index_allocation"
+ */
+
+ if (p < last && *p == '$') {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent unsafe win32 URI");
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+ return;
+ }
+ }
+ }
p = r->uri.data + r->uri.len - 1;
@@ -828,11 +849,6 @@ ngx_http_process_request_line(ngx_event_t *rev)
continue;
}
- if (ngx_strncasecmp(p - 6, (u_char *) "::$data", 7) == 0) {
- p -= 7;
- continue;
- }
-
break;
}
@@ -1933,7 +1949,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
if (rc == NGX_OK && r->filter_finalize) {
c->error = 1;
- return;
}
if (rc == NGX_DECLINED) {
@@ -2001,14 +2016,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
return;
}
-#if (NGX_DEBUG)
- if (r != c->data) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http finalize non-active request: \"%V?%V\"",
- &r->uri, &r->args);
- }
-#endif
-
pr = r->parent;
if (r == c->data) {
@@ -2042,6 +2049,10 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
} else {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http finalize non-active request: \"%V?%V\"",
+ &r->uri, &r->args);
+
r->write_event_handler = ngx_http_request_finalizer;
if (r->waited) {
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index ce290f4ef..e214519fc 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -1043,7 +1043,6 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
}
e->buf.len = len;
- e->is_args = le.is_args;
}
if (code->add_args && r->args.len) {
diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c
index f0fac8736..214de7b74 100644
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -12,8 +12,8 @@
static ngx_int_t ngx_http_upstream_cmp_servers(const void *one,
const void *two);
-static ngx_uint_t
-ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers);
+static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer(
+ ngx_http_upstream_rr_peer_data_t *rrp);
#if (NGX_HTTP_SSL)
@@ -80,8 +80,9 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
peers->peer[n].max_fails = server[i].max_fails;
peers->peer[n].fail_timeout = server[i].fail_timeout;
peers->peer[n].down = server[i].down;
- peers->peer[n].weight = server[i].down ? 0 : server[i].weight;
- peers->peer[n].current_weight = peers->peer[n].weight;
+ peers->peer[n].weight = server[i].weight;
+ peers->peer[n].effective_weight = server[i].weight;
+ peers->peer[n].current_weight = 0;
n++;
}
}
@@ -131,7 +132,8 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
backup->peer[n].socklen = server[i].addrs[j].socklen;
backup->peer[n].name = server[i].addrs[j].name;
backup->peer[n].weight = server[i].weight;
- backup->peer[n].current_weight = server[i].weight;
+ backup->peer[n].effective_weight = server[i].weight;
+ backup->peer[n].current_weight = 0;
backup->peer[n].max_fails = server[i].max_fails;
backup->peer[n].fail_timeout = server[i].fail_timeout;
backup->peer[n].down = server[i].down;
@@ -190,7 +192,8 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
peers->peer[i].socklen = u.addrs[i].socklen;
peers->peer[i].name = u.addrs[i].name;
peers->peer[i].weight = 1;
- peers->peer[i].current_weight = 1;
+ peers->peer[i].effective_weight = 1;
+ peers->peer[i].current_weight = 0;
peers->peer[i].max_fails = 1;
peers->peer[i].fail_timeout = 10;
}
@@ -306,7 +309,8 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
peers->peer[0].socklen = ur->socklen;
peers->peer[0].name = ur->host;
peers->peer[0].weight = 1;
- peers->peer[0].current_weight = 1;
+ peers->peer[0].effective_weight = 1;
+ peers->peer[0].current_weight = 0;
peers->peer[0].max_fails = 1;
peers->peer[0].fail_timeout = 10;
@@ -338,7 +342,8 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
peers->peer[i].name.len = len;
peers->peer[i].name.data = p;
peers->peer[i].weight = 1;
- peers->peer[i].current_weight = 1;
+ peers->peer[i].effective_weight = 1;
+ peers->peer[i].current_weight = 0;
peers->peer[i].max_fails = 1;
peers->peer[i].fail_timeout = 10;
}
@@ -378,8 +383,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
{
ngx_http_upstream_rr_peer_data_t *rrp = data;
- time_t now;
- uintptr_t m;
ngx_int_t rc;
ngx_uint_t i, n;
ngx_connection_t *c;
@@ -389,8 +392,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get rr peer, try: %ui", pc->tries);
- now = ngx_time();
-
/* ngx_lock_mutex(rrp->peers->mutex); */
if (rrp->peers->last_cached) {
@@ -423,118 +424,15 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
/* there are several peers */
- if (pc->tries == rrp->peers->number) {
-
- /* it's a first try - get a current peer */
-
- i = pc->tries;
-
- for ( ;; ) {
- rrp->current = ngx_http_upstream_get_peer(rrp->peers);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get rr peer, current: %ui %i",
- rrp->current,
- rrp->peers->peer[rrp->current].current_weight);
-
- n = rrp->current / (8 * sizeof(uintptr_t));
- m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
-
- if (!(rrp->tried[n] & m)) {
- peer = &rrp->peers->peer[rrp->current];
-
- if (!peer->down) {
-
- if (peer->max_fails == 0
- || peer->fails < peer->max_fails)
- {
- break;
- }
+ peer = ngx_http_upstream_get_peer(rrp);
- if (now - peer->checked > peer->fail_timeout) {
- peer->checked = now;
- break;
- }
-
- peer->current_weight = 0;
-
- } else {
- rrp->tried[n] |= m;
- }
-
- pc->tries--;
- }
-
- if (pc->tries == 0) {
- goto failed;
- }
-
- if (--i == 0) {
- ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
- "round robin upstream stuck on %ui tries",
- pc->tries);
- goto failed;
- }
- }
-
- peer->current_weight--;
-
- } else {
-
- i = pc->tries;
-
- for ( ;; ) {
- n = rrp->current / (8 * sizeof(uintptr_t));
- m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
-
- if (!(rrp->tried[n] & m)) {
-
- peer = &rrp->peers->peer[rrp->current];
-
- if (!peer->down) {
-
- if (peer->max_fails == 0
- || peer->fails < peer->max_fails)
- {
- break;
- }
-
- if (now - peer->checked > peer->fail_timeout) {
- peer->checked = now;
- break;
- }
-
- peer->current_weight = 0;
-
- } else {
- rrp->tried[n] |= m;
- }
-
- pc->tries--;
- }
-
- rrp->current++;
-
- if (rrp->current >= rrp->peers->number) {
- rrp->current = 0;
- }
-
- if (pc->tries == 0) {
- goto failed;
- }
-
- if (--i == 0) {
- ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
- "round robin upstream stuck on %ui tries",
- pc->tries);
- goto failed;
- }
- }
-
- peer->current_weight--;
+ if (peer == NULL) {
+ goto failed;
}
- rrp->tried[n] |= m;
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
+ "get rr peer, current: %ui %i",
+ rrp->current, peer->current_weight);
}
pc->sockaddr = peer->sockaddr;
@@ -545,11 +443,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
if (pc->tries == 1 && rrp->peers->next) {
pc->tries += rrp->peers->next->number;
-
- n = rrp->peers->next->number / (8 * sizeof(uintptr_t)) + 1;
- for (i = 0; i < n; i++) {
- rrp->tried[i] = 0;
- }
}
return NGX_OK;
@@ -595,56 +488,71 @@ failed:
}
-static ngx_uint_t
-ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers)
+static ngx_http_upstream_rr_peer_t *
+ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
{
- ngx_uint_t i, n, reset = 0;
- ngx_http_upstream_rr_peer_t *peer;
+ time_t now;
+ uintptr_t m;
+ ngx_int_t total;
+ ngx_uint_t i, n;
+ ngx_http_upstream_rr_peer_t *peer, *best;
- peer = &peers->peer[0];
+ now = ngx_time();
- for ( ;; ) {
+ best = NULL;
+ total = 0;
- for (i = 0; i < peers->number; i++) {
+ for (i = 0; i < rrp->peers->number; i++) {
- if (peer[i].current_weight <= 0) {
- continue;
- }
+ n = i / (8 * sizeof(uintptr_t));
+ m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
- n = i;
-
- while (i < peers->number - 1) {
-
- i++;
+ if (rrp->tried[n] & m) {
+ continue;
+ }
- if (peer[i].current_weight <= 0) {
- continue;
- }
+ peer = &rrp->peers->peer[i];
- if (peer[n].current_weight * 1000 / peer[i].current_weight
- > peer[n].weight * 1000 / peer[i].weight)
- {
- return n;
- }
+ if (peer->down) {
+ continue;
+ }
- n = i;
- }
+ if (peer->max_fails
+ && peer->fails >= peer->max_fails
+ && now - peer->checked <= peer->fail_timeout)
+ {
+ continue;
+ }
- if (peer[i].current_weight > 0) {
- n = i;
- }
+ peer->current_weight += peer->effective_weight;
+ total += peer->effective_weight;
- return n;
+ if (peer->effective_weight < peer->weight) {
+ peer->effective_weight++;
}
- if (reset++) {
- return 0;
+ if (best == NULL || peer->current_weight > best->current_weight) {
+ best = peer;
}
+ }
- for (i = 0; i < peers->number; i++) {
- peer[i].current_weight = peer[i].weight;
- }
+ if (best == NULL) {
+ return NULL;
}
+
+ i = best - &rrp->peers->peer[0];
+
+ rrp->current = i;
+
+ n = i / (8 * sizeof(uintptr_t));
+ m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
+
+ rrp->tried[n] |= m;
+
+ best->current_weight -= total;
+ best->checked = now;
+
+ return best;
}
@@ -683,15 +591,15 @@ ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
peer->checked = now;
if (peer->max_fails) {
- peer->current_weight -= peer->weight / peer->max_fails;
+ peer->effective_weight -= peer->weight / peer->max_fails;
}
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"free rr peer failed: %ui %i",
- rrp->current, peer->current_weight);
+ rrp->current, peer->effective_weight);
- if (peer->current_weight < 0) {
- peer->current_weight = 0;
+ if (peer->effective_weight < 0) {
+ peer->effective_weight = 0;
}
/* ngx_unlock_mutex(rrp->peers->mutex); */
@@ -705,12 +613,6 @@ ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
}
}
- rrp->current++;
-
- if (rrp->current >= rrp->peers->number) {
- rrp->current = 0;
- }
-
if (pc->tries) {
pc->tries--;
}
diff --git a/src/http/ngx_http_upstream_round_robin.h b/src/http/ngx_http_upstream_round_robin.h
index 4b70f2f5b..4de3caea1 100644
--- a/src/http/ngx_http_upstream_round_robin.h
+++ b/src/http/ngx_http_upstream_round_robin.h
@@ -20,6 +20,7 @@ typedef struct {
ngx_str_t name;
ngx_int_t current_weight;
+ ngx_int_t effective_weight;
ngx_int_t weight;
ngx_uint_t fails;
diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h
index 78af40bfe..2912dea04 100644
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -29,6 +29,8 @@ typedef int ngx_err_t;
#define NGX_ENOTDIR ENOTDIR
#define NGX_EISDIR EISDIR
#define NGX_EINVAL EINVAL
+#define NGX_ENFILE ENFILE
+#define NGX_EMFILE EMFILE
#define NGX_ENOSPC ENOSPC
#define NGX_EPIPE EPIPE
#define NGX_EINPROGRESS EINPROGRESS