From ru at nginx.com Mon Sep 1 08:49:12 2014 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 01 Sep 2014 08:49:12 +0000 Subject: [nginx] Upstream: improved configuration parser diagnostics. Message-ID: details: http://hg.nginx.org/nginx/rev/fe8bafab5b49 branches: changeset: 5818:fe8bafab5b49 user: Ruslan Ermilov date: Mon Sep 01 12:27:38 2014 +0400 description: Upstream: improved configuration parser diagnostics. Made it clear when the selected balancing method does not support certain parameters of the "server" directive. diffstat: src/http/ngx_http_upstream.c | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-) diffs (63 lines): diff -r 74ffe03555d0 -r fe8bafab5b49 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Fri Aug 29 18:00:10 2014 +0400 +++ b/src/http/ngx_http_upstream.c Mon Sep 01 12:27:38 2014 +0400 @@ -4973,7 +4973,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, if (ngx_strncmp(value[i].data, "weight=", 7) == 0) { if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT)) { - goto invalid; + goto not_supported; } weight = ngx_atoi(&value[i].data[7], value[i].len - 7); @@ -4988,7 +4988,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) { if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) { - goto invalid; + goto not_supported; } max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10); @@ -5003,7 +5003,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) { if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT)) { - goto invalid; + goto not_supported; } s.len = value[i].len - 13; @@ -5021,7 +5021,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, if (ngx_strcmp(value[i].data, "backup") == 0) { if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP)) { - goto invalid; + goto not_supported; } us->backup = 1; @@ -5032,7 +5032,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, if (ngx_strcmp(value[i].data, "down") == 0) { if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) { - goto invalid; + goto not_supported; } us->down = 1; @@ -5072,6 +5072,14 @@ invalid: "invalid parameter \"%V\"", &value[i]); return NGX_CONF_ERROR; + +not_supported: + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "balancing method does not support parameter \"%V\"", + &value[i]); + + return NGX_CONF_ERROR; } From niq at apache.org Mon Sep 1 10:34:07 2014 From: niq at apache.org (Nick Kew) Date: Mon, 01 Sep 2014 11:34:07 +0100 Subject: nginx tempfiles In-Reply-To: <20140829132659.GO1849@mdounin.ru> References: <1409273515.5553.89.camel@mimir.webthing.com> <20140829132659.GO1849@mdounin.ru> Message-ID: <1409567647.4002.31.camel@mimir.webthing.com> On Fri, 2014-08-29 at 17:26 +0400, Maxim Dounin wrote: > In either case, you may want to consider using request body > filters instead, as recently discussed here: > > http://mailman.nginx.org/pipermail/nginx-devel/2014-August/005781.html If I'm to use such a feature when it's uncommitted because you're not sure it's a good way to implement input filters, I'd like at least to make it easily switchable. Would you consider adding a #define to detect the patch and simplify compile-time selection of code? Something like: $ diff -u configure* --- configure 2014-08-05 12:13:05.000000000 +0100 +++ configure.patched 2014-09-01 11:25:21.128430978 +0100 @@ -112,4 +112,6 @@ have=NGX_BUILD value="\"$NGX_BUILD\"" . auto/define fi +have=NGX_INPUT_FILTERS value=1358156187 . auto/define + . auto/summary (That's against the 1.7.4 tarball: I didn't find anything looking like a dev repo). > Reading and then writing temorary files will be suboptimal. And Yes of course. I was just guessing that the alternative of buffering it all in memory would be worse; else nginx wouldn't've used a tempfile in the first place! I can also see a minor advantage to all-at-once filtering, in that it means the filter can take responsibility for administrivia like setting a correct Content-Length for the possibly-changed payload. > replacing r->request_body->temp_file, even if you'll be able to do > it properly, will likely result in your module being broken during > further nginx development. That's a risk with any patch, and surely applies even to your own uncommitted input-filtering patch? -- Nick Kew From vbart at nginx.com Mon Sep 1 12:09:30 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Mon, 01 Sep 2014 16:09:30 +0400 Subject: nginx tempfiles In-Reply-To: <1409567647.4002.31.camel@mimir.webthing.com> References: <1409273515.5553.89.camel@mimir.webthing.com> <20140829132659.GO1849@mdounin.ru> <1409567647.4002.31.camel@mimir.webthing.com> Message-ID: <2939563.cvUsE8BLdC@vbart-workstation> On Monday 01 September 2014 11:34:07 Nick Kew wrote: [..] > (That's against the 1.7.4 tarball: I didn't find anything looking > like a dev repo). [..] http://hg.nginx.org/ wbr, Valentin V. Bartenev From mdounin at mdounin.ru Mon Sep 1 12:38:08 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 1 Sep 2014 16:38:08 +0400 Subject: nginx tempfiles In-Reply-To: <1409567647.4002.31.camel@mimir.webthing.com> References: <1409273515.5553.89.camel@mimir.webthing.com> <20140829132659.GO1849@mdounin.ru> <1409567647.4002.31.camel@mimir.webthing.com> Message-ID: <20140901123808.GX1849@mdounin.ru> Hello! On Mon, Sep 01, 2014 at 11:34:07AM +0100, Nick Kew wrote: > On Fri, 2014-08-29 at 17:26 +0400, Maxim Dounin wrote: > > > In either case, you may want to consider using request body > > filters instead, as recently discussed here: > > > > http://mailman.nginx.org/pipermail/nginx-devel/2014-August/005781.html > > If I'm to use such a feature when it's uncommitted because you're > not sure it's a good way to implement input filters, I'd like at > least to make it easily switchable. > > Would you consider adding a #define to detect the patch > and simplify compile-time selection of code? > Something like: > > $ diff -u configure* > --- configure 2014-08-05 12:13:05.000000000 +0100 > +++ configure.patched 2014-09-01 11:25:21.128430978 +0100 > @@ -112,4 +112,6 @@ > have=NGX_BUILD value="\"$NGX_BUILD\"" . auto/define > fi > > +have=NGX_INPUT_FILTERS value=1358156187 . auto/define > + > . auto/summary There is no real difference with just committing it as is. Once committed, you can test nginx_version as it's usually done with all API changes/new features. Further work in this area is expected to happen in near future (at least I hope so). > (That's against the 1.7.4 tarball: I didn't find anything looking > like a dev repo). Repository is linked from http://nginx.org/en/download.html. See http://nginx.org/en/docs/contributing_changes.html for tips. > > Reading and then writing temorary files will be suboptimal. And > > Yes of course. I was just guessing that the alternative of buffering > it all in memory would be worse; else nginx wouldn't've used a tempfile > in the first place! > > I can also see a minor advantage to all-at-once filtering, in that > it means the filter can take responsibility for administrivia like > setting a correct Content-Length for the possibly-changed payload. This should be possible with request body filters, too. E.g., chunked request body filter currently set Content-Length. > > replacing r->request_body->temp_file, even if you'll be able to do > > it properly, will likely result in your module being broken during > > further nginx development. > > That's a risk with any patch, and surely applies even to your own > uncommitted input-filtering patch? The problem is that what you are trying to do with r->request_body->temp_file is certainly out of the scope of what is considered to be nginx modules API. And such a code has much higher chances of being broken. -- Maxim Dounin http://nginx.org/ From vbart at nginx.com Mon Sep 1 13:51:45 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 01 Sep 2014 13:51:45 +0000 Subject: [nginx] Mail: initialize the "signature" field of ngx_mail_sessi... Message-ID: details: http://hg.nginx.org/nginx/rev/8e7ee4c70a3c branches: changeset: 5819:8e7ee4c70a3c user: Valentin Bartenev date: Mon Sep 01 17:50:59 2014 +0400 description: Mail: initialize the "signature" field of ngx_mail_session_t. Currently it isn't used, but it can be suitable to distinguish objects stored in c->data. diffstat: src/mail/ngx_mail_handler.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r fe8bafab5b49 -r 8e7ee4c70a3c src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c Mon Sep 01 12:27:38 2014 +0400 +++ b/src/mail/ngx_mail_handler.c Mon Sep 01 17:50:59 2014 +0400 @@ -121,6 +121,8 @@ ngx_mail_init_connection(ngx_connection_ return; } + s->signature = NGX_MAIL_MODULE; + s->main_conf = addr_conf->ctx->main_conf; s->srv_conf = addr_conf->ctx->srv_conf; From vbart at nginx.com Mon Sep 1 14:22:14 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 01 Sep 2014 14:22:14 +0000 Subject: [nginx] Events: removed broken thread support from posted events. Message-ID: details: http://hg.nginx.org/nginx/rev/3377f9459e99 branches: changeset: 5820:3377f9459e99 user: Valentin Bartenev date: Mon Sep 01 18:20:03 2014 +0400 description: Events: removed broken thread support from posted events. It's mostly dead code. And the idea of thread support for this task has been deprecated. diffstat: src/core/ngx_connection.c | 25 +---- src/core/ngx_resolver.c | 11 -- src/event/modules/ngx_devpoll_module.c | 28 +---- src/event/modules/ngx_epoll_module.c | 26 +--- src/event/modules/ngx_eventport_module.c | 28 +---- src/event/modules/ngx_kqueue_module.c | 29 +---- src/event/modules/ngx_poll_module.c | 28 +---- src/event/modules/ngx_rtsig_module.c | 34 +---- src/event/modules/ngx_select_module.c | 11 +- src/event/modules/ngx_win32_select_module.c | 11 +- src/event/ngx_event.c | 22 +---- src/event/ngx_event.h | 29 ----- src/event/ngx_event_accept.c | 7 - src/event/ngx_event_connect.c | 11 -- src/event/ngx_event_mutex.c | 2 +- src/event/ngx_event_posted.c | 144 +--------------------------- src/event/ngx_event_posted.h | 30 +---- src/event/ngx_event_timer.c | 30 ----- src/os/unix/ngx_channel.c | 7 - src/os/unix/ngx_process_cycle.c | 9 +- 20 files changed, 66 insertions(+), 456 deletions(-) diffs (truncated from 1018 to 300 lines): diff -r 8e7ee4c70a3c -r 3377f9459e99 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Mon Sep 01 17:50:59 2014 +0400 +++ b/src/core/ngx_connection.c Mon Sep 01 18:20:03 2014 +0400 @@ -951,7 +951,9 @@ ngx_close_connection(ngx_connection_t *c * before we clean the connection */ - ngx_mutex_lock(ngx_posted_events_mutex); + ngx_unlock(&c->lock); + +#endif if (c->read->prev) { ngx_delete_posted_event(c->read); @@ -964,27 +966,6 @@ ngx_close_connection(ngx_connection_t *c c->read->closed = 1; c->write->closed = 1; - ngx_unlock(&c->lock); - c->read->locked = 0; - c->write->locked = 0; - - ngx_mutex_unlock(ngx_posted_events_mutex); - -#else - - if (c->read->prev) { - ngx_delete_posted_event(c->read); - } - - if (c->write->prev) { - ngx_delete_posted_event(c->write); - } - - c->read->closed = 1; - c->write->closed = 1; - -#endif - ngx_reusable_connection(c, 0); log_error = c->log_error; diff -r 8e7ee4c70a3c -r 3377f9459e99 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Mon Sep 01 17:50:59 2014 +0400 +++ b/src/core/ngx_resolver.c Mon Sep 01 18:20:03 2014 +0400 @@ -3082,17 +3082,6 @@ ngx_udp_connect(ngx_udp_connection_t *uc c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); -#if (NGX_THREADS) - - /* TODO: lock event when call completion handler */ - - rev->lock = &c->lock; - wev->lock = &c->lock; - rev->own_lock = &c->lock; - wev->own_lock = &c->lock; - -#endif - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "connect to %V, fd:%d #%uA", &uc->server, s, c->number); diff -r 8e7ee4c70a3c -r 3377f9459e99 src/event/modules/ngx_devpoll_module.c --- a/src/event/modules/ngx_devpoll_module.c Mon Sep 01 17:50:59 2014 +0400 +++ b/src/event/modules/ngx_devpoll_module.c Mon Sep 01 18:20:03 2014 +0400 @@ -404,8 +404,6 @@ ngx_devpoll_process_events(ngx_cycle_t * return NGX_ERROR; } - ngx_mutex_lock(ngx_posted_events_mutex); - for (i = 0; i < events; i++) { fd = event_list[i].fd; @@ -495,19 +493,13 @@ ngx_devpoll_process_events(ngx_cycle_t * rev = c->read; if ((revents & POLLIN) && rev->active) { - - if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { - rev->posted_ready = 1; - - } else { - rev->ready = 1; - } + rev->ready = 1; if (flags & NGX_POST_EVENTS) { - queue = (ngx_event_t **) (rev->accept ? - &ngx_posted_accept_events : &ngx_posted_events); + queue = rev->accept ? &ngx_posted_accept_events + : &ngx_posted_events; - ngx_locked_post_event(rev, queue); + ngx_post_event(rev, queue); } else { instance = rev->instance; @@ -523,16 +515,10 @@ ngx_devpoll_process_events(ngx_cycle_t * wev = c->write; if ((revents & POLLOUT) && wev->active) { - - if (flags & NGX_POST_THREAD_EVENTS) { - wev->posted_ready = 1; - - } else { - wev->ready = 1; - } + wev->ready = 1; if (flags & NGX_POST_EVENTS) { - ngx_locked_post_event(wev, &ngx_posted_events); + ngx_post_event(wev, &ngx_posted_events); } else { wev->handler(wev); @@ -540,8 +526,6 @@ ngx_devpoll_process_events(ngx_cycle_t * } } - ngx_mutex_unlock(ngx_posted_events_mutex); - return NGX_OK; } diff -r 8e7ee4c70a3c -r 3377f9459e99 src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c Mon Sep 01 17:50:59 2014 +0400 +++ b/src/event/modules/ngx_epoll_module.c Mon Sep 01 18:20:03 2014 +0400 @@ -612,8 +612,6 @@ ngx_epoll_process_events(ngx_cycle_t *cy return NGX_ERROR; } - ngx_mutex_lock(ngx_posted_events_mutex); - for (i = 0; i < events; i++) { c = event_list[i].data.ptr; @@ -674,18 +672,13 @@ ngx_epoll_process_events(ngx_cycle_t *cy } #endif - if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { - rev->posted_ready = 1; - - } else { - rev->ready = 1; - } + rev->ready = 1; if (flags & NGX_POST_EVENTS) { - queue = (ngx_event_t **) (rev->accept ? - &ngx_posted_accept_events : &ngx_posted_events); + queue = rev->accept ? &ngx_posted_accept_events + : &ngx_posted_events; - ngx_locked_post_event(rev, queue); + ngx_post_event(rev, queue); } else { rev->handler(rev); @@ -708,15 +701,10 @@ ngx_epoll_process_events(ngx_cycle_t *cy continue; } - if (flags & NGX_POST_THREAD_EVENTS) { - wev->posted_ready = 1; - - } else { - wev->ready = 1; - } + wev->ready = 1; if (flags & NGX_POST_EVENTS) { - ngx_locked_post_event(wev, &ngx_posted_events); + ngx_post_event(wev, &ngx_posted_events); } else { wev->handler(wev); @@ -724,8 +712,6 @@ ngx_epoll_process_events(ngx_cycle_t *cy } } - ngx_mutex_unlock(ngx_posted_events_mutex); - return NGX_OK; } diff -r 8e7ee4c70a3c -r 3377f9459e99 src/event/modules/ngx_eventport_module.c --- a/src/event/modules/ngx_eventport_module.c Mon Sep 01 17:50:59 2014 +0400 +++ b/src/event/modules/ngx_eventport_module.c Mon Sep 01 18:20:03 2014 +0400 @@ -466,8 +466,6 @@ ngx_eventport_process_events(ngx_cycle_t return NGX_ERROR; } - ngx_mutex_lock(ngx_posted_events_mutex); - for (i = 0; i < events; i++) { if (event_list[i].portev_source == PORT_SOURCE_TIMER) { @@ -534,19 +532,13 @@ ngx_eventport_process_events(ngx_cycle_t wev->active = 0; if (revents & POLLIN) { - - if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { - rev->posted_ready = 1; - - } else { - rev->ready = 1; - } + rev->ready = 1; if (flags & NGX_POST_EVENTS) { - queue = (ngx_event_t **) (rev->accept ? - &ngx_posted_accept_events : &ngx_posted_events); + queue = rev->accept ? &ngx_posted_accept_events + : &ngx_posted_events; - ngx_locked_post_event(rev, queue); + ngx_post_event(rev, queue); } else { rev->handler(rev); @@ -574,16 +566,10 @@ ngx_eventport_process_events(ngx_cycle_t } if (revents & POLLOUT) { - - if (flags & NGX_POST_THREAD_EVENTS) { - wev->posted_ready = 1; - - } else { - wev->ready = 1; - } + wev->ready = 1; if (flags & NGX_POST_EVENTS) { - ngx_locked_post_event(wev, &ngx_posted_events); + ngx_post_event(wev, &ngx_posted_events); } else { wev->handler(wev); @@ -600,8 +586,6 @@ ngx_eventport_process_events(ngx_cycle_t } } - ngx_mutex_unlock(ngx_posted_events_mutex); - return NGX_OK; } diff -r 8e7ee4c70a3c -r 3377f9459e99 src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c Mon Sep 01 17:50:59 2014 +0400 +++ b/src/event/modules/ngx_kqueue_module.c Mon Sep 01 18:20:03 2014 +0400 @@ -573,8 +573,6 @@ ngx_kqueue_process_events(ngx_cycle_t *c return NGX_ERROR; } - ngx_mutex_lock(ngx_posted_events_mutex); - for (i = 0; i < events; i++) { ngx_kqueue_dump_event(cycle->log, &event_list[i]); @@ -626,24 +624,6 @@ ngx_kqueue_process_events(ngx_cycle_t *c ev->active = 0; } -#if (NGX_THREADS) - - if ((flags & NGX_POST_THREAD_EVENTS) && !ev->accept) { - ev->posted_ready = 1; - ev->posted_available = event_list[i].data; - - if (event_list[i].flags & EV_EOF) { - ev->posted_eof = 1; - ev->posted_errno = event_list[i].fflags; - } - - ngx_locked_post_event(ev, &ngx_posted_events); - - continue; - } - -#endif - ev->available = event_list[i].data; if (event_list[i].flags & EV_EOF) { @@ -674,9 +654,10 @@ ngx_kqueue_process_events(ngx_cycle_t *c } if (flags & NGX_POST_EVENTS) { - queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events: - &ngx_posted_events); - ngx_locked_post_event(ev, queue); + queue = ev->accept ? &ngx_posted_accept_events + : &ngx_posted_events; + From vbart at nginx.com Mon Sep 1 14:22:17 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 01 Sep 2014 14:22:17 +0000 Subject: [nginx] Events: processing of posted events changed from LIFO to... Message-ID: details: http://hg.nginx.org/nginx/rev/3f5f0ab59b35 branches: changeset: 5821:3f5f0ab59b35 user: Valentin Bartenev date: Mon Sep 01 18:20:18 2014 +0400 description: Events: processing of posted events changed from LIFO to FIFO. In theory, this can provide a bit better distribution of latencies. Also it simplifies the code, since ngx_queue_t is now used instead of custom implementation. diffstat: src/core/ngx_connection.c | 4 ++-- src/event/modules/ngx_devpoll_module.c | 3 ++- src/event/modules/ngx_epoll_module.c | 3 ++- src/event/modules/ngx_eventport_module.c | 3 ++- src/event/modules/ngx_kqueue_module.c | 3 ++- src/event/modules/ngx_poll_module.c | 3 ++- src/event/modules/ngx_rtsig_module.c | 6 ++++-- src/event/modules/ngx_select_module.c | 3 ++- src/event/modules/ngx_win32_select_module.c | 3 ++- src/event/ngx_event.c | 14 +++++--------- src/event/ngx_event.h | 9 +++++---- src/event/ngx_event_posted.c | 16 +++++++--------- src/event/ngx_event_posted.h | 27 +++++++++------------------ src/http/ngx_http_spdy.c | 4 ++-- 14 files changed, 48 insertions(+), 53 deletions(-) diffs (truncated from 312 to 300 lines): diff -r 3377f9459e99 -r 3f5f0ab59b35 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/core/ngx_connection.c Mon Sep 01 18:20:18 2014 +0400 @@ -955,11 +955,11 @@ ngx_close_connection(ngx_connection_t *c #endif - if (c->read->prev) { + if (c->read->posted) { ngx_delete_posted_event(c->read); } - if (c->write->prev) { + if (c->write->posted) { ngx_delete_posted_event(c->write); } diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/modules/ngx_devpoll_module.c --- a/src/event/modules/ngx_devpoll_module.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/modules/ngx_devpoll_module.c Mon Sep 01 18:20:18 2014 +0400 @@ -344,7 +344,8 @@ ngx_devpoll_process_events(ngx_cycle_t * ngx_err_t err; ngx_int_t i; ngx_uint_t level, instance; - ngx_event_t *rev, *wev, **queue; + ngx_event_t *rev, *wev; + ngx_queue_t *queue; ngx_connection_t *c; struct pollfd pfd; struct dvpoll dvp; diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/modules/ngx_epoll_module.c Mon Sep 01 18:20:18 2014 +0400 @@ -568,7 +568,8 @@ ngx_epoll_process_events(ngx_cycle_t *cy ngx_int_t instance, i; ngx_uint_t level; ngx_err_t err; - ngx_event_t *rev, *wev, **queue; + ngx_event_t *rev, *wev; + ngx_queue_t *queue; ngx_connection_t *c; /* NGX_TIMER_INFINITE == INFTIM */ diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/modules/ngx_eventport_module.c --- a/src/event/modules/ngx_eventport_module.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/modules/ngx_eventport_module.c Mon Sep 01 18:20:18 2014 +0400 @@ -414,7 +414,8 @@ ngx_eventport_process_events(ngx_cycle_t ngx_err_t err; ngx_int_t instance; ngx_uint_t i, level; - ngx_event_t *ev, *rev, *wev, **queue; + ngx_event_t *ev, *rev, *wev; + ngx_queue_t *queue; ngx_connection_t *c; struct timespec ts, *tp; diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/modules/ngx_kqueue_module.c Mon Sep 01 18:20:18 2014 +0400 @@ -495,7 +495,8 @@ ngx_kqueue_process_events(ngx_cycle_t *c ngx_int_t i, instance; ngx_uint_t level; ngx_err_t err; - ngx_event_t *ev, **queue; + ngx_event_t *ev; + ngx_queue_t *queue; struct timespec ts, *tp; if (ngx_threaded) { diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/modules/ngx_poll_module.c --- a/src/event/modules/ngx_poll_module.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/modules/ngx_poll_module.c Mon Sep 01 18:20:18 2014 +0400 @@ -241,7 +241,8 @@ ngx_poll_process_events(ngx_cycle_t *cyc int ready, revents; ngx_err_t err; ngx_uint_t i, found, level; - ngx_event_t *ev, **queue; + ngx_event_t *ev; + ngx_queue_t *queue; ngx_connection_t *c; /* NGX_TIMER_INFINITE == INFTIM */ diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/modules/ngx_rtsig_module.c --- a/src/event/modules/ngx_rtsig_module.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/modules/ngx_rtsig_module.c Mon Sep 01 18:20:18 2014 +0400 @@ -307,7 +307,8 @@ ngx_rtsig_process_events(ngx_cycle_t *cy ngx_int_t instance; ngx_err_t err; siginfo_t si; - ngx_event_t *rev, *wev, **queue; + ngx_event_t *rev, *wev; + ngx_queue_t *queue; struct timespec ts, *tp; struct sigaction sa; ngx_connection_t *c; @@ -480,7 +481,8 @@ ngx_rtsig_process_overflow(ngx_cycle_t * size_t len; ngx_err_t err; ngx_uint_t tested, n, i; - ngx_event_t *rev, *wev, **queue; + ngx_event_t *rev, *wev; + ngx_queue_t *queue; ngx_connection_t *c; ngx_rtsig_conf_t *rtscf; diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/modules/ngx_select_module.c --- a/src/event/modules/ngx_select_module.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/modules/ngx_select_module.c Mon Sep 01 18:20:18 2014 +0400 @@ -214,7 +214,8 @@ ngx_select_process_events(ngx_cycle_t *c int ready, nready; ngx_err_t err; ngx_uint_t i, found; - ngx_event_t *ev, **queue; + ngx_event_t *ev; + ngx_queue_t *queue; struct timeval tv, *tp; ngx_connection_t *c; diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/modules/ngx_win32_select_module.c --- a/src/event/modules/ngx_win32_select_module.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/modules/ngx_win32_select_module.c Mon Sep 01 18:20:18 2014 +0400 @@ -221,7 +221,8 @@ ngx_select_process_events(ngx_cycle_t *c int ready, nready; ngx_err_t err; ngx_uint_t i, found; - ngx_event_t *ev, **queue; + ngx_event_t *ev; + ngx_queue_t *queue; struct timeval tv, *tp; ngx_connection_t *c; diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/ngx_event.c --- a/src/event/ngx_event.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/ngx_event.c Mon Sep 01 18:20:18 2014 +0400 @@ -252,9 +252,7 @@ ngx_process_events_and_timers(ngx_cycle_ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "timer delta: %M", delta); - if (ngx_posted_accept_events) { - ngx_event_process_posted(cycle, &ngx_posted_accept_events); - } + ngx_event_process_posted(cycle, &ngx_posted_accept_events); if (ngx_accept_mutex_held) { ngx_shmtx_unlock(&ngx_accept_mutex); @@ -264,12 +262,7 @@ ngx_process_events_and_timers(ngx_cycle_ ngx_event_expire_timers(); } - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, - "posted events %p", ngx_posted_events); - - if (ngx_posted_events) { - ngx_event_process_posted(cycle, &ngx_posted_events); - } + ngx_event_process_posted(cycle, &ngx_posted_events); } @@ -612,6 +605,9 @@ ngx_event_process_init(ngx_cycle_t *cycl #endif + ngx_queue_init(&ngx_posted_accept_events); + ngx_queue_init(&ngx_posted_events); + if (ngx_event_timer_init(cycle->log) == NGX_ERROR) { return NGX_ERROR; } diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/ngx_event.h --- a/src/event/ngx_event.h Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/ngx_event.h Mon Sep 01 18:20:18 2014 +0400 @@ -74,6 +74,8 @@ struct ngx_event_s { /* the pending eof reported by kqueue, epoll or in aio chain operation */ unsigned pending_eof:1; + unsigned posted:1; + #if (NGX_WIN32) /* setsockopt(SO_UPDATE_ACCEPT_CONTEXT) was successful */ unsigned accept_context_updated:1; @@ -125,16 +127,15 @@ struct ngx_event_s { ngx_rbtree_node_t timer; + /* the posted queue */ + ngx_queue_t queue; + unsigned closed:1; /* to test on worker exit */ unsigned channel:1; unsigned resolver:1; - /* the links of the posted queue */ - ngx_event_t *next; - ngx_event_t **prev; - #if 0 diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/ngx_event_posted.c --- a/src/event/ngx_event_posted.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/ngx_event_posted.c Mon Sep 01 18:20:18 2014 +0400 @@ -10,26 +10,24 @@ #include -ngx_event_t *ngx_posted_accept_events; -ngx_event_t *ngx_posted_events; +ngx_queue_t ngx_posted_accept_events; +ngx_queue_t ngx_posted_events; void -ngx_event_process_posted(ngx_cycle_t *cycle, ngx_event_t **posted) +ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted) { + ngx_queue_t *q; ngx_event_t *ev; - for ( ;; ) { + while (!ngx_queue_empty(posted)) { - ev = *posted; + q = ngx_queue_head(posted); + ev = ngx_queue_data(q, ngx_event_t, queue); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "posted event %p", ev); - if (ev == NULL) { - return; - } - ngx_delete_posted_event(ev); ev->handler(ev); diff -r 3377f9459e99 -r 3f5f0ab59b35 src/event/ngx_event_posted.h --- a/src/event/ngx_event_posted.h Mon Sep 01 18:20:03 2014 +0400 +++ b/src/event/ngx_event_posted.h Mon Sep 01 18:20:18 2014 +0400 @@ -14,16 +14,11 @@ #include -#define ngx_post_event(ev, queue) \ +#define ngx_post_event(ev, q) \ \ - if (ev->prev == NULL) { \ - ev->next = *queue; \ - ev->prev = queue; \ - *queue = ev; \ - \ - if (ev->next) { \ - ev->next->prev = &ev->next; \ - } \ + if (!ev->posted) { \ + ev->posted = 1; \ + ngx_queue_insert_tail(q, &ev->queue); \ \ ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "post event %p", ev); \ \ @@ -35,23 +30,19 @@ #define ngx_delete_posted_event(ev) \ \ - *(ev->prev) = ev->next; \ + ev->posted = 0; \ + ngx_queue_remove(&ev->queue); \ \ - if (ev->next) { \ - ev->next->prev = ev->prev; \ - } \ - \ - ev->prev = NULL; \ ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, \ "delete posted event %p", ev); -void ngx_event_process_posted(ngx_cycle_t *cycle, ngx_event_t **posted); +void ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted); -extern ngx_event_t *ngx_posted_accept_events; -extern ngx_event_t *ngx_posted_events; +extern ngx_queue_t ngx_posted_accept_events; +extern ngx_queue_t ngx_posted_events; #endif /* _NGX_EVENT_POSTED_H_INCLUDED_ */ diff -r 3377f9459e99 -r 3f5f0ab59b35 src/http/ngx_http_spdy.c --- a/src/http/ngx_http_spdy.c Mon Sep 01 18:20:03 2014 +0400 +++ b/src/http/ngx_http_spdy.c Mon Sep 01 18:20:18 2014 +0400 @@ -3372,7 +3372,7 @@ ngx_http_spdy_close_stream(ngx_http_spdy ngx_del_timer(ev); } - if (ev->prev) { + if (ev->posted) { From steven.hartland at multiplay.co.uk Mon Sep 1 22:57:05 2014 From: steven.hartland at multiplay.co.uk (Steven Hartland) Date: Mon, 01 Sep 2014 22:57:05 +0000 Subject: [PATCH] Allow Partial Content responses to satisfy Range requests Message-ID: <0dc608b347e24b914ee1.1409612225@blade26.multiplay.co.uk> # HG changeset patch # User Steven Hartland # Date 1409611936 0 # Mon Sep 01 22:52:16 2014 +0000 # Node ID 0dc608b347e24b914ee193214857de15aad2ac0b # Parent 3f5f0ab59b359064db16e1aa52dfca335720dff6 Allow Partial Content responses to satisfy Range requests. Previously on 200 responsed could statisfy Range requests, this adds support for 206 responses (Partial Content) to also satisfy Range requests as long as the Range fits within the Partial Content. This can be used directly as well as by other modules where is can be used to build more complex responses, such as the response to a Range request from a predicable set of sub Range requests. diff -r 3f5f0ab59b35 -r 0dc608b347e2 src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c Mon Sep 01 18:20:18 2014 +0400 +++ b/src/http/modules/ngx_http_range_filter_module.c Mon Sep 01 22:52:16 2014 +0000 @@ -54,6 +54,8 @@ typedef struct { off_t offset; + off_t content_end; + off_t content_length; ngx_str_t boundary_header; ngx_array_t ranges; } ngx_http_range_filter_ctx_t; @@ -65,7 +67,8 @@ ngx_http_range_filter_ctx_t *ctx); static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx); -static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r); +static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r, + ngx_http_range_filter_ctx_t *ctx); static ngx_int_t ngx_http_range_test_overlapped(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); static ngx_int_t ngx_http_range_singlepart_body(ngx_http_request_t *r, @@ -76,6 +79,9 @@ static ngx_int_t ngx_http_range_header_filter_init(ngx_conf_t *cf); static ngx_int_t ngx_http_range_body_filter_init(ngx_conf_t *cf); +static ngx_int_t ngx_http_content_range_parse(ngx_http_request_t *r, + ngx_http_range_filter_ctx_t *ctx); + static ngx_http_module_t ngx_http_range_header_filter_module_ctx = { NULL, /* preconfiguration */ @@ -153,8 +159,8 @@ ngx_http_range_filter_ctx_t *ctx; if (r->http_version < NGX_HTTP_VERSION_10 - || r->headers_out.status != NGX_HTTP_OK - || r != r->main + || (r->headers_out.status != NGX_HTTP_OK + && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) || r->headers_out.content_length_n == -1 || !r->allow_ranges) { @@ -230,26 +236,35 @@ ranges = r->single_range ? 1 : clcf->max_ranges; - switch (ngx_http_range_parse(r, ctx, ranges)) { + switch (ngx_http_content_range_parse(r, ctx)) { case NGX_OK: - ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); + switch (ngx_http_range_parse(r, ctx, ranges)) { - r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; - r->headers_out.status_line.len = 0; + case NGX_OK: + ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); - if (ctx->ranges.nelts == 1) { - return ngx_http_range_singlepart_header(r, ctx); + r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; + r->headers_out.status_line.len = 0; + + if (ctx->ranges.nelts == 1) { + return ngx_http_range_singlepart_header(r, ctx); + } + + return ngx_http_range_multipart_header(r, ctx); + + case NGX_HTTP_RANGE_NOT_SATISFIABLE: + return ngx_http_range_not_satisfiable(r, ctx); + + case NGX_ERROR: + return NGX_ERROR; + + default: /* NGX_DECLINED */ + break; } - - return ngx_http_range_multipart_header(r, ctx); - + break; case NGX_HTTP_RANGE_NOT_SATISFIABLE: - return ngx_http_range_not_satisfiable(r); - - case NGX_ERROR: - return NGX_ERROR; - + return ngx_http_range_not_satisfiable(r, ctx); default: /* NGX_DECLINED */ break; } @@ -274,13 +289,12 @@ ngx_uint_t ranges) { u_char *p; - off_t start, end, size, content_length; + off_t start, end, size; ngx_uint_t suffix; ngx_http_range_t *range; p = r->headers_in.range->value.data + 6; size = 0; - content_length = r->headers_out.content_length_n; for ( ;; ) { start = 0; @@ -298,6 +312,10 @@ start = start * 10 + *p++ - '0'; } + if (start < ctx->offset) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + while (*p == ' ') { p++; } if (*p++ != '-') { @@ -307,7 +325,7 @@ while (*p == ' ') { p++; } if (*p == ',' || *p == '\0') { - end = content_length; + end = ctx->content_length; goto found; } @@ -324,6 +342,10 @@ end = end * 10 + *p++ - '0'; } + if (end > ctx->content_end) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + while (*p == ' ') { p++; } if (*p != ',' && *p != '\0') { @@ -331,12 +353,12 @@ } if (suffix) { - start = content_length - end; - end = content_length - 1; + start = ctx->content_length - end; + end = ctx->content_length - 1; } - if (end >= content_length) { - end = content_length; + if (end >= ctx->content_length) { + end = ctx->content_length; } else { end++; @@ -369,7 +391,7 @@ return NGX_HTTP_RANGE_NOT_SATISFIABLE; } - if (size > content_length) { + if (size > ctx->content_length) { return NGX_DECLINED; } @@ -384,16 +406,18 @@ ngx_table_elt_t *content_range; ngx_http_range_t *range; - content_range = ngx_list_push(&r->headers_out.headers); - if (content_range == NULL) { - return NGX_ERROR; + if (r->headers_out.content_range == NULL) { + content_range = ngx_list_push(&r->headers_out.headers); + if (content_range == NULL) { + return NGX_ERROR; + } + r->headers_out.content_range = content_range; + content_range->hash = 1; + ngx_str_set(&content_range->key, "Content-Range"); + } else { + content_range = r->headers_out.content_range; } - r->headers_out.content_range = content_range; - - content_range->hash = 1; - ngx_str_set(&content_range->key, "Content-Range"); - content_range->value.data = ngx_pnalloc(r->pool, sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN); if (content_range->value.data == NULL) { @@ -407,7 +431,7 @@ content_range->value.len = ngx_sprintf(content_range->value.data, "bytes %O-%O/%O", range->start, range->end - 1, - r->headers_out.content_length_n) + ctx->content_length) - content_range->value.data; r->headers_out.content_length_n = range->end - range->start; @@ -546,22 +570,25 @@ static ngx_int_t -ngx_http_range_not_satisfiable(ngx_http_request_t *r) +ngx_http_range_not_satisfiable(ngx_http_request_t *r, + ngx_http_range_filter_ctx_t *ctx) { ngx_table_elt_t *content_range; r->headers_out.status = NGX_HTTP_RANGE_NOT_SATISFIABLE; - content_range = ngx_list_push(&r->headers_out.headers); - if (content_range == NULL) { - return NGX_ERROR; + if (r->headers_out.content_range == NULL) { + content_range = ngx_list_push(&r->headers_out.headers); + if (content_range == NULL) { + return NGX_ERROR; + } + r->headers_out.content_range = content_range; + content_range->hash = 1; + ngx_str_set(&content_range->key, "Content-Range"); + } else { + content_range = r->headers_out.content_range; } - r->headers_out.content_range = content_range; - - content_range->hash = 1; - ngx_str_set(&content_range->key, "Content-Range"); - content_range->value.data = ngx_pnalloc(r->pool, sizeof("bytes */") - 1 + NGX_OFF_T_LEN); if (content_range->value.data == NULL) { @@ -570,7 +597,7 @@ content_range->value.len = ngx_sprintf(content_range->value.data, "bytes */%O", - r->headers_out.content_length_n) + ctx->content_length) - content_range->value.data; ngx_http_clear_content_length(r); @@ -888,3 +915,77 @@ return NGX_OK; } + +static ngx_int_t +ngx_http_content_range_parse(ngx_http_request_t *r, + ngx_http_range_filter_ctx_t *ctx) +{ + u_char *p; + off_t start, end, len; + + ctx->offset = 0; + ctx->content_end = r->headers_out.content_length_n - 1; + ctx->content_length = r->headers_out.content_length_n; + + if (r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) { + return NGX_OK; + } + + if (r->headers_out.content_range == NULL + || r->headers_out.content_range->value.len == 0) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + if (r->headers_out.content_range->value.len < 7 + || ngx_strncasecmp(r->headers_out.content_range->value.data, + (u_char *) "bytes ", 6) != 0) { + return NGX_DECLINED; + } + + start = 0; + end = 0; + len = 0; + + p = r->headers_out.content_range->value.data + 6; + + while (*p == ' ') { p++; } + + if (*p < '0' || *p > '9') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + while (*p >= '0' && *p <= '9') { + start = start * 10 + *p++ - '0'; + } + + if (*p++ != '-') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + while (*p >= '0' && *p <= '9') { + end = end * 10 + *p++ - '0'; + } + + if (*p++ != '/') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + if (*p < '0' || *p > '9') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + while (*p >= '0' && *p <= '9') { + len = len * 10 + *p++ - '0'; + } + + if (*p != '\0') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + ctx->offset = start; + ctx->content_end = end; + ctx->content_length = len; + + return NGX_OK; +} + diff -r 3f5f0ab59b35 -r 0dc608b347e2 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Mon Sep 01 18:20:18 2014 +0400 +++ b/src/http/ngx_http_upstream.c Mon Sep 01 22:52:16 2014 +0000 @@ -286,6 +286,11 @@ ngx_http_upstream_copy_content_encoding, 0, 0 }, #endif + { ngx_string("Content-Range"), + ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_copy_allow_ranges, + offsetof(ngx_http_headers_out_t, content_range), 1 }, + { ngx_null_string, NULL, 0, NULL, 0, 0 } }; @@ -4362,33 +4367,23 @@ ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - ngx_table_elt_t *ho; - #if (NGX_HTTP_CACHE) - if (r->cached) { r->allow_ranges = 1; - return NGX_OK; + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { + return NGX_OK; + } } if (r->upstream->cacheable) { r->allow_ranges = 1; r->single_range = 1; - return NGX_OK; - } - + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { + return NGX_OK; + } + } #endif - - ho = ngx_list_push(&r->headers_out.headers); - if (ho == NULL) { - return NGX_ERROR; - } - - *ho = *h; - - r->headers_out.accept_ranges = ho; - - return NGX_OK; + return ngx_http_upstream_copy_header_line(r, h, offset); } From agentzh at gmail.com Wed Sep 3 19:06:52 2014 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Wed, 3 Sep 2014 12:06:52 -0700 Subject: [BUG] ngx_http_sub_module fails to process single-char patterns Message-ID: Hello! I've noted a bug in nginx 1.7.4's standard ngx_http_sub_module that single-char patterns are never handled properly but longer patterns work. Consider the following minimal example: location = /t { default_type text/html; return 200 "hello world"; sub_filter 'h' ''; } Accessing /t gives the response body hello world instead of the expected output ello world The 'h' pattern is essentially ignored. Using longer patterns like 'he' in the example above works as expected though. Best regards, -agentzh From agentzh at gmail.com Wed Sep 3 19:09:41 2014 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Wed, 3 Sep 2014 12:09:41 -0700 Subject: [BUG] ngx_http_sub_module fails to process single-char patterns In-Reply-To: References: Message-ID: Hello! On Wed, Sep 3, 2014 at 12:06 PM, Yichun Zhang (agentzh) wrote: > I've noted a bug in nginx 1.7.4's standard ngx_http_sub_module that > single-char patterns are never handled properly but longer patterns > work. Oops, I used to report this issue almost 2 years ago: http://mailman.nginx.org/pipermail/nginx-devel/2012-December/003187.html I thought it was fixed :P Regards, -agentzh From thresh at nginx.com Wed Sep 3 19:20:10 2014 From: thresh at nginx.com (Konstantin Pavlov) Date: Wed, 03 Sep 2014 23:20:10 +0400 Subject: [BUG] ngx_http_sub_module fails to process single-char patterns In-Reply-To: References: Message-ID: <540769EA.7020700@nginx.com> On 03/09/2014 23:09, Yichun Zhang (agentzh) wrote: > Hello! > > On Wed, Sep 3, 2014 at 12:06 PM, Yichun Zhang (agentzh) wrote: >> I've noted a bug in nginx 1.7.4's standard ngx_http_sub_module that >> single-char patterns are never handled properly but longer patterns >> work. > > Oops, I used to report this issue almost 2 years ago: > > http://mailman.nginx.org/pipermail/nginx-devel/2012-December/003187.html > > I thought it was fixed :P And it was, nine days ago: http://hg.nginx.org/nginx/rev/5322be87fc02 :) -- Konstantin Pavlov From agentzh at gmail.com Wed Sep 3 19:57:35 2014 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Wed, 3 Sep 2014 12:57:35 -0700 Subject: [BUG] ngx_http_sub_module fails to process single-char patterns In-Reply-To: <540769EA.7020700@nginx.com> References: <540769EA.7020700@nginx.com> Message-ID: Hi Konstantin On Wed, Sep 3, 2014 at 12:20 PM, Konstantin Pavlov wrote: > > And it was, nine days ago: http://hg.nginx.org/nginx/rev/5322be87fc02 > Awesome! Thanks! Sorry for not checking the latest hg repos :) Regards, -agentzh From piotr at cloudflare.com Wed Sep 3 21:53:23 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 03 Sep 2014 14:53:23 -0700 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds Message-ID: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> # HG changeset patch # User Piotr Sikora # Date 1409780995 25200 # Wed Sep 03 14:49:55 2014 -0700 # Node ID 9c59138cd7030a88a761856f849c581924ca1a3b # Parent 3f5f0ab59b359064db16e1aa52dfca335720dff6 SSL: guard use of all SSL options for bug workarounds. Some of the OpenSSL forks (read: BoringSSL) started removing unused, no longer necessary and/or not really working bug workarounds along with the SSL options and defines for them. Instead of fixing nginx build after each removal, be proactive and guard use of all SSL options for bug workarounds. Signed-off-by: Piotr Sikora diff -r 3f5f0ab59b35 -r 9c59138cd703 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Mon Sep 01 18:20:18 2014 +0400 +++ b/src/event/ngx_event_openssl.c Wed Sep 03 14:49:55 2014 -0700 @@ -206,13 +206,23 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ /* client side options */ +#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG); +#endif + +#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG); +#endif /* server side options */ +#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG); +#endif + +#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER); +#endif #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */ @@ -223,10 +233,17 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG); #endif +#ifdef SSL_OP_TLS_D5_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG); +#endif + +#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG); - +#endif + +#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); +#endif SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE); From piotr at cloudflare.com Wed Sep 3 21:53:25 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 03 Sep 2014 14:53:25 -0700 Subject: [PATCH] SSL: enable CBC 1/n-1 record splitting on the client side Message-ID: <2d40a7b1e3bc01777fca.1409781205@piotrs-macbook-pro.local> # HG changeset patch # User Piotr Sikora # Date 1409780995 25200 # Wed Sep 03 14:49:55 2014 -0700 # Node ID 2d40a7b1e3bc01777fcae9576b3860e70ca273bb # Parent 3f5f0ab59b359064db16e1aa52dfca335720dff6 SSL: enable CBC 1/n-1 record splitting on the client side. This is currently available only in BoringSSL, where it replaced CBC 0/n record splitting (empty fragments), which is disabled in nginx due to the (legacy?) interoperability issues. Signed-off-by: Piotr Sikora diff -r 3f5f0ab59b35 -r 2d40a7b1e3bc src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Mon Sep 01 18:20:18 2014 +0400 +++ b/src/event/ngx_event_openssl.c Wed Sep 03 14:49:55 2014 -0700 @@ -972,6 +972,10 @@ ngx_ssl_create_connection(ngx_ssl_t *ssl if (flags & NGX_SSL_CLIENT) { SSL_set_connect_state(sc->connection); +#ifdef SSL_MODE_CBC_RECORD_SPLITTING + SSL_set_mode(sc->connection, SSL_MODE_CBC_RECORD_SPLITTING); +#endif + } else { SSL_set_accept_state(sc->connection); } From richard at fussenegger.info Thu Sep 4 08:28:39 2014 From: richard at fussenegger.info (Richard Fussenegger, BSc) Date: Thu, 04 Sep 2014 10:28:39 +0200 Subject: [PATCH] SSL: enable CBC 1/n-1 record splitting on the client side In-Reply-To: <2d40a7b1e3bc01777fca.1409781205@piotrs-macbook-pro.local> References: <2d40a7b1e3bc01777fca.1409781205@piotrs-macbook-pro.local> Message-ID: <540822B7.5010809@fussenegger.info> Definitely not a legacy interoperability issue, e.g.: https://bugzilla.mozilla.org/show_bug.cgi?id=665814#c59 Even with the 1/n-1 many problems arise but at least not as much as with the 0/n approach: https://www.imperialviolet.org/2012/01/15/beastfollowup.html Richard On 9/3/2014 11:53 PM, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1409780995 25200 > # Wed Sep 03 14:49:55 2014 -0700 > # Node ID 2d40a7b1e3bc01777fcae9576b3860e70ca273bb > # Parent 3f5f0ab59b359064db16e1aa52dfca335720dff6 > SSL: enable CBC 1/n-1 record splitting on the client side. > > This is currently available only in BoringSSL, where it replaced > CBC 0/n record splitting (empty fragments), which is disabled in > nginx due to the (legacy?) interoperability issues. > > Signed-off-by: Piotr Sikora > > diff -r 3f5f0ab59b35 -r 2d40a7b1e3bc src/event/ngx_event_openssl.c > --- a/src/event/ngx_event_openssl.c Mon Sep 01 18:20:18 2014 +0400 > +++ b/src/event/ngx_event_openssl.c Wed Sep 03 14:49:55 2014 -0700 > @@ -972,6 +972,10 @@ ngx_ssl_create_connection(ngx_ssl_t *ssl > if (flags & NGX_SSL_CLIENT) { > SSL_set_connect_state(sc->connection); > > +#ifdef SSL_MODE_CBC_RECORD_SPLITTING > + SSL_set_mode(sc->connection, SSL_MODE_CBC_RECORD_SPLITTING); > +#endif > + > } else { > SSL_set_accept_state(sc->connection); > } > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From arut at nginx.com Fri Sep 5 14:16:13 2014 From: arut at nginx.com (Roman Arutyunyan) Date: Fri, 05 Sep 2014 14:16:13 +0000 Subject: [nginx] Upstream: suppressed the file cache slab allocator error... Message-ID: details: http://hg.nginx.org/nginx/rev/063f7e75f9ef branches: changeset: 5822:063f7e75f9ef user: Roman Arutyunyan date: Fri Sep 05 18:14:59 2014 +0400 description: Upstream: suppressed the file cache slab allocator error messages. The messages "ngx_slab_alloc() failed: no memory in cache keys zone" from the file cache slab allocator are suppressed since the allocation is likely to succeed after the forced expiration of cache nodes. The second allocation failure is reported. diffstat: src/http/ngx_http_file_cache.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (21 lines): diff -r 3f5f0ab59b35 -r 063f7e75f9ef src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c Mon Sep 01 18:20:18 2014 +0400 +++ b/src/http/ngx_http_file_cache.c Fri Sep 05 18:14:59 2014 +0400 @@ -145,6 +145,8 @@ ngx_http_file_cache_init(ngx_shm_zone_t ngx_sprintf(cache->shpool->log_ctx, " in cache keys zone \"%V\"%Z", &shm_zone->shm.name); + cache->shpool->log_nomem = 0; + return NGX_OK; } @@ -698,6 +700,8 @@ ngx_http_file_cache_exists(ngx_http_file fcn = ngx_slab_calloc_locked(cache->shpool, sizeof(ngx_http_file_cache_node_t)); if (fcn == NULL) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "could not allocate node%s", cache->shpool->log_ctx); rc = NGX_ERROR; goto failed; } From mdounin at mdounin.ru Fri Sep 5 18:25:18 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 5 Sep 2014 22:25:18 +0400 Subject: [PATCH 1 of 2] clear err when ngx_regex_compile has allocation failure In-Reply-To: References: Message-ID: <20140905182518.GK1634@mdounin.ru> Hello! On Sun, Aug 17, 2014 at 11:00:29PM +0300, Markus Linnala wrote: > # HG changeset patch > # User Markus Linnala > # Date 1408303316 -10800 > # Sun Aug 17 22:21:56 2014 +0300 > # Node ID d350d288cffef0e6395ae1f412842c3b55bc8d42 > # Parent 0719145489f842b14765506f8856798c2203e3cc > clear err when ngx_regex_compile has allocation failure > > diff -r 0719145489f8 -r d350d288cffe src/core/ngx_regex.c > --- a/src/core/ngx_regex.c Sun Aug 17 21:59:38 2014 +0300 > +++ b/src/core/ngx_regex.c Sun Aug 17 22:21:56 2014 +0300 > @@ -149,6 +149,7 @@ > > rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t)); > if (rc->regex == NULL) { > + rc->err.len = 0; > return NGX_ERROR; > } > > @@ -159,6 +160,7 @@ > if (ngx_pcre_studies != NULL) { > elt = ngx_list_push(ngx_pcre_studies); > if (elt == NULL) { > + rc->err.len = 0; > return NGX_ERROR; > } This doesn't looks good, as it will result in empty errors being logged in such cases. Something like this should be more user-friendly (and it also fixes another long-standing bug): # HG changeset patch # User Maxim Dounin # Date 1409938779 -14400 # Fri Sep 05 21:39:39 2014 +0400 # Node ID f43551f64d028de939332ab9b66c3620b4259e08 # Parent 063f7e75f9efd56f3aaa3d9c24c98ed3f42348ea Core: ngx_regex_compile() error handling fixes. Now we actually return NGX_ERROR on errors, and provide an error string for memory allocation errors. Reported by Markus Linnala. diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c --- a/src/core/ngx_regex.c +++ b/src/core/ngx_regex.c @@ -149,7 +149,8 @@ ngx_regex_compile(ngx_regex_compile_t *r rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t)); if (rc->regex == NULL) { - return NGX_ERROR; + p = "regex \"%V\" compilation failed: no memory"; + goto failed; } rc->regex->code = re; @@ -159,7 +160,8 @@ ngx_regex_compile(ngx_regex_compile_t *r if (ngx_pcre_studies != NULL) { elt = ngx_list_push(ngx_pcre_studies); if (elt == NULL) { - return NGX_ERROR; + p = "regex \"%V\" compilation failed: no memory"; + goto failed; } elt->regex = rc->regex; @@ -204,7 +206,7 @@ failed: rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n) - rc->err.data; - return NGX_OK; + return NGX_ERROR; } -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Fri Sep 5 18:27:32 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 5 Sep 2014 22:27:32 +0400 Subject: [PATCH 2 of 2] fix ETag allocation failure In-Reply-To: <6af8cc12f3c933eed752.1408305630@maage-hp-eb.localdomain> References: <6af8cc12f3c933eed752.1408305630@maage-hp-eb.localdomain> Message-ID: <20140905182732.GL1634@mdounin.ru> Hello! On Sun, Aug 17, 2014 at 11:00:30PM +0300, Markus Linnala wrote: > # HG changeset patch > # User Markus Linnala > # Date 1408305457 -10800 > # Sun Aug 17 22:57:37 2014 +0300 > # Node ID 6af8cc12f3c933eed752e9ca61622d27a909ca00 > # Parent d350d288cffef0e6395ae1f412842c3b55bc8d42 > fix ETag allocation failure > > diff -r d350d288cffe -r 6af8cc12f3c9 src/http/ngx_http_core_module.c > --- a/src/http/ngx_http_core_module.c Sun Aug 17 22:21:56 2014 +0300 > +++ b/src/http/ngx_http_core_module.c Sun Aug 17 22:57:37 2014 +0300 > @@ -1832,14 +1832,15 @@ > return NGX_ERROR; > } > > + etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3); > + if (etag->value.data == NULL) { > + etag->hash = 0; > + return NGX_ERROR; > + } > + > etag->hash = 1; > ngx_str_set(&etag->key, "ETag"); > > - etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3); > - if (etag->value.data == NULL) { > - return NGX_ERROR; > - } > - I don't think that moving the allocation make sense as anyway etag->hash has to be explicitly set in the error path. Something like this should be better: # HG changeset patch # User Maxim Dounin # Date 1409941111 -14400 # Fri Sep 05 22:18:31 2014 +0400 # Node ID a80ee1f90b2b2c6cdee4e9b0ba2e0d48cad0f011 # Parent f43551f64d028de939332ab9b66c3620b4259e08 Fixed ETag memory allocation error handling. The etag->hash must be set to 0 to avoid an empty ETag header being returned with the 500 Internal Error page after the memory allocation failure. Reported by Markus Linnala. diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1837,6 +1837,7 @@ ngx_http_set_etag(ngx_http_request_t *r) etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3); if (etag->value.data == NULL) { + etag->hash = 0; return NGX_ERROR; } -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Fri Sep 5 18:38:54 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 5 Sep 2014 22:38:54 +0400 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds In-Reply-To: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> References: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> Message-ID: <20140905183854.GM1634@mdounin.ru> Hello! On Wed, Sep 03, 2014 at 02:53:23PM -0700, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1409780995 25200 > # Wed Sep 03 14:49:55 2014 -0700 > # Node ID 9c59138cd7030a88a761856f849c581924ca1a3b > # Parent 3f5f0ab59b359064db16e1aa52dfca335720dff6 > SSL: guard use of all SSL options for bug workarounds. > > Some of the OpenSSL forks (read: BoringSSL) started removing unused, > no longer necessary and/or not really working bug workarounds along > with the SSL options and defines for them. > > Instead of fixing nginx build after each removal, be proactive > and guard use of all SSL options for bug workarounds. After looking into http://trac.nginx.org/nginx/ticket/618, I'm rather sceptical about BoringSSL-related fixes. On the other hand, if they indeed remove something we use, it may be a good enough reason to reconsider the use of the flags removed. -- Maxim Dounin http://nginx.org/ From piotr at cloudflare.com Mon Sep 8 08:06:15 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Mon, 8 Sep 2014 01:06:15 -0700 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds In-Reply-To: <20140905183854.GM1634@mdounin.ru> References: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> <20140905183854.GM1634@mdounin.ru> Message-ID: Hey Maxim, > After looking into http://trac.nginx.org/nginx/ticket/618, > I'm rather sceptical about BoringSSL-related fixes. To be fair, it was a regression that was fixed pretty fast once reported. > On the other hand, if they indeed remove something we use, it may > be a good enough reason to reconsider the use of the flags > removed. Most of the defines that they removed (SSL_OP_MICROSOFT_SESS_ID_BUG, SSL_OP_NETSCAPE_CHALLENGE_BUG, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG and SSL_OP_MSIE_SSLV2_RSA_PADDING) were for options that were removed from BoringSSL along SSLv2 support. They also removed SSL_OP_TLS_BLOCK_PADDING_BUG, which was broken for a while and SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, which nginx uses to disable CBC 0/n record splitting, which they replaced with CBC 1/n-1 record splitting that is not enabled by default (see my other patch). This, however, doesn't mean that those options aren't doing anything in OpenSSL (or LibreSSL, for that matter), especially when you insist on supporting ancient versions of OpenSSL, so I don't think that we should remove them from nginx. Best regards, Piotr Sikora From richard at fussenegger.info Mon Sep 8 11:01:02 2014 From: richard at fussenegger.info (Richard Fussenegger, BSc) Date: Mon, 08 Sep 2014 13:01:02 +0200 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds In-Reply-To: References: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> <20140905183854.GM1634@mdounin.ru> Message-ID: <540D8C6E.1090500@fussenegger.info> Wouldn't it be better to drop support for ancient OpenSSL versions? It would be a great step for performance and security. Are there any good reasons to support old OpenSSL versions? Richard On 9/8/2014 10:06 AM, Piotr Sikora wrote: > Hey Maxim, > >> After looking into http://trac.nginx.org/nginx/ticket/618, >> I'm rather sceptical about BoringSSL-related fixes. > To be fair, it was a regression that was fixed pretty fast once reported. > >> On the other hand, if they indeed remove something we use, it may >> be a good enough reason to reconsider the use of the flags >> removed. > Most of the defines that they removed (SSL_OP_MICROSOFT_SESS_ID_BUG, > SSL_OP_NETSCAPE_CHALLENGE_BUG, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG and > SSL_OP_MSIE_SSLV2_RSA_PADDING) were for options that were removed from > BoringSSL along SSLv2 support. > > They also removed SSL_OP_TLS_BLOCK_PADDING_BUG, which was broken for a > while and SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, which nginx uses to > disable CBC 0/n record splitting, which they replaced with CBC 1/n-1 > record splitting that is not enabled by default (see my other patch). > > This, however, doesn't mean that those options aren't doing anything > in OpenSSL (or LibreSSL, for that matter), especially when you insist > on supporting ancient versions of OpenSSL, so I don't think that we > should remove them from nginx. > > Best regards, > Piotr Sikora > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel --- This email is free from viruses and malware because avast! Antivirus protection is active. http://www.avast.com From mdounin at mdounin.ru Mon Sep 8 17:12:25 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 08 Sep 2014 17:12:25 +0000 Subject: [nginx] SSL: guard use of all SSL options for bug workarounds. Message-ID: details: http://hg.nginx.org/nginx/rev/275e35d54626 branches: changeset: 5823:275e35d54626 user: Piotr Sikora date: Wed Sep 03 14:49:55 2014 -0700 description: SSL: guard use of all SSL options for bug workarounds. Some of the OpenSSL forks (read: BoringSSL) started removing unused, no longer necessary and/or not really working bug workarounds along with the SSL options and defines for them. Instead of fixing nginx build after each removal, be proactive and guard use of all SSL options for bug workarounds. Signed-off-by: Piotr Sikora diffstat: src/event/ngx_event_openssl.c | 19 ++++++++++++++++++- 1 files changed, 18 insertions(+), 1 deletions(-) diffs (46 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -206,13 +206,23 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ /* client side options */ +#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG); +#endif + +#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG); +#endif /* server side options */ +#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG); +#endif + +#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER); +#endif #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */ @@ -223,10 +233,17 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG); #endif +#ifdef SSL_OP_TLS_D5_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG); +#endif + +#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG); - +#endif + +#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); +#endif SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE); From mdounin at mdounin.ru Mon Sep 8 17:12:38 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 8 Sep 2014 21:12:38 +0400 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds In-Reply-To: References: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> <20140905183854.GM1634@mdounin.ru> Message-ID: <20140908171238.GE59236@mdounin.ru> Hello! On Mon, Sep 08, 2014 at 01:06:15AM -0700, Piotr Sikora wrote: > Hey Maxim, > > > After looking into http://trac.nginx.org/nginx/ticket/618, > > I'm rather sceptical about BoringSSL-related fixes. > > To be fair, it was a regression that was fixed pretty fast once reported. The question is how many other such regressions was introduced and not yet reported. > > On the other hand, if they indeed remove something we use, it may > > be a good enough reason to reconsider the use of the flags > > removed. > > Most of the defines that they removed (SSL_OP_MICROSOFT_SESS_ID_BUG, > SSL_OP_NETSCAPE_CHALLENGE_BUG, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG and > SSL_OP_MSIE_SSLV2_RSA_PADDING) were for options that were removed from > BoringSSL along SSLv2 support. > > They also removed SSL_OP_TLS_BLOCK_PADDING_BUG, which was broken for a > while and SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, which nginx uses to > disable CBC 0/n record splitting, which they replaced with CBC 1/n-1 > record splitting that is not enabled by default (see my other patch). > > This, however, doesn't mean that those options aren't doing anything > in OpenSSL (or LibreSSL, for that matter), especially when you insist > on supporting ancient versions of OpenSSL, so I don't think that we > should remove them from nginx. Ok, it looks like there are no reasons to remove workarounds in question. And as SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER and SSL_OP_TLS_D5_BUG are the only remaining workarounds without guards, it make sense to just use #ifdef's for all of them. Committed, thanks. -- Maxim Dounin http://nginx.org/ From quanah at zimbra.com Mon Sep 8 17:18:47 2014 From: quanah at zimbra.com (Quanah Gibson-Mount) Date: Mon, 08 Sep 2014 10:18:47 -0700 Subject: SASL support for mail proxy in NGINX In-Reply-To: <639768787.1257597.1408744223634.JavaMail.zimbra@zimbra.com> References: <639768787.1257597.1408744223634.JavaMail.zimbra@zimbra.com> Message-ID: <16F955A2D49E0C06AC57A36F@[192.168.1.2]> --On Friday, August 22, 2014 5:50 PM -0500 Kunal Pariani wrote: > > > Hello, > Wanted to know if there's a plan to add SASL support to Nginx anytime > soon ? > > Zimbra has patches that add SASL support for POP3 & IMAP. Would you be > interested in that as a contribution from us ? > > We plan on adding SASL support to SMTP as well unless you guys have plan > to do that already ? Any nginx developers have any thoughts on this? Thanks, Quanah -- Quanah Gibson-Mount Server Architect Zimbra, Inc. -------------------- Zimbra :: the leader in open source messaging and collaboration From quanah at zimbra.com Mon Sep 8 17:19:17 2014 From: quanah at zimbra.com (Quanah Gibson-Mount) Date: Mon, 08 Sep 2014 10:19:17 -0700 Subject: [PATCH] SSL support for the mail proxy module In-Reply-To: <1971574953.1254572.1408742007421.JavaMail.zimbra@zimbra.com> References: <1399448073.850051.1408489095173.JavaMail.zimbra@zimbra.com> <1971574953.1254572.1408742007421.JavaMail.zimbra@zimbra.com> Message-ID: <2B39312159AE5CF614E0F6B2@[192.168.1.2]> --On Friday, August 22, 2014 5:13 PM -0500 Kunal Pariani wrote: > > > Any comments on this yet ? Any nginx developers who could comment on this? --Quanah > __________________________________________________ > > From: "Kunal Pariani" > To: "nginx-devel" > Sent: Tuesday, August 19, 2014 3:58:15 PM > Subject: [PATCH] SSL support for the mail proxy module > > > > > ># HG changeset patch > ># User Kunal Pariani > ># Date 1408485440 25200 > ># Tue Aug 19 14:57:20 2014 -0700 > ># Node ID 7858c2a9ac0e83aa779197fc028b4d078612e7e8 > ># Parent f25ab24517bb5e45b1b7fa1a1502b907f2cff213 > > SSL support for the mail proxy > > > > diff -r f25ab24517bb -r 7858c2a9ac0e src/mail/ngx_mail_proxy_module.c > > --- a/src/mail/ngx_mail_proxy_module.c Mon Aug 04 16:26:30 2014 -0700 > > +++ b/src/mail/ngx_mail_proxy_module.c Tue Aug 19 14:57:20 2014 -0700 > > @@ -18,6 +18,8 @@ > > ngx_flag_t xclient; > > size_t buffer_size; > > ngx_msec_t timeout; > > + ngx_flag_t proxy_ssl; > > + ngx_ssl_t *ssl; > > } ngx_mail_proxy_conf_t; > > > > > > @@ -35,7 +37,13 @@ > > static void *ngx_mail_proxy_create_conf(ngx_conf_t *cf); > > static char *ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, > > void *child); > > - > > +#if (NGX_MAIL_SSL) > > +static char *ngx_mail_proxy_ssl(ngx_conf_t *cf, ngx_command_t *cmd, > > + void *conf); > > +static void ngx_mail_proxy_ssl_init_connection(ngx_mail_session_t *s, > > + ngx_connection_t *c); > > +static void ngx_mail_proxy_ssl_handshake(ngx_connection_t *c); > > +#endif > > > > static ngx_command_t ngx_mail_proxy_commands[] = { > > > > @@ -74,6 +82,16 @@ > > offsetof(ngx_mail_proxy_conf_t, xclient), > > NULL }, > > > > +#if (NGX_MAIL_SSL) > > + { ngx_string("proxy_ssl"), > > + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, > > + ngx_mail_proxy_ssl, > > + NGX_MAIL_SRV_CONF_OFFSET, > > + offsetof(ngx_mail_proxy_conf_t, proxy_ssl), > > + NULL }, > > + > > +#endif > > + > > ngx_null_command > > }; > > > > @@ -174,6 +192,15 @@ > > > > s->out.len = 0; > > > > +#if (NGX_MAIL_SSL) > > + > > + if (pcf->proxy_ssl && p->upstream.connection->ssl == NULL) { > > + ngx_mail_proxy_ssl_init_connection(s, p->upstream.connection); > > + return; > > + } > > + > > +#endif > > + > > switch (s->protocol) { > > > > case NGX_MAIL_POP3_PROTOCOL: > > @@ -1092,6 +1119,13 @@ > > "close mail proxy connection: %d", > > s->proxy->upstream.connection->fd); > > > > +#if (NGX_MAIL_SSL) > > + if (s->proxy->upstream.connection->ssl) { > > + s->proxy->upstream.connection->ssl->no_wait_shutdown = 1; > > + ngx_ssl_shutdown(s->proxy->upstream.connection); > > + } > > +#endif > > + > > ngx_close_connection(s->proxy->upstream.connection); > > } > > > > @@ -1114,6 +1148,8 @@ > > pcf->xclient = NGX_CONF_UNSET; > > pcf->buffer_size = NGX_CONF_UNSET_SIZE; > > pcf->timeout = NGX_CONF_UNSET_MSEC; > > + pcf->proxy_ssl = NGX_CONF_UNSET; > > + pcf->ssl = NGX_CONF_UNSET_PTR; > > > > return pcf; > > } > > @@ -1131,6 +1167,118 @@ > > ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, > > (size_t) ngx_pagesize); > > ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * > 60000); > > + ngx_conf_merge_value(conf->proxy_ssl, prev->proxy_ssl, 0); > > + ngx_conf_merge_ptr_value(conf->ssl, prev->ssl, NULL); > > > > return NGX_CONF_OK; > > } > > + > > +#if (NGX_MAIL_SSL) > > + > > +static char * > > +ngx_mail_proxy_ssl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { > > + > > + ngx_pool_cleanup_t *cln; > > + char *rc; > > + ngx_mail_proxy_conf_t *pcf; > > + > > + rc = ngx_conf_set_flag_slot(cf, cmd, conf); > > + if (rc != NGX_CONF_OK) { > > + return rc; > > + } > > + > > + pcf = (ngx_mail_proxy_conf_t *)conf; > > + > > + if (!pcf->proxy_ssl) { > > + return NGX_CONF_OK; > > + } > > + > > + pcf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); > > + > > + if (pcf->ssl == NULL) { > > + return NGX_CONF_ERROR; > > + } > > + > > + pcf->ssl->log = cf->log; > > + > > + // don't support SSLv2 anymore > > + if (ngx_ssl_create(pcf->ssl, NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL) > > + != NGX_OK) { > > + return NGX_CONF_ERROR; > > + } > > + > > + cln = ngx_pool_cleanup_add(cf->pool, 0); > > + if (cln == NULL) { > > + return NGX_CONF_ERROR; > > + } > > + > > + cln->handler = ngx_ssl_cleanup_ctx; > > + cln->data = pcf->ssl; > > + > > + return NGX_CONF_OK; > > +} > > + > > +static void > > +ngx_mail_proxy_ssl_init_connection(ngx_mail_session_t *s, > ngx_connection_t *c) > > +{ > > + ngx_int_t rc; > > + ngx_mail_proxy_conf_t *pcf; > > + > > + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); > > + > > + if (ngx_ssl_create_connection(pcf->ssl, c, > > + NGX_SSL_BUFFER|NGX_SSL_CLIENT) > > + != NGX_OK) > > + { > > + ngx_mail_proxy_internal_server_error(s); > > + return; > > + } > > + > > + s->connection->log->action = "SSL handshaking to upstream"; > > + > > + rc = ngx_ssl_handshake(c); > > + > > + if (rc == NGX_AGAIN) { > > + c->ssl->handler = ngx_mail_proxy_ssl_handshake; > > + return; > > + } > > + > > + ngx_mail_proxy_ssl_handshake(c); > > +} > > + > > + > > +static void > > +ngx_mail_proxy_ssl_handshake(ngx_connection_t *c) > > +{ > > + ngx_mail_session_t *s; > > + s = c->data; > > + > > + if (c->ssl->handshaked) { > > + c->write->handler = ngx_mail_proxy_dummy_handler; > > + switch (s->protocol) { > > + > > + case NGX_MAIL_POP3_PROTOCOL: > > + c->read->handler = ngx_mail_proxy_pop3_handler; > > + s->mail_state = ngx_pop3_start; > > + break; > > + > > + case NGX_MAIL_IMAP_PROTOCOL: > > + c->read->handler = ngx_mail_proxy_imap_handler; > > + s->mail_state = ngx_imap_start; > > + break; > > + > > + default: /* NGX_MAIL_SMTP_PROTOCOL */ > > + c->read->handler = ngx_mail_proxy_smtp_handler; > > + s->mail_state = ngx_smtp_start; > > + break; > > + } > > + > > + /* server might have sent the initial welcome msg */ > > + c->read->handler(c->read); > > + } else { > > + /* when handshake fails, we should close the session */ > > + ngx_mail_proxy_upstream_error(s); > > + } > > +} > > + > > +#endif > > > Thanks > -Kunal > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Quanah Gibson-Mount Server Architect Zimbra, Inc. -------------------- Zimbra :: the leader in open source messaging and collaboration From mdounin at mdounin.ru Mon Sep 8 17:22:14 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 8 Sep 2014 21:22:14 +0400 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds In-Reply-To: <540D8C6E.1090500@fussenegger.info> References: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> <20140905183854.GM1634@mdounin.ru> <540D8C6E.1090500@fussenegger.info> Message-ID: <20140908172213.GF59236@mdounin.ru> Hello! On Mon, Sep 08, 2014 at 01:01:02PM +0200, Richard Fussenegger, BSc wrote: > Wouldn't it be better to drop support for ancient OpenSSL versions? It would > be a great step for performance and security. Are there any good reasons to > support old OpenSSL versions? Dropping support doesn't changes anything for ones who uses modern versions of the OpenSSL library. And will upset ones who, for some reason, have to use old versions. The only benefit of dropping support for older OpenSSL versions is slightly lower code maintenance costs on nginx side. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Sep 8 19:24:03 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 8 Sep 2014 23:24:03 +0400 Subject: [PATCH] SSL support for the mail proxy module In-Reply-To: <2B39312159AE5CF614E0F6B2@[192.168.1.2]> References: <1399448073.850051.1408489095173.JavaMail.zimbra@zimbra.com> <1971574953.1254572.1408742007421.JavaMail.zimbra@zimbra.com> <2B39312159AE5CF614E0F6B2@[192.168.1.2]> Message-ID: <20140908192402.GG59236@mdounin.ru> Hello! On Mon, Sep 08, 2014 at 10:19:17AM -0700, Quanah Gibson-Mount wrote: > --On Friday, August 22, 2014 5:13 PM -0500 Kunal Pariani > wrote: > > > > > > >Any comments on this yet ? > > Any nginx developers who could comment on this? Some obvious problems with the patch: - it's corrupted by author's mail client, and hence can't be applied/tested; - there are various style violations, like C++-style comments; - it introduces yet another "SSL without certificate verification" case, which is believed to be bad (similar thing was recently resolved by introducing proxy_ssl_verify in the http proxy module); Some more comments below. [...] > >+ // don't support SSLv2 anymore > > > >+ if (ngx_ssl_create(pcf->ssl, NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL) > > > >+ != NGX_OK) { It is incorrect to support SSLv3 and TLSv1 only. By default NGX_SSL_TLSv1_1 and NGX_SSL_TLSv1_2 should be allowed, too. It's also may be a good idea to make this configurable like in http proxy module. Also, 2 style issues here: "//" comment and incorrectly placed "{". [...] > >+ if (ngx_ssl_create_connection(pcf->ssl, c, > > > >+ NGX_SSL_BUFFER|NGX_SSL_CLIENT) > > > >+ != NGX_OK) > > > >+ { The NGX_SSL_BUFFER is incorrect here. It won't currently make any difference as the code only uses c->recv() / c->send(), but nevertheless mail protocols doesn't assume buffering, and the mail module doesn't use NGX_SSL_BUFFER in ngx_ssl_create_connection() calls intentionally. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Sep 8 19:49:33 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 8 Sep 2014 23:49:33 +0400 Subject: SASL support for mail proxy in NGINX In-Reply-To: <16F955A2D49E0C06AC57A36F@[192.168.1.2]> References: <639768787.1257597.1408744223634.JavaMail.zimbra@zimbra.com> <16F955A2D49E0C06AC57A36F@[192.168.1.2]> Message-ID: <20140908194933.GH59236@mdounin.ru> Hello! On Mon, Sep 08, 2014 at 10:18:47AM -0700, Quanah Gibson-Mount wrote: > --On Friday, August 22, 2014 5:50 PM -0500 Kunal Pariani > wrote: > > > > > > >Hello, > >Wanted to know if there's a plan to add SASL support to Nginx anytime > >soon ? > > > >Zimbra has patches that add SASL support for POP3 & IMAP. Would you be > >interested in that as a contribution from us ? > > > >We plan on adding SASL support to SMTP as well unless you guys have plan > >to do that already ? > > Any nginx developers have any thoughts on this? When talking to mail backends, nginx doesn't use SASL for authentication as it's believed to be superfluous to use it instead of native protocol commands in the non-hostile backend environment. There is SASL support in nginx mail module though, and it happily authenticates users with PLAIN, LOGIN and CRAM-MD5 SASL mechanisms (as long as http_auth script used is able to handle this). -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Sep 8 20:27:54 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 08 Sep 2014 20:27:54 +0000 Subject: [nginx] Core: ngx_regex_compile() error handling fixes. Message-ID: details: http://hg.nginx.org/nginx/rev/e7f6991eca47 branches: changeset: 5824:e7f6991eca47 user: Maxim Dounin date: Mon Sep 08 21:35:53 2014 +0400 description: Core: ngx_regex_compile() error handling fixes. Now we actually return NGX_ERROR on errors, and provide an error string for memory allocation errors. Reported by Markus Linnala. diffstat: src/core/ngx_regex.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diffs (38 lines): diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c --- a/src/core/ngx_regex.c +++ b/src/core/ngx_regex.c @@ -149,7 +149,7 @@ ngx_regex_compile(ngx_regex_compile_t *r rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t)); if (rc->regex == NULL) { - return NGX_ERROR; + goto nomem; } rc->regex->code = re; @@ -159,7 +159,7 @@ ngx_regex_compile(ngx_regex_compile_t *r if (ngx_pcre_studies != NULL) { elt = ngx_list_push(ngx_pcre_studies); if (elt == NULL) { - return NGX_ERROR; + goto nomem; } elt->regex = rc->regex; @@ -204,7 +204,15 @@ failed: rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n) - rc->err.data; - return NGX_OK; + return NGX_ERROR; + +nomem: + + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "regex \"%V\" compilation failed: no memory", + &rc->pattern) + - rc->err.data; + return NGX_ERROR; } From mdounin at mdounin.ru Mon Sep 8 20:27:58 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 08 Sep 2014 20:27:58 +0000 Subject: [nginx] Fixed ETag memory allocation error handling. Message-ID: details: http://hg.nginx.org/nginx/rev/51fe42cc7876 branches: changeset: 5825:51fe42cc7876 user: Maxim Dounin date: Mon Sep 08 21:36:03 2014 +0400 description: Fixed ETag memory allocation error handling. The etag->hash must be set to 0 to avoid an empty ETag header being returned with the 500 Internal Server Error page after the memory allocation failure. Reported by Markus Linnala. diffstat: src/http/ngx_http_core_module.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1837,6 +1837,7 @@ ngx_http_set_etag(ngx_http_request_t *r) etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3); if (etag->value.data == NULL) { + etag->hash = 0; return NGX_ERROR; } From mdounin at mdounin.ru Mon Sep 8 20:28:02 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 08 Sep 2014 20:28:02 +0000 Subject: [nginx] Added ngx_init_setproctitle() return code check. Message-ID: details: http://hg.nginx.org/nginx/rev/16013b71feed branches: changeset: 5826:16013b71feed user: Maxim Dounin date: Mon Sep 08 21:36:09 2014 +0400 description: Added ngx_init_setproctitle() return code check. The ngx_init_setproctitle() function, as used on systems without setproctitle(3), may fail due to memory allocation errors, and therefore its return code needs to be checked. Reported by Markus Linnala. diffstat: src/os/unix/ngx_posix_init.c | 4 +++- src/os/unix/ngx_setproctitle.h | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diffs (35 lines): diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c --- a/src/os/unix/ngx_posix_init.c +++ b/src/os/unix/ngx_posix_init.c @@ -40,7 +40,9 @@ ngx_os_init(ngx_log_t *log) } #endif - ngx_init_setproctitle(log); + if (ngx_init_setproctitle(log) != NGX_OK) { + return NGX_ERROR; + } ngx_pagesize = getpagesize(); ngx_cacheline_size = NGX_CPU_CACHE_LINE; diff --git a/src/os/unix/ngx_setproctitle.h b/src/os/unix/ngx_setproctitle.h --- a/src/os/unix/ngx_setproctitle.h +++ b/src/os/unix/ngx_setproctitle.h @@ -13,7 +13,7 @@ /* FreeBSD, NetBSD, OpenBSD */ -#define ngx_init_setproctitle(log) +#define ngx_init_setproctitle(log) NGX_OK #define ngx_setproctitle(title) setproctitle("%s", title) @@ -39,7 +39,7 @@ void ngx_setproctitle(char *title); #else -#define ngx_init_setproctitle(log) +#define ngx_init_setproctitle(log) NGX_OK #define ngx_setproctitle(title) #endif /* OSes */ From mdounin at mdounin.ru Mon Sep 8 20:32:20 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 9 Sep 2014 00:32:20 +0400 Subject: [PATCH 1 of 2] clear err when ngx_regex_compile has allocation failure In-Reply-To: <20140905182518.GK1634@mdounin.ru> References: <20140905182518.GK1634@mdounin.ru> Message-ID: <20140908203220.GI59236@mdounin.ru> Hello! On Fri, Sep 05, 2014 at 10:25:18PM +0400, Maxim Dounin wrote: > Hello! > > On Sun, Aug 17, 2014 at 11:00:29PM +0300, Markus Linnala wrote: > > > # HG changeset patch > > # User Markus Linnala > > # Date 1408303316 -10800 > > # Sun Aug 17 22:21:56 2014 +0300 > > # Node ID d350d288cffef0e6395ae1f412842c3b55bc8d42 > > # Parent 0719145489f842b14765506f8856798c2203e3cc > > clear err when ngx_regex_compile has allocation failure > > > > diff -r 0719145489f8 -r d350d288cffe src/core/ngx_regex.c > > --- a/src/core/ngx_regex.c Sun Aug 17 21:59:38 2014 +0300 > > +++ b/src/core/ngx_regex.c Sun Aug 17 22:21:56 2014 +0300 > > @@ -149,6 +149,7 @@ > > > > rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t)); > > if (rc->regex == NULL) { > > + rc->err.len = 0; > > return NGX_ERROR; > > } > > > > @@ -159,6 +160,7 @@ > > if (ngx_pcre_studies != NULL) { > > elt = ngx_list_push(ngx_pcre_studies); > > if (elt == NULL) { > > + rc->err.len = 0; > > return NGX_ERROR; > > } > > This doesn't looks good, as it will result in empty errors being > logged in such cases. > > Something like this should be more user-friendly (and it also > fixes another long-standing bug): > > # HG changeset patch > # User Maxim Dounin > # Date 1409938779 -14400 > # Fri Sep 05 21:39:39 2014 +0400 > # Node ID f43551f64d028de939332ab9b66c3620b4259e08 > # Parent 063f7e75f9efd56f3aaa3d9c24c98ed3f42348ea > Core: ngx_regex_compile() error handling fixes. > > Now we actually return NGX_ERROR on errors, and provide an error > string for memory allocation errors. > > Reported by Markus Linnala. Committed this and other patches with minor changes, thanks. [...] -- Maxim Dounin http://nginx.org/ From richard at fussenegger.info Mon Sep 8 21:48:28 2014 From: richard at fussenegger.info (Richard Fussenegger, BSc) Date: Mon, 08 Sep 2014 23:48:28 +0200 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds In-Reply-To: <20140908172213.GF59236@mdounin.ru> References: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> <20140905183854.GM1634@mdounin.ru> <540D8C6E.1090500@fussenegger.info> <20140908172213.GF59236@mdounin.ru> Message-ID: <540E242C.80907@fussenegger.info> On 9/8/2014 7:22 PM, Maxim Dounin wrote: > Hello! > > On Mon, Sep 08, 2014 at 01:01:02PM +0200, Richard Fussenegger, BSc wrote: > >> Wouldn't it be better to drop support for ancient OpenSSL versions? It would >> be a great step for performance and security. Are there any good reasons to >> support old OpenSSL versions? > Dropping support doesn't changes anything for ones who uses modern > versions of the OpenSSL library. And will upset ones who, for > some reason, have to use old versions. > > The only benefit of dropping support for older OpenSSL versions is > slightly lower code maintenance costs on nginx side. The nginx project could be a forerunner by removing support. Of course you would upset some admins but you know as well as I that many of those could easily upgrade but are unwilling to do so. If they can stick to outdated OpenSSL versions that have SERIOUS vulnerabilities regarding security and performance, why would they need an updated nginx? Honestly, I don't understand this kind of politics. It would be much better to implement a policy that says (e.g.) current nginx versions supports two versions back of OpenSSL from the time of release of both. That would be a clear rule that anyone can easily understand and it would ensure proper updates and fixes for security problems of the complete Internet infrastructure. I think that you underestimate the scope of engagement that nginx is playing now as second most used web server of the world. I think that the project should take that role much more serious. (Please don't answer with some like "but Apache httpd", the project shouldn't reiterate problems of other projects.) And of course we could take the reduced maintenance costs and benefit from it. Richard --- This email is free from viruses and malware because avast! Antivirus protection is active. http://www.avast.com From quanah at zimbra.com Mon Sep 8 22:28:01 2014 From: quanah at zimbra.com (Quanah Gibson-Mount) Date: Mon, 08 Sep 2014 15:28:01 -0700 Subject: SASL support for mail proxy in NGINX In-Reply-To: <20140908194933.GH59236@mdounin.ru> References: <639768787.1257597.1408744223634.JavaMail.zimbra@zimbra.com> <16F955A2D49E0C06AC57A36F@[192.168.1.2]> <20140908194933.GH59236@mdounin.ru> Message-ID: --On Tuesday, September 09, 2014 12:49 AM +0400 Maxim Dounin wrote: >> > We plan on adding SASL support to SMTP as well unless you guys have >> > plan to do that already ? >> >> Any nginx developers have any thoughts on this? > > When talking to mail backends, nginx doesn't use SASL for > authentication as it's believed to be superfluous to use it > instead of native protocol commands in the non-hostile backend > environment. I'm not sure what you mean by this, can you expand please? > There is SASL support in nginx mail module though, and it happily > authenticates users with PLAIN, LOGIN and CRAM-MD5 SASL mechanisms > (as long as http_auth script used is able to handle this). These are particularly limited SASL mechanisms. Ours adds support for linking to cyrus-sasl, for extended SASL mechanisms such as GSSAPI, SPNEGO, etc. If that's not of interest, that's fine, but it's generally much more useful security wise. --Quanah -- Quanah Gibson-Mount Server Architect Zimbra, Inc. -------------------- Zimbra :: the leader in open source messaging and collaboration From mdounin at mdounin.ru Mon Sep 8 23:33:25 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 08 Sep 2014 23:33:25 +0000 Subject: [nginx] Upstream: avoided directly terminating the connection. Message-ID: details: http://hg.nginx.org/nginx/rev/54e9b83d00f0 branches: changeset: 5827:54e9b83d00f0 user: FengGu date: Wed Aug 13 14:53:55 2014 +0800 description: Upstream: avoided directly terminating the connection. When memory allocation failed in ngx_http_upstream_cache(), the connection would be terminated directly in ngx_http_upstream_init_request(). Return a INTERNAL_SERVER_ERROR response instead. diffstat: src/http/ngx_http_upstream.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -519,6 +519,11 @@ ngx_http_upstream_init_request(ngx_http_ return; } + if (rc == NGX_ERROR) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + if (rc != NGX_DECLINED) { ngx_http_finalize_request(r, rc); return; From mdounin at mdounin.ru Mon Sep 8 23:34:29 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 9 Sep 2014 03:34:29 +0400 Subject: [PATCH]Upstream: avoided directly terminating the connection. In-Reply-To: <4621925e.91c.147ce2e14d8.Coremail.flygoast@126.com> References: <4621925e.91c.147ce2e14d8.Coremail.flygoast@126.com> Message-ID: <20140908233429.GJ59236@mdounin.ru> Hello! On Wed, Aug 13, 2014 at 03:03:52PM +0800, flygoast wrote: > # HG changeset patch > # User FengGu > # Date 1407912835 -28800 > # Wed Aug 13 14:53:55 2014 +0800 > # Node ID 9dd4e38fcce05bcbba4747873a579bc2c9392dd2 > # Parent 92490a725fef588939abfe0e1fe89cda0788d02d > Upstream: avoided directly terminating the connection. > > > When memory allocation failed in ngx_http_upstream_cache(), the connection > would be terminated directly in ngx_http_upstream_init_request(). > Return a INTERNAL_SERVER_ERROR response instead. > > > diff -r 92490a725fef -r 9dd4e38fcce0 src/http/ngx_http_upstream.c > --- a/src/http/ngx_http_upstream.c Sun Aug 10 17:44:46 2014 +0400 > +++ b/src/http/ngx_http_upstream.c Wed Aug 13 14:53:55 2014 +0800 > @@ -519,6 +519,11 @@ ngx_http_upstream_init_request(ngx_http_ > return; > } > > > + if (rc == NGX_ERROR) { > + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); > + return; > + } > + > if (rc != NGX_DECLINED) { > ngx_http_finalize_request(r, rc); > return; Committed, thanks. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Tue Sep 9 01:59:34 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 9 Sep 2014 05:59:34 +0400 Subject: SASL support for mail proxy in NGINX In-Reply-To: References: <639768787.1257597.1408744223634.JavaMail.zimbra@zimbra.com> <16F955A2D49E0C06AC57A36F@[192.168.1.2]> <20140908194933.GH59236@mdounin.ru> Message-ID: <20140909015934.GL59236@mdounin.ru> Hello! On Mon, Sep 08, 2014 at 03:28:01PM -0700, Quanah Gibson-Mount wrote: > --On Tuesday, September 09, 2014 12:49 AM +0400 Maxim Dounin > wrote: > > >>> We plan on adding SASL support to SMTP as well unless you guys have > >>> plan to do that already ? > >> > >>Any nginx developers have any thoughts on this? > > > >When talking to mail backends, nginx doesn't use SASL for > >authentication as it's believed to be superfluous to use it > >instead of native protocol commands in the non-hostile backend > >environment. > > I'm not sure what you mean by this, can you expand please? I mean: nginx uses "LOGIN" when talking to IMAP backends, "USER/PASS" when talking to POP3 backends, and I don't see reasons to use SASL mechanisms instead when talking to backends. > >There is SASL support in nginx mail module though, and it happily > >authenticates users with PLAIN, LOGIN and CRAM-MD5 SASL mechanisms > >(as long as http_auth script used is able to handle this). > > These are particularly limited SASL mechanisms. Ours adds support for > linking to cyrus-sasl, for extended SASL mechanisms such as GSSAPI, SPNEGO, > etc. If that's not of interest, that's fine, but it's generally much more > useful security wise. No, linking to cyrus-sasl isn't an option, thanks. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Tue Sep 9 02:47:23 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 9 Sep 2014 06:47:23 +0400 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds In-Reply-To: <540E242C.80907@fussenegger.info> References: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> <20140905183854.GM1634@mdounin.ru> <540D8C6E.1090500@fussenegger.info> <20140908172213.GF59236@mdounin.ru> <540E242C.80907@fussenegger.info> Message-ID: <20140909024723.GM59236@mdounin.ru> Hello! On Mon, Sep 08, 2014 at 11:48:28PM +0200, Richard Fussenegger, BSc wrote: > On 9/8/2014 7:22 PM, Maxim Dounin wrote: > >Hello! > > > >On Mon, Sep 08, 2014 at 01:01:02PM +0200, Richard Fussenegger, BSc wrote: > > > >>Wouldn't it be better to drop support for ancient OpenSSL versions? It would > >>be a great step for performance and security. Are there any good reasons to > >>support old OpenSSL versions? > >Dropping support doesn't changes anything for ones who uses modern > >versions of the OpenSSL library. And will upset ones who, for > >some reason, have to use old versions. > > > >The only benefit of dropping support for older OpenSSL versions is > >slightly lower code maintenance costs on nginx side. > The nginx project could be a forerunner by removing support. Of course you > would upset some admins but you know as well as I that many of those could > easily upgrade but are unwilling to do so. If they can stick to outdated > OpenSSL versions that have SERIOUS vulnerabilities regarding security and > performance, What make you think that there are any vulnerabilities? As far as I know, OpenSSL 0.9.7* (the oldest branch nginx currently supports compilation with) is still commercially supported as a part of at least one OS, and will be supported till 2017. Even if there are, SSL isn't the only reason to compile nginx with OpenSSL. Some just need MD5/SHA1 from OpenSSL for various uses within nginx itself, and some just use a single packet for everything - and any version of OpenSSL will do as long as it compiles, as SSL isn't used at all. I personally more or less regularly test nginx on a system with OpenSSL 0.9.7d - and I'm fine as long as it compiles, as it's a test virtual machine. > why would they need an updated nginx? Honestly, I don't And that's another part of the problem: if they won't be able to update nginx, they won't update it. And that's not we want to happen - instead, we want them to update nginx even if they stick to some old libraries for some reason. And make this as painless as possible. > understand this kind of politics. It would be much better to implement a > policy that says (e.g.) current nginx versions supports two versions back of > OpenSSL from the time of release of both. That would be a clear rule that > anyone can easily understand and it would ensure proper updates and fixes > for security problems of the complete Internet infrastructure. I think that As of now, minimum supported OpenSSL version is 0.9.7, and this is documented in http://nginx.org/en/CHANGES. That's certainly a clear rule that anyone can easily understand. We'll probably bump this to 0.9.8 once we'll get bored with 0.9.7 compatibility, but that's all we can do now without introducing a lot of trouble: various major OSes are shipped with 0.9.8*, and 0.9.8 branch is still supported by OpenSSL. > you underestimate the scope of engagement that nginx is playing now as > second most used web server of the world. I think that the project should > take that role much more serious. (Please don't answer with some like "but > Apache httpd", the project shouldn't reiterate problems of other projects.) I think you overestimate positive impact of not supporting old OpenSSL versions, and underestimate negative impact of this. -- Maxim Dounin http://nginx.org/ From alex at zeitgeist.se Tue Sep 9 08:11:27 2014 From: alex at zeitgeist.se (Alex) Date: Tue, 09 Sep 2014 10:11:27 +0200 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds In-Reply-To: <20140909024723.GM59236@mdounin.ru> References: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> <20140905183854.GM1634@mdounin.ru> <540D8C6E.1090500@fussenegger.info> <20140908172213.GF59236@mdounin.ru> <540E242C.80907@fussenegger.info> <20140909024723.GM59236@mdounin.ru> Message-ID: <432B125A-B5AB-44C7-8652-D54DB8030239@postfach.slogh.com> Hi, On 2014-09-09 04:47, Maxim Dounin wrote: > What make you think that there are any vulnerabilities? As far as > I know, OpenSSL 0.9.7* (the oldest branch nginx currently supports > compilation with) is still commercially supported as a part of at > least one OS, and will be supported till 2017. Indeed. For example, OpenSSL before 1.0.1 (including the 0.9.8 and 0.9.7 branches) were not vulnerable to Heartbleed. New versions bring new features which may also open room for new vulnerabilities. What's important is that long term distributions continue backport vulnerability fixes. > We'll probably bump this to 0.9.8 once we'll get bored with 0.9.7 > compatibility, but that's all we can do now without introducing a > lot of trouble: various major OSes are shipped with 0.9.8*, and > 0.9.8 branch is still supported by OpenSSL. That would make sense. 0.9.7 isn't officially supported anymore (i.e. it's completely up to long term distributions to backport fixes). 0.9.8 however still is, with the latest version being 0.9.8zb that was just released last month. From richard at fussenegger.info Tue Sep 9 15:56:37 2014 From: richard at fussenegger.info (Richard Fussenegger, BSc) Date: Tue, 09 Sep 2014 17:56:37 +0200 Subject: [PATCH] SSL: guard use of all SSL options for bug workarounds In-Reply-To: <20140909024723.GM59236@mdounin.ru> References: <9c59138cd7030a88a761.1409781203@piotrs-macbook-pro.local> <20140905183854.GM1634@mdounin.ru> <540D8C6E.1090500@fussenegger.info> <20140908172213.GF59236@mdounin.ru> <540E242C.80907@fussenegger.info> <20140909024723.GM59236@mdounin.ru> Message-ID: <540F2335.7090306@fussenegger.info> On 9/9/2014 4:47 AM, Maxim Dounin wrote: > What make you think that there are any vulnerabilities? As far as > I know, OpenSSL 0.9.7* (the oldest branch nginx currently supports > compilation with) is still commercially supported as a part of at > least one OS, and will be supported till 2017. > > Even if there are, SSL isn't the only reason to compile nginx with > OpenSSL. Some just need MD5/SHA1 from OpenSSL for various uses > within nginx itself, and some just use a single packet for > everything - and any version of OpenSSL will do as long as it > compiles, as SSL isn't used at all. I didn't think of situations in which no SSL/TLS is in use and of course the usage of old versions isn't an issue as long as they are secure (the performance argument is nullified because no SSL/TLS is in use). > And that's another part of the problem: if they won't be able to > update nginx, they won't update it. And that's not we want to > happen - instead, we want them to update nginx even if they stick > to some old libraries for some reason. And make this as painless > as possible. Of course this policy makes sense. But sometimes it would be a very good idea to stop supporting some technologies, e.g. SSLv2. Simply to help the web evolve and get rid of old insecure technologies. Nginx is now playing a leading role and can dictate or help in such matters. Even if that means that some pain in upgrades in introduced. > I think you overestimate positive impact of not supporting old OpenSSL > versions, and underestimate negative impact of this. Seems so, but if maintenance is getting more complicated with supporting multiple forks it might become necessary. Or maybe it might be necessary to reduce the amount of supported forks. Although I don't think that this is a good idea because the forks seem to be introducing a lot of interesting stuff in the future. I'm especially looking at BoringSSL and the reduction of memory consumption per connection that Google was talking about that they might bring to the library. Richard --- This email is free from viruses and malware because avast! Antivirus protection is active. http://www.avast.com From quanah at zimbra.com Tue Sep 9 16:53:42 2014 From: quanah at zimbra.com (Quanah Gibson-Mount) Date: Tue, 09 Sep 2014 09:53:42 -0700 Subject: SASL support for mail proxy in NGINX In-Reply-To: <20140909015934.GL59236@mdounin.ru> References: <639768787.1257597.1408744223634.JavaMail.zimbra@zimbra.com> <16F955A2D49E0C06AC57A36F@[192.168.1.2]> <20140908194933.GH59236@mdounin.ru> <20140909015934.GL59236@mdounin.ru> Message-ID: <9B0A8511BA407EA3AC6D66A6@[192.168.1.2]> --On Tuesday, September 09, 2014 6:59 AM +0400 Maxim Dounin wrote: > Hello! > > On Mon, Sep 08, 2014 at 03:28:01PM -0700, Quanah Gibson-Mount wrote: > >> --On Tuesday, September 09, 2014 12:49 AM +0400 Maxim Dounin >> wrote: >> >> >>> We plan on adding SASL support to SMTP as well unless you guys have >> >>> plan to do that already ? >> >> >> >> Any nginx developers have any thoughts on this? >> > >> > When talking to mail backends, nginx doesn't use SASL for >> > authentication as it's believed to be superfluous to use it >> > instead of native protocol commands in the non-hostile backend >> > environment. >> >> I'm not sure what you mean by this, can you expand please? > > I mean: nginx uses "LOGIN" when talking to IMAP backends, > "USER/PASS" when talking to POP3 backends, and I don't see reasons > to use SASL mechanisms instead when talking to backends. If this were 1993, I might understand this. However, using SASL as an authentication mechanism has been standarized for a few decades now, and is part of all the major MTAs and IMAP, POP, etc servers. It is also all quite standardized: etc. >> > There is SASL support in nginx mail module though, and it happily >> > authenticates users with PLAIN, LOGIN and CRAM-MD5 SASL mechanisms >> > (as long as http_auth script used is able to handle this). >> >> These are particularly limited SASL mechanisms. Ours adds support for >> linking to cyrus-sasl, for extended SASL mechanisms such as GSSAPI, >> SPNEGO, etc. If that's not of interest, that's fine, but it's generally >> much more useful security wise. > > No, linking to cyrus-sasl isn't an option, thanks. The linking is entirely optional, but allows those who are concerned with actual security to enable secure mechanisms for communicating via SMTP, POP, IMAP, etc. By ignoring modern SASL mechanisms (i.e., post 1993), you're eliminating wide swathes of the world from using nginx, particularly government, military, and educational institutions, which often have tight requirements for secure authentication mechansisms such as Kerberos5 (SASL/GSSAPI). I would hope that increasing the security of nginx was actually a priority to the developers. --Quanah -- Quanah Gibson-Mount Server Architect Zimbra, Inc. -------------------- Zimbra :: the leader in open source messaging and collaboration From kpariani at zimbra.com Wed Sep 10 21:29:53 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Wed, 10 Sep 2014 16:29:53 -0500 (CDT) Subject: [PATCH] SSL support for the mail proxy module In-Reply-To: <1206468761.898924.1410384559835.JavaMail.zimbra@zimbra.com> References: <1399448073.850051.1408489095173.JavaMail.zimbra@zimbra.com> <1971574953.1254572.1408742007421.JavaMail.zimbra@zimbra.com> <2B39312159AE5CF614E0F6B2@[192.168.1.2]> <20140908192402.GG59236@mdounin.ru> Message-ID: <1648872325.899027.1410384593493.JavaMail.zimbra@zimbra.com> Based on your comments, Should i add all the ssl related directives in the http proxy module to the mail proxy module as part of this ? Mainly these ones below proxy_ssl_ciphers proxy_ssl_crl proxy_ssl_name proxy_ssl_server_name proxy_ssl_session_reuse proxy_ssl_protocols proxy_ssl_trusted_certificate proxy_ssl_verify proxy_ssl_verify_depth Thanks -Kunal ----- Original Message ----- From: "Maxim Dounin" To: "nginx-devel" Sent: Monday, September 8, 2014 12:24:03 PM Subject: Re: [PATCH] SSL support for the mail proxy module Hello! On Mon, Sep 08, 2014 at 10:19:17AM -0700, Quanah Gibson-Mount wrote: > --On Friday, August 22, 2014 5:13 PM -0500 Kunal Pariani > wrote: > > > > > > >Any comments on this yet ? > > Any nginx developers who could comment on this? Some obvious problems with the patch: - it's corrupted by author's mail client, and hence can't be applied/tested; - there are various style violations, like C++-style comments; - it introduces yet another "SSL without certificate verification" case, which is believed to be bad (similar thing was recently resolved by introducing proxy_ssl_verify in the http proxy module); Some more comments below. [...] > >+ // don't support SSLv2 anymore > > > >+ if (ngx_ssl_create(pcf->ssl, NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL) > > > >+ != NGX_OK) { It is incorrect to support SSLv3 and TLSv1 only. By default NGX_SSL_TLSv1_1 and NGX_SSL_TLSv1_2 should be allowed, too. It's also may be a good idea to make this configurable like in http proxy module. Also, 2 style issues here: "//" comment and incorrectly placed "{". [...] > >+ if (ngx_ssl_create_connection(pcf->ssl, c, > > > >+ NGX_SSL_BUFFER|NGX_SSL_CLIENT) > > > >+ != NGX_OK) > > > >+ { The NGX_SSL_BUFFER is incorrect here. It won't currently make any difference as the code only uses c->recv() / c->send(), but nevertheless mail protocols doesn't assume buffering, and the mail module doesn't use NGX_SSL_BUFFER in ngx_ssl_create_connection() calls intentionally. -- Maxim Dounin http://nginx.org/ _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From mdounin at mdounin.ru Thu Sep 11 15:09:19 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Sep 2014 19:09:19 +0400 Subject: [PATCH] SSL support for the mail proxy module In-Reply-To: <1648872325.899027.1410384593493.JavaMail.zimbra@zimbra.com> References: <1399448073.850051.1408489095173.JavaMail.zimbra@zimbra.com> <1971574953.1254572.1408742007421.JavaMail.zimbra@zimbra.com> <2B39312159AE5CF614E0F6B2@[192.168.1.2]> <20140908192402.GG59236@mdounin.ru> <1648872325.899027.1410384593493.JavaMail.zimbra@zimbra.com> Message-ID: <20140911150918.GB59236@mdounin.ru> Hello! On Wed, Sep 10, 2014 at 04:29:53PM -0500, Kunal Pariani wrote: > Based on your comments, Should i add all the ssl related > directives in the http proxy module to the mail proxy module as > part of this ? Mainly these ones below > > proxy_ssl_ciphers > proxy_ssl_crl > proxy_ssl_name > proxy_ssl_server_name > proxy_ssl_session_reuse > proxy_ssl_protocols > proxy_ssl_trusted_certificate > proxy_ssl_verify > proxy_ssl_verify_depth There is no need to to add all of them, but certificate verification seems to be important part of the problem. Note well that it won't be trivial to port name-related things as currently nginx mail module doesn't know backend name at all. Instead, it obtains a backend ip address from the auth_http service. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Sep 11 16:37:24 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Sep 2014 16:37:24 +0000 Subject: [nginx] Style. Message-ID: details: http://hg.nginx.org/nginx/rev/733952da0a8a branches: changeset: 5828:733952da0a8a user: Maxim Dounin date: Thu Sep 11 20:08:45 2014 +0400 description: Style. diffstat: src/http/modules/ngx_http_scgi_module.c | 3 ++- src/http/modules/ngx_http_uwsgi_module.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diffs (26 lines): diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -1248,7 +1248,8 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t } if (conf->upstream.max_temp_file_size != 0 - && conf->upstream.max_temp_file_size < size) { + && conf->upstream.max_temp_file_size < size) + { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_max_temp_file_size\" must be equal to zero to disable " "temporary files usage or must be equal to or greater than " diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -1435,7 +1435,8 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t } if (conf->upstream.max_temp_file_size != 0 - && conf->upstream.max_temp_file_size < size) { + && conf->upstream.max_temp_file_size < size) + { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"uwsgi_max_temp_file_size\" must be equal to zero to disable " "temporary files usage or must be equal to or greater than " From mdounin at mdounin.ru Thu Sep 11 16:37:27 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Sep 2014 16:37:27 +0000 Subject: [nginx] Added warning about unset cache keys. Message-ID: details: http://hg.nginx.org/nginx/rev/906530c9ffd2 branches: changeset: 5829:906530c9ffd2 user: Maxim Dounin date: Thu Sep 11 20:08:52 2014 +0400 description: Added warning about unset cache keys. In fastcgi, scgi and uwsgi modules there are no default cache keys, and using a cache without a cache key set is likely meaningless. diffstat: src/http/modules/ngx_http_fastcgi_module.c | 5 +++++ src/http/modules/ngx_http_scgi_module.c | 5 +++++ src/http/modules/ngx_http_uwsgi_module.c | 5 +++++ 3 files changed, 15 insertions(+), 0 deletions(-) diffs (45 lines): diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -2582,6 +2582,11 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf conf->cache_key = prev->cache_key; } + if (conf->upstream.cache && conf->cache_key.value.data == NULL) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "no \"fastcgi_cache_key\" for \"fastcgi_cache\""); + } + ngx_conf_merge_value(conf->upstream.cache_lock, prev->upstream.cache_lock, 0); diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -1337,6 +1337,11 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t conf->cache_key = prev->cache_key; } + if (conf->upstream.cache && conf->cache_key.value.data == NULL) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "no \"scgi_cache_key\" for \"scgi_cache\""); + } + ngx_conf_merge_value(conf->upstream.cache_lock, prev->upstream.cache_lock, 0); diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -1524,6 +1524,11 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t conf->cache_key = prev->cache_key; } + if (conf->upstream.cache && conf->cache_key.value.data == NULL) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "no \"uwsgi_cache_key\" for \"uwsgi_cache\""); + } + ngx_conf_merge_value(conf->upstream.cache_lock, prev->upstream.cache_lock, 0); From mdounin at mdounin.ru Thu Sep 11 16:37:30 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Sep 2014 16:37:30 +0000 Subject: [nginx] Upstream keepalive: removed "single" parameter remnants. Message-ID: details: http://hg.nginx.org/nginx/rev/3e5b630e0ec9 branches: changeset: 5830:3e5b630e0ec9 user: Maxim Dounin date: Thu Sep 11 20:09:04 2014 +0400 description: Upstream keepalive: removed "single" parameter remnants. The "single" parameter is deprecated and ignored since 5b5c07dee156 (1.3.2). diffstat: src/http/modules/ngx_http_upstream_keepalive_module.c | 21 +------------------ 1 files changed, 1 insertions(+), 20 deletions(-) diffs (44 lines): diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c --- a/src/http/modules/ngx_http_upstream_keepalive_module.c +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c @@ -79,7 +79,7 @@ static char *ngx_http_upstream_keepalive static ngx_command_t ngx_http_upstream_keepalive_commands[] = { { ngx_string("keepalive"), - NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12, + NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, ngx_http_upstream_keepalive, NGX_HTTP_SRV_CONF_OFFSET, 0, @@ -485,7 +485,6 @@ ngx_http_upstream_keepalive(ngx_conf_t * ngx_int_t n; ngx_str_t *value; - ngx_uint_t i; uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); @@ -514,23 +513,5 @@ ngx_http_upstream_keepalive(ngx_conf_t * kcf->max_cached = n; - for (i = 2; i < cf->args->nelts; i++) { - - if (ngx_strcmp(value[i].data, "single") == 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "the \"single\" parameter is deprecated"); - continue; - } - - goto invalid; - } - return NGX_CONF_OK; - -invalid: - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid parameter \"%V\"", &value[i]); - - return NGX_CONF_ERROR; } From arut at nginx.com Fri Sep 12 14:53:11 2014 From: arut at nginx.com (Roman Arutyunyan) Date: Fri, 12 Sep 2014 14:53:11 +0000 Subject: [nginx] Upstream: included backup peers into peer.tries. Message-ID: details: http://hg.nginx.org/nginx/rev/575175ebf4b4 branches: changeset: 5831:575175ebf4b4 user: Roman Arutyunyan date: Fri Sep 12 18:50:46 2014 +0400 description: Upstream: included backup peers into peer.tries. Since peer.tries is never reset it can now be limited if required. diffstat: src/http/modules/ngx_http_upstream_least_conn_module.c | 5 ----- src/http/ngx_http_upstream_round_robin.c | 13 ++++++------- 2 files changed, 6 insertions(+), 12 deletions(-) diffs (73 lines): diff -r 3e5b630e0ec9 -r 575175ebf4b4 src/http/modules/ngx_http_upstream_least_conn_module.c --- a/src/http/modules/ngx_http_upstream_least_conn_module.c Thu Sep 11 20:09:04 2014 +0400 +++ b/src/http/modules/ngx_http_upstream_least_conn_module.c Fri Sep 12 18:50:46 2014 +0400 @@ -299,10 +299,6 @@ ngx_http_upstream_get_least_conn_peer(ng lcp->rrp.tried[n] |= m; lcp->conns[p]++; - if (pc->tries == 1 && peers->next) { - pc->tries += peers->next->number; - } - return NGX_OK; failed: @@ -314,7 +310,6 @@ failed: lcp->conns += peers->number; lcp->rrp.peers = peers->next; - pc->tries = lcp->rrp.peers->number; n = (lcp->rrp.peers->number + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); diff -r 3e5b630e0ec9 -r 575175ebf4b4 src/http/ngx_http_upstream_round_robin.c --- a/src/http/ngx_http_upstream_round_robin.c Thu Sep 11 20:09:04 2014 +0400 +++ b/src/http/ngx_http_upstream_round_robin.c Fri Sep 12 18:50:46 2014 +0400 @@ -10,6 +10,10 @@ #include +#define ngx_http_upstream_tries(p) ((p)->number \ + + ((p)->next ? (p)->next->number : 0)) + + static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer( ngx_http_upstream_rr_peer_data_t *rrp); @@ -255,7 +259,7 @@ ngx_http_upstream_init_round_robin_peer( r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer; r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer; - r->upstream->peer.tries = rrp->peers->number; + r->upstream->peer.tries = ngx_http_upstream_tries(rrp->peers); #if (NGX_HTTP_SSL) r->upstream->peer.set_session = ngx_http_upstream_set_round_robin_peer_session; @@ -374,7 +378,7 @@ ngx_http_upstream_create_round_robin_pee r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer; r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer; - r->upstream->peer.tries = rrp->peers->number; + r->upstream->peer.tries = ngx_http_upstream_tries(rrp->peers); #if (NGX_HTTP_SSL) r->upstream->peer.set_session = ngx_http_upstream_empty_set_session; r->upstream->peer.save_session = ngx_http_upstream_empty_save_session; @@ -432,10 +436,6 @@ ngx_http_upstream_get_round_robin_peer(n /* ngx_unlock_mutex(peers->mutex); */ - if (pc->tries == 1 && peers->next) { - pc->tries += peers->next->number; - } - return NGX_OK; failed: @@ -447,7 +447,6 @@ failed: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers"); rrp->peers = peers->next; - pc->tries = rrp->peers->number; n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); From arut at nginx.com Fri Sep 12 14:53:15 2014 From: arut at nginx.com (Roman Arutyunyan) Date: Fri, 12 Sep 2014 14:53:15 +0000 Subject: [nginx] Upstream: limited next_upstream time and tries (ticket #... Message-ID: details: http://hg.nginx.org/nginx/rev/d09b689911ac branches: changeset: 5832:d09b689911ac user: Roman Arutyunyan date: Fri Sep 12 18:50:47 2014 +0400 description: Upstream: limited next_upstream time and tries (ticket #544). The new directives {proxy,fastcgi,scgi,uwsgi,memcached}_next_upstream_tries and {proxy,fastcgi,scgi,uwsgi,memcached}_next_upstream_timeout limit the number of upstreams tried and the maximum time spent for these tries when searching for a valid upstream. diffstat: src/event/ngx_event_connect.h | 1 + src/http/modules/ngx_http_fastcgi_module.c | 22 ++++++++++++++++++++++ src/http/modules/ngx_http_memcached_module.c | 22 ++++++++++++++++++++++ src/http/modules/ngx_http_proxy_module.c | 22 ++++++++++++++++++++++ src/http/modules/ngx_http_scgi_module.c | 22 ++++++++++++++++++++++ src/http/modules/ngx_http_uwsgi_module.c | 22 ++++++++++++++++++++++ src/http/ngx_http_upstream.c | 18 +++++++++++++++--- src/http/ngx_http_upstream.h | 2 ++ 8 files changed, 128 insertions(+), 3 deletions(-) diffs (truncated from 368 to 300 lines): diff -r 575175ebf4b4 -r d09b689911ac src/event/ngx_event_connect.h --- a/src/event/ngx_event_connect.h Fri Sep 12 18:50:46 2014 +0400 +++ b/src/event/ngx_event_connect.h Fri Sep 12 18:50:47 2014 +0400 @@ -42,6 +42,7 @@ struct ngx_peer_connection_s { ngx_str_t *name; ngx_uint_t tries; + ngx_msec_t start_time; ngx_event_get_peer_pt get; ngx_event_free_peer_pt free; diff -r 575175ebf4b4 -r d09b689911ac src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c Fri Sep 12 18:50:46 2014 +0400 +++ b/src/http/modules/ngx_http_fastcgi_module.c Fri Sep 12 18:50:47 2014 +0400 @@ -442,6 +442,20 @@ static ngx_command_t ngx_http_fastcgi_c offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream), &ngx_http_fastcgi_next_upstream_masks }, + { ngx_string("fastcgi_next_upstream_tries"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream_tries), + NULL }, + + { ngx_string("fastcgi_next_upstream_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream_timeout), + NULL }, + { ngx_string("fastcgi_param"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23, ngx_http_upstream_param_set_slot, @@ -2314,6 +2328,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_con conf->upstream.store = NGX_CONF_UNSET; conf->upstream.store_access = NGX_CONF_UNSET_UINT; + conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; conf->upstream.buffering = NGX_CONF_UNSET; conf->upstream.ignore_client_abort = NGX_CONF_UNSET; @@ -2322,6 +2337,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_con conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; @@ -2387,6 +2403,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf ngx_conf_merge_uint_value(conf->upstream.store_access, prev->upstream.store_access, 0600); + ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, + prev->upstream.next_upstream_tries, 0); + ngx_conf_merge_value(conf->upstream.buffering, prev->upstream.buffering, 1); @@ -2405,6 +2424,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf ngx_conf_merge_msec_value(conf->upstream.read_timeout, prev->upstream.read_timeout, 60000); + ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout, + prev->upstream.next_upstream_timeout, 0); + ngx_conf_merge_size_value(conf->upstream.send_lowat, prev->upstream.send_lowat, 0); diff -r 575175ebf4b4 -r d09b689911ac src/http/modules/ngx_http_memcached_module.c --- a/src/http/modules/ngx_http_memcached_module.c Fri Sep 12 18:50:46 2014 +0400 +++ b/src/http/modules/ngx_http_memcached_module.c Fri Sep 12 18:50:47 2014 +0400 @@ -102,6 +102,20 @@ static ngx_command_t ngx_http_memcached offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream), &ngx_http_memcached_next_upstream_masks }, + { ngx_string("memcached_next_upstream_tries"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream_tries), + NULL }, + + { ngx_string("memcached_next_upstream_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream_timeout), + NULL }, + { ngx_string("memcached_gzip_flag"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -583,9 +597,11 @@ ngx_http_memcached_create_loc_conf(ngx_c */ conf->upstream.local = NGX_CONF_UNSET_PTR; + conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; @@ -619,6 +635,9 @@ ngx_http_memcached_merge_loc_conf(ngx_co ngx_conf_merge_ptr_value(conf->upstream.local, prev->upstream.local, NULL); + ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, + prev->upstream.next_upstream_tries, 0); + ngx_conf_merge_msec_value(conf->upstream.connect_timeout, prev->upstream.connect_timeout, 60000); @@ -628,6 +647,9 @@ ngx_http_memcached_merge_loc_conf(ngx_co ngx_conf_merge_msec_value(conf->upstream.read_timeout, prev->upstream.read_timeout, 60000); + ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout, + prev->upstream.next_upstream_timeout, 0); + ngx_conf_merge_size_value(conf->upstream.buffer_size, prev->upstream.buffer_size, (size_t) ngx_pagesize); diff -r 575175ebf4b4 -r d09b689911ac src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Fri Sep 12 18:50:46 2014 +0400 +++ b/src/http/modules/ngx_http_proxy_module.c Fri Sep 12 18:50:47 2014 +0400 @@ -505,6 +505,20 @@ static ngx_command_t ngx_http_proxy_com offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream), &ngx_http_proxy_next_upstream_masks }, + { ngx_string("proxy_next_upstream_tries"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_tries), + NULL }, + + { ngx_string("proxy_next_upstream_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_timeout), + NULL }, + { ngx_string("proxy_pass_header"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_array_slot, @@ -2455,6 +2469,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->upstream.store = NGX_CONF_UNSET; conf->upstream.store_access = NGX_CONF_UNSET_UINT; + conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; conf->upstream.buffering = NGX_CONF_UNSET; conf->upstream.ignore_client_abort = NGX_CONF_UNSET; @@ -2463,6 +2478,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; @@ -2543,6 +2559,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_conf_merge_uint_value(conf->upstream.store_access, prev->upstream.store_access, 0600); + ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, + prev->upstream.next_upstream_tries, 0); + ngx_conf_merge_value(conf->upstream.buffering, prev->upstream.buffering, 1); @@ -2561,6 +2580,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_conf_merge_msec_value(conf->upstream.read_timeout, prev->upstream.read_timeout, 60000); + ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout, + prev->upstream.next_upstream_timeout, 0); + ngx_conf_merge_size_value(conf->upstream.send_lowat, prev->upstream.send_lowat, 0); diff -r 575175ebf4b4 -r d09b689911ac src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c Fri Sep 12 18:50:46 2014 +0400 +++ b/src/http/modules/ngx_http_scgi_module.c Fri Sep 12 18:50:47 2014 +0400 @@ -299,6 +299,20 @@ static ngx_command_t ngx_http_scgi_comma offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream), &ngx_http_scgi_next_upstream_masks }, + { ngx_string("scgi_next_upstream_tries"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream_tries), + NULL }, + + { ngx_string("scgi_next_upstream_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream_timeout), + NULL }, + { ngx_string("scgi_param"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23, ngx_http_upstream_param_set_slot, @@ -1074,6 +1088,7 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t conf->upstream.store = NGX_CONF_UNSET; conf->upstream.store_access = NGX_CONF_UNSET_UINT; + conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; conf->upstream.buffering = NGX_CONF_UNSET; conf->upstream.ignore_client_abort = NGX_CONF_UNSET; @@ -1082,6 +1097,7 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; @@ -1142,6 +1158,9 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t ngx_conf_merge_uint_value(conf->upstream.store_access, prev->upstream.store_access, 0600); + ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, + prev->upstream.next_upstream_tries, 0); + ngx_conf_merge_value(conf->upstream.buffering, prev->upstream.buffering, 1); @@ -1160,6 +1179,9 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t ngx_conf_merge_msec_value(conf->upstream.read_timeout, prev->upstream.read_timeout, 60000); + ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout, + prev->upstream.next_upstream_timeout, 0); + ngx_conf_merge_size_value(conf->upstream.send_lowat, prev->upstream.send_lowat, 0); diff -r 575175ebf4b4 -r d09b689911ac src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c Fri Sep 12 18:50:46 2014 +0400 +++ b/src/http/modules/ngx_http_uwsgi_module.c Fri Sep 12 18:50:47 2014 +0400 @@ -354,6 +354,20 @@ static ngx_command_t ngx_http_uwsgi_comm offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream), &ngx_http_uwsgi_next_upstream_masks }, + { ngx_string("uwsgi_next_upstream_tries"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_tries), + NULL }, + + { ngx_string("uwsgi_next_upstream_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_timeout), + NULL }, + { ngx_string("uwsgi_param"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23, ngx_http_upstream_param_set_slot, @@ -1254,6 +1268,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_ conf->upstream.store = NGX_CONF_UNSET; conf->upstream.store_access = NGX_CONF_UNSET_UINT; + conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; conf->upstream.buffering = NGX_CONF_UNSET; conf->upstream.ignore_client_abort = NGX_CONF_UNSET; @@ -1262,6 +1277,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_ conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; @@ -1329,6 +1345,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t ngx_conf_merge_uint_value(conf->upstream.store_access, prev->upstream.store_access, 0600); + ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, + prev->upstream.next_upstream_tries, 0); + ngx_conf_merge_value(conf->upstream.buffering, prev->upstream.buffering, 1); @@ -1347,6 +1366,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t ngx_conf_merge_msec_value(conf->upstream.read_timeout, prev->upstream.read_timeout, 60000); From vbart at nginx.com Sat Sep 13 17:52:14 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Sat, 13 Sep 2014 17:52:14 +0000 Subject: [nginx] Access log: fixed the "if=" parameter with buffering (ti... Message-ID: details: http://hg.nginx.org/nginx/rev/e3016ee8dba3 branches: changeset: 5833:e3016ee8dba3 user: Valentin Bartenev date: Sat Sep 13 21:47:13 2014 +0400 description: Access log: fixed the "if=" parameter with buffering (ticket #625). It might not work if there were more than one "access_log" directives pointed to the same file and duplicate buffer parameters. diffstat: src/http/modules/ngx_http_log_module.c | 41 ++++++++++++++++----------------- 1 files changed, 20 insertions(+), 21 deletions(-) diffs (72 lines): diff -r d09b689911ac -r e3016ee8dba3 src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c Fri Sep 12 18:50:47 2014 +0400 +++ b/src/http/modules/ngx_http_log_module.c Sat Sep 13 21:47:13 2014 +0400 @@ -1136,7 +1136,7 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx ngx_int_t gzip; ngx_uint_t i, n; ngx_msec_t flush; - ngx_str_t *value, name, s, filter; + ngx_str_t *value, name, s; ngx_http_log_t *log; ngx_syslog_peer_t *peer; ngx_http_log_buf_t *buffer; @@ -1257,7 +1257,6 @@ process_formats: size = 0; flush = 0; gzip = 0; - filter.len = 0; for (i = 3; i < cf->args->nelts; i++) { @@ -1325,8 +1324,25 @@ process_formats: } if (ngx_strncmp(value[i].data, "if=", 3) == 0) { - filter.len = value[i].len - 3; - filter.data = value[i].data + 3; + s.len = value[i].len - 3; + s.data = value[i].data + 3; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &s; + ccv.complex_value = ngx_palloc(cf->pool, + sizeof(ngx_http_complex_value_t)); + if (ccv.complex_value == NULL) { + return NGX_CONF_ERROR; + } + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + log->filter = ccv.complex_value; + continue; } @@ -1405,23 +1421,6 @@ process_formats: log->file->data = buffer; } - if (filter.len) { - log->filter = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); - if (log->filter == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); - - ccv.cf = cf; - ccv.value = &filter; - ccv.complex_value = log->filter; - - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { - return NGX_CONF_ERROR; - } - } - return NGX_CONF_OK; } From kpariani at zimbra.com Sat Sep 13 23:14:31 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Sat, 13 Sep 2014 18:14:31 -0500 Subject: [PATCH] SSL support for the mail proxy module Message-ID: <5c2524403ab7c870b1fa.1410650071@zdev-vm048.eng.zimbra.com> # HG changeset patch # User Kunal Pariani # Date 1410649455 18000 # Sat Sep 13 18:04:15 2014 -0500 # Node ID 5c2524403ab7c870b1fa7294f935d3292f25fd1d # Parent e3016ee8dba396614f28a3644996b8cc6de8f9e3 SSL support for the mail proxy module diff -r e3016ee8dba3 -r 5c2524403ab7 src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c Sat Sep 13 21:47:13 2014 +0400 +++ b/src/mail/ngx_mail_proxy_module.c Sat Sep 13 18:04:15 2014 -0500 @@ -18,6 +18,15 @@ ngx_flag_t xclient; size_t buffer_size; ngx_msec_t timeout; +#if (NGX_MAIL_SSL) + ngx_flag_t proxy_ssl; + ngx_ssl_t *ssl; + ngx_uint_t ssl_protocols; + ngx_str_t ssl_ciphers; + ngx_flag_t ssl_verify; + ngx_uint_t ssl_verify_depth; + ngx_str_t ssl_trusted_certificate; +#endif } ngx_mail_proxy_conf_t; @@ -35,7 +44,22 @@ static void *ngx_mail_proxy_create_conf(ngx_conf_t *cf); static char *ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child); +#if (NGX_MAIL_SSL) +static char *ngx_mail_proxy_set_ssl(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static void ngx_mail_proxy_ssl_init_connection(ngx_mail_session_t *s, + ngx_connection_t *c); +static void ngx_mail_proxy_ssl_handshake(ngx_connection_t *c); +static ngx_conf_bitmask_t ngx_mail_proxy_ssl_protocols[] = { + { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, + { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, + { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, + { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, + { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_null_string, 0 } +}; +#endif static ngx_command_t ngx_mail_proxy_commands[] = { @@ -74,6 +98,52 @@ offsetof(ngx_mail_proxy_conf_t, xclient), NULL }, +#if (NGX_MAIL_SSL) + + { ngx_string("proxy_ssl"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_mail_proxy_set_ssl, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, proxy_ssl), + NULL }, + + { ngx_string("proxy_ssl_protocols"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_protocols), + &ngx_mail_proxy_ssl_protocols }, + + { ngx_string("proxy_ssl_ciphers"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_ciphers), + NULL }, + + { ngx_string("proxy_ssl_verify"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_verify), + NULL }, + + { ngx_string("proxy_ssl_verify_depth"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_verify_depth), + NULL }, + + { ngx_string("proxy_ssl_trusted_certificate"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_trusted_certificate), + NULL }, + +#endif + ngx_null_command }; @@ -174,6 +244,15 @@ s->out.len = 0; +#if (NGX_MAIL_SSL) + + if (pcf->proxy_ssl && p->upstream.connection->ssl == NULL) { + ngx_mail_proxy_ssl_init_connection(s, p->upstream.connection); + return; + } + +#endif + switch (s->protocol) { case NGX_MAIL_POP3_PROTOCOL: @@ -1091,6 +1170,13 @@ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "close mail proxy connection: %d", s->proxy->upstream.connection->fd); +#if (NGX_MAIL_SSL) + + if (s->proxy->upstream.connection->ssl) { + s->proxy->upstream.connection->ssl->no_wait_shutdown = 1; + ngx_ssl_shutdown(s->proxy->upstream.connection); + } +#endif ngx_close_connection(s->proxy->upstream.connection); } @@ -1109,12 +1195,26 @@ return NULL; } + /* + * set by ngx_pcalloc(): + * + * pcf->ssl_protocols = 0; + * pcf->ssl_ciphers = { 0, NULL }; + * pcf->ssl_trusted_certificate = { 0, NULL }; + */ pcf->enable = NGX_CONF_UNSET; pcf->pass_error_message = NGX_CONF_UNSET; pcf->xclient = NGX_CONF_UNSET; pcf->buffer_size = NGX_CONF_UNSET_SIZE; pcf->timeout = NGX_CONF_UNSET_MSEC; +#if (NGX_HTTP_SSL) + pcf->proxy_ssl = NGX_CONF_UNSET; + pcf->ssl = NGX_CONF_UNSET_PTR; + pcf->ssl_verify = NGX_CONF_UNSET; + pcf->ssl_verify_depth = NGX_CONF_UNSET_UINT; +#endif + return pcf; } @@ -1132,5 +1232,161 @@ (size_t) ngx_pagesize); ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000); +#if (NGX_HTTP_SSL) + + ngx_conf_merge_value(conf->proxy_ssl, prev->proxy_ssl, 0); + ngx_conf_merge_ptr_value(conf->ssl, prev->ssl, NULL); + + ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols, + (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3 + |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1 + |NGX_SSL_TLSv1_2)); + + ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, + "DEFAULT"); + + ngx_conf_merge_value(conf->ssl_verify, + prev->ssl_verify, 0); + ngx_conf_merge_uint_value(conf->ssl_verify_depth, + prev->ssl_verify_depth, 1); + ngx_conf_merge_str_value(conf->ssl_trusted_certificate, + prev->ssl_trusted_certificate, ""); + +#endif return NGX_CONF_OK; } + +#if (NGX_MAIL_SSL) + +static char* +ngx_mail_proxy_set_ssl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + + ngx_pool_cleanup_t *cln; + char *rc; + ngx_mail_proxy_conf_t *pcf; + + rc = ngx_conf_set_flag_slot(cf, cmd, conf); + if (rc != NGX_CONF_OK) { + return rc; + } + + pcf = (ngx_mail_proxy_conf_t *)conf; + + if (!pcf->proxy_ssl) { + return NGX_CONF_OK; + } + + pcf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); + + if (pcf->ssl == NULL) { + return NGX_CONF_ERROR; + } + + pcf->ssl->log = cf->log; + + if (ngx_ssl_create(pcf->ssl, pcf->ssl_protocols, NULL) + != NGX_OK) { + return NGX_CONF_ERROR; + } + + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NGX_CONF_ERROR; + } + + cln->handler = ngx_ssl_cleanup_ctx; + cln->data = pcf->ssl; + + if (SSL_CTX_set_cipher_list(pcf->ssl->ctx, + (const char *) pcf->ssl_ciphers.data) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, + "SSL_CTX_set_cipher_list(\"%V\") failed", + &pcf->ssl_ciphers); + return NGX_CONF_ERROR; + } + + if (pcf->ssl_verify) { + if (pcf->ssl_trusted_certificate.len == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no proxy_ssl_trusted_certificate for proxy_ssl_verify"); + return NGX_CONF_ERROR; + } + + if (ngx_ssl_trusted_certificate(cf, pcf->ssl, + &pcf->ssl_trusted_certificate, + pcf->ssl_verify_depth) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; +} + +static void +ngx_mail_proxy_ssl_init_connection(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_int_t rc; + ngx_mail_proxy_conf_t *pcf; + + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + + if (ngx_ssl_create_connection(pcf->ssl, c, NGX_SSL_CLIENT) + != NGX_OK) + { + ngx_mail_proxy_internal_server_error(s); + return; + } + + s->connection->log->action = "SSL handshaking to upstream"; + + rc = ngx_ssl_handshake(c); + + if (rc == NGX_AGAIN) { + c->ssl->handler = ngx_mail_proxy_ssl_handshake; + return; + } + + ngx_mail_proxy_ssl_handshake(c); +} + + +static void +ngx_mail_proxy_ssl_handshake(ngx_connection_t *c) +{ + ngx_mail_session_t *s; + s = c->data; + + if (c->ssl->handshaked) { + + c->write->handler = ngx_mail_proxy_dummy_handler; + switch (s->protocol) { + + case NGX_MAIL_POP3_PROTOCOL: + c->read->handler = ngx_mail_proxy_pop3_handler; + s->mail_state = ngx_pop3_start; + break; + + case NGX_MAIL_IMAP_PROTOCOL: + c->read->handler = ngx_mail_proxy_imap_handler; + s->mail_state = ngx_imap_start; + break; + + default: /* NGX_MAIL_SMTP_PROTOCOL */ + c->read->handler = ngx_mail_proxy_smtp_handler; + s->mail_state = ngx_smtp_start; + break; + } + + /* server might have send the initial welcome msg */ + c->read->handler(c->read); + } else { + /* when handshake fails, we should close the session */ + ngx_mail_proxy_upstream_error(s); + } +} + +#endif From nginx at philliptaylor.net Mon Sep 15 09:47:44 2014 From: nginx at philliptaylor.net (Phillip Taylor (nginx)) Date: Mon, 15 Sep 2014 10:47:44 +0100 Subject: Guard websites with a secret handshake [ngx_http_knock_module] In-Reply-To: References: <2ec7814a33f25172053d128a2a1e5223@master.philliptaylor.net> Message-ID: Hi everyone, Firstly I want to thank SplitIce for their feedback on my work. I've taken it all on board. Last night, I updated the git repo for this module to use a red-black tree instead of a statically sized array. I still need to: a) implement the shared memory feature so that workers > 1 will work. b) fix the log statements which don't appear to log anywhere. Can someone guide me on how to allocate memory that is shared between the workers please and lasts for the lifetime of the web server please? Perhaps point me to some examples? For non connection-oriented requests, I need my memory to last longer than the connection. Would I choose an ngx_pool that had a lifetime of forever, or how would I achieve this please? https://github.com/PhillipTaylor/ngx_http_knock_module/commits/master Any other code review feedback is still welcome at this point. Hopefully I can get everything fixed in the next month. Thanks Phill On 2014-08-19 03:54, SplitIce wrote: > Is it just me or would access_records be per worker and hence this > module > not work with workers > 1 ? > > Additionally > for (i = 0; i < NGX_HTTP_KNOCK__IP_DB_SIZE && i < > ngx_http_knock_next_free_slot; i++) { > if (access_records[i].ip_addr == ip_addr) > > Perhaps using the nginx Red-Black tree here would lead to better > performance (in place of O(n)) and remove the limitation on number of > IPs. > > > On Tue, Aug 19, 2014 at 9:50 AM, Phillip Taylor (nginx) < > nginx at philliptaylor.net> wrote: > >> Hello everyone, >> >> I've written a module for nginx that takes the concept of "Port >> Knocking" >> and applies it to websites. When you visit an configured nginx >> website, it >> returns a 404 "page not found" error. However if you go to secret >> urls, >> even though they all, on the service appear to return 404, you are >> secretly >> handshaking with nginx. After you've hit the magic combination you ip >> is >> logged server side, and you're allowed to the visit the site (that is, >> it >> returns content instead of 404). >> >> The benefits include: >> * private websites >> * protect login pages against bots and scripts >> * protect against zero day exploits >> * protect against known exploits if you're slow to defend the site. >> >> The code, documentation and even a link to demonstration youtube video >> is >> available here: >> >> https://github.com/PhillipTaylor/ngx_http_knock_module >> >> I contact this mailing list: >> >> * to raise awareness that I have developed it. >> * for possibly inclusion on the 3rd Party Modules page for nginx ( >> http://wiki.nginx.org/3rdPartyModules) >> * to ask if you would be so kind to provide some code review feedback >> and >> advice regarding its quality. >> * and any other thoughts. >> >> Thank you >> >> Phillip Taylor >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From mdounin at mdounin.ru Mon Sep 15 14:39:29 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 15 Sep 2014 14:39:29 +0000 Subject: [nginx] SSL: session id context now includes certificate hash. Message-ID: details: http://hg.nginx.org/nginx/rev/ca63fc5ed9b1 branches: changeset: 5834:ca63fc5ed9b1 user: Maxim Dounin date: Mon Sep 15 17:59:47 2014 +0400 description: SSL: session id context now includes certificate hash. This prevents inappropriate session reuse in unrelated server{} blocks, while preserving ability to restore sessions on other servers when using TLS Session Tickets. Additionally, session context is now set even if there is no session cache configured. This is needed as it's also used for TLS Session Tickets. Thanks to Antoine Delignat-Lavaud and Piotr Sikora. diffstat: src/event/ngx_event_openssl.c | 98 ++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 96 insertions(+), 2 deletions(-) diffs (127 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -33,6 +33,8 @@ static void ngx_ssl_connection_error(ngx ngx_err_t err, char *text); static void ngx_ssl_clear_error(ngx_log_t *log); +static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl, + ngx_str_t *sess_ctx); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess); @@ -1973,13 +1975,15 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng SSL_CTX_set_timeout(ssl->ctx, (long) timeout); + if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) { + return NGX_ERROR; + } + if (builtin_session_cache == NGX_SSL_NO_SCACHE) { SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); return NGX_OK; } - SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len); - if (builtin_session_cache == NGX_SSL_NONE_SCACHE) { /* @@ -2036,6 +2040,96 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng } +static ngx_int_t +ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) +{ + int n, i; + X509 *cert; + X509_NAME *name; + EVP_MD_CTX md; + unsigned int len; + STACK_OF(X509_NAME) *list; + u_char buf[EVP_MAX_MD_SIZE]; + + /* + * Session ID context is set based on the string provided, + * the server certificate, and the client CA list. + */ + + EVP_MD_CTX_init(&md); + + if (EVP_DigestInit_ex(&md, EVP_sha1(), NULL) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestInit_ex() failed"); + goto failed; + } + + if (EVP_DigestUpdate(&md, sess_ctx->data, sess_ctx->len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + + if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "X509_digest() failed"); + goto failed; + } + + if (EVP_DigestUpdate(&md, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + + list = SSL_CTX_get_client_CA_list(ssl->ctx); + + if (list != NULL) { + n = sk_X509_NAME_num(list); + + for (i = 0; i < n; i++) { + name = sk_X509_NAME_value(list, i); + + if (X509_NAME_digest(name, EVP_sha1(), buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "X509_NAME_digest() failed"); + goto failed; + } + + if (EVP_DigestUpdate(&md, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + } + } + + if (EVP_DigestFinal_ex(&md, buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + + EVP_MD_CTX_cleanup(&md); + + if (SSL_CTX_set_session_id_context(ssl->ctx, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_session_id_context() failed"); + return NGX_ERROR; + } + + return NGX_OK; + +failed: + + EVP_MD_CTX_cleanup(&md); + + return NGX_ERROR; +} + + ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data) { From mdounin at mdounin.ru Mon Sep 15 14:39:32 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 15 Sep 2014 14:39:32 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: http://hg.nginx.org/nginx/rev/46a6c74f79d5 branches: changeset: 5835:46a6c74f79d5 user: Maxim Dounin date: Mon Sep 15 18:03:49 2014 +0400 description: Updated OpenSSL used for win32 builds. diffstat: misc/GNUmakefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/misc/GNUmakefile b/misc/GNUmakefile --- a/misc/GNUmakefile +++ b/misc/GNUmakefile @@ -5,7 +5,7 @@ NGINX = nginx-$(VER) TEMP = tmp OBJS = objs.msvc8 -OPENSSL = openssl-1.0.1h +OPENSSL = openssl-1.0.1i ZLIB = zlib-1.2.8 PCRE = pcre-8.35 From fdasilvayy at gmail.com Tue Sep 16 05:48:10 2014 From: fdasilvayy at gmail.com (Filipe Da Silva) Date: Tue, 16 Sep 2014 07:48:10 +0200 Subject: [PATCH] SSL support for the mail proxy module In-Reply-To: <5c2524403ab7c870b1fa.1410650071@zdev-vm048.eng.zimbra.com> References: <5c2524403ab7c870b1fa.1410650071@zdev-vm048.eng.zimbra.com> Message-ID: <8B3FA009-99B4-43AD-A207-5BE41FA58ECD@gmail.com> Hello, I see at least three issues in this patch: - a mixed use of NGX_MAIL_SSL and NGX_HTTP_SSL defines - a wrong patch format: please add this item to your .hgrc config file: [diff] showfunc = True - as Maxim previously explains, there a conflict with the mail proxy workflow and your changes. Currently, the mail back-end server address ( ip+port) is dynamically returned by the auth script ( called by HTTP ). With your patch, there is only one set of ssl settings for all the mail back-ends, if I'm not wrong ? HTH and regards, FDS. 2014-09-14 1:14 GMT+02:00 Kunal Pariani : > # HG changeset patch > # User Kunal Pariani > # Date 1410649455 18000 > # Sat Sep 13 18:04:15 2014 -0500 > # Node ID 5c2524403ab7c870b1fa7294f935d3292f25fd1d > # Parent e3016ee8dba396614f28a3644996b8cc6de8f9e3 > SSL support for the mail proxy module > > diff -r e3016ee8dba3 -r 5c2524403ab7 src/mail/ngx_mail_proxy_module.c > --- a/src/mail/ngx_mail_proxy_module.c Sat Sep 13 21:47:13 2014 +0400 > +++ b/src/mail/ngx_mail_proxy_module.c Sat Sep 13 18:04:15 2014 -0500 From kpariani at zimbra.com Tue Sep 16 07:13:17 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Tue, 16 Sep 2014 02:13:17 -0500 Subject: [PATCH] SSL support for the mail proxy module In-Reply-To: <8B3FA009-99B4-43AD-A207-5BE41FA58ECD@gmail.com> References: <8B3FA009-99B4-43AD-A207-5BE41FA58ECD@gmail.com> Message-ID: # HG changeset patch # User Kunal Pariani # Date 1410850478 18000 # Tue Sep 16 01:54:38 2014 -0500 # Node ID b35a5391bef67f79f7a099c0cb868477b9abeb43 # Parent e3016ee8dba396614f28a3644996b8cc6de8f9e3 SSL support for the mail proxy module diff -r e3016ee8dba3 -r b35a5391bef6 src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c Sat Sep 13 21:47:13 2014 +0400 +++ b/src/mail/ngx_mail_proxy_module.c Tue Sep 16 01:54:38 2014 -0500 @@ -18,6 +18,15 @@ typedef struct { ngx_flag_t xclient; size_t buffer_size; ngx_msec_t timeout; +#if (NGX_MAIL_SSL) + ngx_flag_t proxy_ssl; + ngx_ssl_t *ssl; + ngx_uint_t ssl_protocols; + ngx_str_t ssl_ciphers; + ngx_flag_t ssl_verify; + ngx_uint_t ssl_verify_depth; + ngx_str_t ssl_trusted_certificate; +#endif } ngx_mail_proxy_conf_t; @@ -35,7 +44,22 @@ static void ngx_mail_proxy_close_session static void *ngx_mail_proxy_create_conf(ngx_conf_t *cf); static char *ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child); +#if (NGX_MAIL_SSL) +static char *ngx_mail_proxy_set_ssl(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static void ngx_mail_proxy_ssl_init_connection(ngx_mail_session_t *s, + ngx_connection_t *c); +static void ngx_mail_proxy_ssl_handshake(ngx_connection_t *c); +static ngx_conf_bitmask_t ngx_mail_proxy_ssl_protocols[] = { + { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, + { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, + { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, + { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, + { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_null_string, 0 } +}; +#endif static ngx_command_t ngx_mail_proxy_commands[] = { @@ -74,6 +98,52 @@ static ngx_command_t ngx_mail_proxy_com offsetof(ngx_mail_proxy_conf_t, xclient), NULL }, +#if (NGX_MAIL_SSL) + + { ngx_string("proxy_ssl"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_mail_proxy_set_ssl, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, proxy_ssl), + NULL }, + + { ngx_string("proxy_ssl_protocols"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_protocols), + &ngx_mail_proxy_ssl_protocols }, + + { ngx_string("proxy_ssl_ciphers"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_ciphers), + NULL }, + + { ngx_string("proxy_ssl_verify"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_verify), + NULL }, + + { ngx_string("proxy_ssl_verify_depth"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_verify_depth), + NULL }, + + { ngx_string("proxy_ssl_trusted_certificate"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, ssl_trusted_certificate), + NULL }, + +#endif + ngx_null_command }; @@ -174,6 +244,15 @@ ngx_mail_proxy_init(ngx_mail_session_t * s->out.len = 0; +#if (NGX_MAIL_SSL) + + if (pcf->proxy_ssl && p->upstream.connection->ssl == NULL) { + ngx_mail_proxy_ssl_init_connection(s, p->upstream.connection); + return; + } + +#endif + switch (s->protocol) { case NGX_MAIL_POP3_PROTOCOL: @@ -1091,6 +1170,13 @@ ngx_mail_proxy_close_session(ngx_mail_se ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "close mail proxy connection: %d", s->proxy->upstream.connection->fd); +#if (NGX_MAIL_SSL) + + if (s->proxy->upstream.connection->ssl) { + s->proxy->upstream.connection->ssl->no_wait_shutdown = 1; + ngx_ssl_shutdown(s->proxy->upstream.connection); + } +#endif ngx_close_connection(s->proxy->upstream.connection); } @@ -1109,12 +1195,26 @@ ngx_mail_proxy_create_conf(ngx_conf_t *c return NULL; } + /* + * set by ngx_pcalloc(): + * + * pcf->ssl_protocols = 0; + * pcf->ssl_ciphers = { 0, NULL }; + * pcf->ssl_trusted_certificate = { 0, NULL }; + */ pcf->enable = NGX_CONF_UNSET; pcf->pass_error_message = NGX_CONF_UNSET; pcf->xclient = NGX_CONF_UNSET; pcf->buffer_size = NGX_CONF_UNSET_SIZE; pcf->timeout = NGX_CONF_UNSET_MSEC; +#if (NGX_MAIL_SSL) + pcf->proxy_ssl = NGX_CONF_UNSET; + pcf->ssl = NGX_CONF_UNSET_PTR; + pcf->ssl_verify = NGX_CONF_UNSET; + pcf->ssl_verify_depth = NGX_CONF_UNSET_UINT; +#endif + return pcf; } @@ -1132,5 +1232,161 @@ ngx_mail_proxy_merge_conf(ngx_conf_t *cf (size_t) ngx_pagesize); ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000); +#if (NGX_MAIL_SSL) + + ngx_conf_merge_value(conf->proxy_ssl, prev->proxy_ssl, 0); + ngx_conf_merge_ptr_value(conf->ssl, prev->ssl, NULL); + + ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols, + (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3 + |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1 + |NGX_SSL_TLSv1_2)); + + ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, + "DEFAULT"); + + ngx_conf_merge_value(conf->ssl_verify, + prev->ssl_verify, 0); + ngx_conf_merge_uint_value(conf->ssl_verify_depth, + prev->ssl_verify_depth, 1); + ngx_conf_merge_str_value(conf->ssl_trusted_certificate, + prev->ssl_trusted_certificate, ""); + +#endif return NGX_CONF_OK; } + +#if (NGX_MAIL_SSL) + +static char* +ngx_mail_proxy_set_ssl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + + ngx_pool_cleanup_t *cln; + char *rc; + ngx_mail_proxy_conf_t *pcf; + + rc = ngx_conf_set_flag_slot(cf, cmd, conf); + if (rc != NGX_CONF_OK) { + return rc; + } + + pcf = (ngx_mail_proxy_conf_t *)conf; + + if (!pcf->proxy_ssl) { + return NGX_CONF_OK; + } + + pcf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); + + if (pcf->ssl == NULL) { + return NGX_CONF_ERROR; + } + + pcf->ssl->log = cf->log; + + if (ngx_ssl_create(pcf->ssl, pcf->ssl_protocols, NULL) + != NGX_OK) { + return NGX_CONF_ERROR; + } + + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NGX_CONF_ERROR; + } + + cln->handler = ngx_ssl_cleanup_ctx; + cln->data = pcf->ssl; + + if (SSL_CTX_set_cipher_list(pcf->ssl->ctx, + (const char *) pcf->ssl_ciphers.data) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, + "SSL_CTX_set_cipher_list(\"%V\") failed", + &pcf->ssl_ciphers); + return NGX_CONF_ERROR; + } + + if (pcf->ssl_verify) { + if (pcf->ssl_trusted_certificate.len == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no proxy_ssl_trusted_certificate for proxy_ssl_verify"); + return NGX_CONF_ERROR; + } + + if (ngx_ssl_trusted_certificate(cf, pcf->ssl, + &pcf->ssl_trusted_certificate, + pcf->ssl_verify_depth) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; +} + +static void +ngx_mail_proxy_ssl_init_connection(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_int_t rc; + ngx_mail_proxy_conf_t *pcf; + + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + + if (ngx_ssl_create_connection(pcf->ssl, c, NGX_SSL_CLIENT) + != NGX_OK) + { + ngx_mail_proxy_internal_server_error(s); + return; + } + + s->connection->log->action = "SSL handshaking to upstream"; + + rc = ngx_ssl_handshake(c); + + if (rc == NGX_AGAIN) { + c->ssl->handler = ngx_mail_proxy_ssl_handshake; + return; + } + + ngx_mail_proxy_ssl_handshake(c); +} + + +static void +ngx_mail_proxy_ssl_handshake(ngx_connection_t *c) +{ + ngx_mail_session_t *s; + s = c->data; + + if (c->ssl->handshaked) { + + c->write->handler = ngx_mail_proxy_dummy_handler; + switch (s->protocol) { + + case NGX_MAIL_POP3_PROTOCOL: + c->read->handler = ngx_mail_proxy_pop3_handler; + s->mail_state = ngx_pop3_start; + break; + + case NGX_MAIL_IMAP_PROTOCOL: + c->read->handler = ngx_mail_proxy_imap_handler; + s->mail_state = ngx_imap_start; + break; + + default: /* NGX_MAIL_SMTP_PROTOCOL */ + c->read->handler = ngx_mail_proxy_smtp_handler; + s->mail_state = ngx_smtp_start; + break; + } + + /* server might have send the initial welcome msg */ + c->read->handler(c->read); + } else { + /* when handshake fails, we should close the session */ + ngx_mail_proxy_upstream_error(s); + } +} + +#endif From kpariani at zimbra.com Tue Sep 16 07:30:17 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Tue, 16 Sep 2014 02:30:17 -0500 (CDT) Subject: [PATCH] SSL support for the mail proxy module In-Reply-To: <1502529507.1950032.1410852599388.JavaMail.zimbra@zimbra.com> References: <5c2524403ab7c870b1fa.1410650071@zdev-vm048.eng.zimbra.com> <8B3FA009-99B4-43AD-A207-5BE41FA58ECD@gmail.com> Message-ID: <607846621.1950104.1410852617470.JavaMail.zimbra@zimbra.com> Updated the diffs after addressing the first 2 issues. Regarding the 3rd comment, you are correct. Only 1 set of ssl settings for all the mail backends with my patch. I guess this will be a limitation with the current mail proxy workflow ? Am not sure of the exact changes that will be required to address this issue completely. Also skipped the non-trivial name related ssl directives from http proxy module as suggested by Maxim. Thanks -Kunal ----- Original Message ----- From: "Filipe Da Silva" To: "nginx-devel" Sent: Monday, September 15, 2014 10:48:10 PM Subject: Re: [PATCH] SSL support for the mail proxy module Hello, I see at least three issues in this patch: - a mixed use of NGX_MAIL_SSL and NGX_HTTP_SSL defines - a wrong patch format: please add this item to your .hgrc config file: [diff] showfunc = True - as Maxim previously explains, there a conflict with the mail proxy workflow and your changes. Currently, the mail back-end server address ( ip+port) is dynamically returned by the auth script ( called by HTTP ). With your patch, there is only one set of ssl settings for all the mail back-ends, if I'm not wrong ? HTH and regards, FDS. 2014-09-14 1:14 GMT+02:00 Kunal Pariani : > # HG changeset patch > # User Kunal Pariani > # Date 1410649455 18000 > # Sat Sep 13 18:04:15 2014 -0500 > # Node ID 5c2524403ab7c870b1fa7294f935d3292f25fd1d > # Parent e3016ee8dba396614f28a3644996b8cc6de8f9e3 > SSL support for the mail proxy module > > diff -r e3016ee8dba3 -r 5c2524403ab7 src/mail/ngx_mail_proxy_module.c > --- a/src/mail/ngx_mail_proxy_module.c Sat Sep 13 21:47:13 2014 +0400 > +++ b/src/mail/ngx_mail_proxy_module.c Sat Sep 13 18:04:15 2014 -0500 _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From mdounin at mdounin.ru Tue Sep 16 12:03:06 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 16:03:06 +0400 Subject: [PATCH] SSL support for the mail proxy module In-Reply-To: <607846621.1950104.1410852617470.JavaMail.zimbra@zimbra.com> References: <5c2524403ab7c870b1fa.1410650071@zdev-vm048.eng.zimbra.com> <8B3FA009-99B4-43AD-A207-5BE41FA58ECD@gmail.com> <607846621.1950104.1410852617470.JavaMail.zimbra@zimbra.com> Message-ID: <20140916120306.GF59236@mdounin.ru> Hello! On Tue, Sep 16, 2014 at 02:30:17AM -0500, Kunal Pariani wrote: > Updated the diffs after addressing the first 2 issues. > Regarding the 3rd comment, you are correct. Only 1 set of ssl > settings for all the mail backends with my patch. I guess this > will be a limitation with the current mail proxy workflow ? Am > not sure of the exact changes that will be required to address > this issue completely. Probably, returning a name by the auth script is a way to go. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Tue Sep 16 14:41:47 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 14:41:47 +0000 Subject: [nginx] nginx-1.7.5-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/fe129aa02db9 branches: changeset: 5836:fe129aa02db9 user: Maxim Dounin date: Tue Sep 16 16:19:03 2014 +0400 description: nginx-1.7.5-RELEASE diffstat: docs/xml/nginx/changes.xml | 145 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 145 insertions(+), 0 deletions(-) diffs (155 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,151 @@ + + + + +??? ????????????? ?????? ??? ?????????? ?????? server +???????????? ???? SSL-?????? ??? ?????? ????? ??? ?????????? +TLS session tickets ???? ???????? ???????? ???????????? +SSL-?????? ? ????????? ??????? ????? server (CVE-2014-3616).
+??????? Antoine Delignat-Lavaud. +
+ +it was possible to reuse SSL sessions in unrelated contexts +if a shared SSL session cache or the same TLS session ticket key +was used for multiple "server" blocks (CVE-2014-3616).
+Thanks to Antoine Delignat-Lavaud. +
+
+ + + +????????? stub_status ?????? ????? ????????? ??? ??????????. + + +now the "stub_status" directive does not require a parameter. + + + + + +???????? always ????????? add_header. + + +the "always" parameter of the "add_header" directive. + + + + + +????????? +proxy_next_upstream_tries, proxy_next_upstream_timeout, +fastcgi_next_upstream_tries, fastcgi_next_upstream_timeout, +memcached_next_upstream_tries, memcached_next_upstream_timeout, +scgi_next_upstream_tries, scgi_next_upstream_timeout, +uwsgi_next_upstream_tries ? uwsgi_next_upstream_timeout. + + +the +"proxy_next_upstream_tries", "proxy_next_upstream_timeout", +"fastcgi_next_upstream_tries", "fastcgi_next_upstream_timeout", +"memcached_next_upstream_tries", "memcached_next_upstream_timeout", +"scgi_next_upstream_tries", "scgi_next_upstream_timeout", +"uwsgi_next_upstream_tries", and "uwsgi_next_upstream_timeout" +directives. + + + + + +? ????????? if ????????? access_log. + + +in the "if" parameter of the "access_log" directive. + + + + + +? ?????? ngx_http_perl_module.
+??????? Piotr Sikora. +
+ +in the ngx_http_perl_module.
+Thanks to Piotr Sikora. +
+
+ + + +????????? listen ????????? ??????-??????? +?? ????????? ??????? ????? ???? ??????????. + + +the "listen" directive of the mail proxy module +did not allow to specify more than two parameters. + + + + + +????????? sub_filter ?? ???????? +? ?????????? ??????? ?? ?????? ???????. + + +the "sub_filter" directive did not work +with a string to replace consisting of a single character. + + + + + +??????? ????? ????????, ???? ????????????? resolver +? ? ???????? ????????? ? DNS-??????? ?????????? ???????. + + +requests might hang if resolver was used +and a timeout occurred during a DNS request. + + + + + +? ?????? ngx_http_spdy_module ??? ????????????? ????????? ? AIO. + + +in the ngx_http_spdy_module when using with AIO. + + + + + +? ??????? ???????? ??? ????????? segmentation fault, +???? ? ??????? ????????? set ?????????? ?????????? +"$http_...", "$sent_http_..." ??? "$upstream_http_...". + + +a segmentation fault might occur in a worker process +if the "set" directive was used to change the "$http_...", +"$sent_http_...", or "$upstream_http_..." variables. + + + + + +? ????????? ?????? ????????? ??????.
+??????? Markus Linnala ? Feng Gu. +
+ +in memory allocation error handling.
+Thanks to Markus Linnala and Feng Gu. +
+
+ +
+ + From mdounin at mdounin.ru Tue Sep 16 14:41:51 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 14:41:51 +0000 Subject: [nginx] release-1.7.5 tag Message-ID: details: http://hg.nginx.org/nginx/rev/4062a5d59d41 branches: changeset: 5837:4062a5d59d41 user: Maxim Dounin date: Tue Sep 16 16:19:03 2014 +0400 description: release-1.7.5 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -374,3 +374,4 @@ 0351a6d89c3dbcc7a76295024ba6b70e27b9a497 0bd223a546192fdf2e862f33938f4ec2a3b5b283 release-1.7.2 fe7cd01828d5ca7491059f0690bb4453645eb28b release-1.7.3 cbb146b120296852e781079d5138b04495bab6df release-1.7.4 +fe129aa02db9001d220f1db7c3c056f79482c111 release-1.7.5 From mdounin at mdounin.ru Tue Sep 16 14:41:54 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 14:41:54 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/91c1f9071abf branches: stable-1.6 changeset: 5838:91c1f9071abf user: Maxim Dounin date: Mon Sep 15 23:39:21 2014 +0400 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1006001 -#define NGINX_VERSION "1.6.1" +#define nginx_version 1006002 +#define NGINX_VERSION "1.6.2" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" From mdounin at mdounin.ru Tue Sep 16 14:41:57 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 14:41:57 +0000 Subject: [nginx] Resolver: fixed resend on malformed responses. Message-ID: details: http://hg.nginx.org/nginx/rev/20ebe12cfa7a branches: stable-1.6 changeset: 5839:20ebe12cfa7a user: Ruslan Ermilov date: Wed Jul 16 10:21:28 2014 +0400 description: Resolver: fixed resend on malformed responses. DNS request resend on malformed responses was broken in 98876ce2a7fd (1.5.8). Reported by Pramod Korathota. diffstat: src/core/ngx_resolver.c | 29 +++++++++++++++++++++++++++-- 1 files changed, 27 insertions(+), 2 deletions(-) diffs (81 lines): diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -1467,7 +1467,6 @@ ngx_resolver_process_a(ngx_resolver_t *r goto failed; } - rn->naddrs6 = 0; qident = (rn->query6[0] << 8) + rn->query6[1]; break; @@ -1482,7 +1481,6 @@ ngx_resolver_process_a(ngx_resolver_t *r goto failed; } - rn->naddrs = 0; qident = (rn->query[0] << 8) + rn->query[1]; } @@ -1507,6 +1505,8 @@ ngx_resolver_process_a(ngx_resolver_t *r case NGX_RESOLVE_AAAA: + rn->naddrs6 = 0; + if (rn->naddrs == (u_short) -1) { goto next; } @@ -1519,6 +1519,8 @@ ngx_resolver_process_a(ngx_resolver_t *r default: /* NGX_RESOLVE_A */ + rn->naddrs = 0; + if (rn->naddrs6 == (u_short) -1) { goto next; } @@ -1539,6 +1541,8 @@ ngx_resolver_process_a(ngx_resolver_t *r case NGX_RESOLVE_AAAA: + rn->naddrs6 = 0; + if (rn->naddrs == (u_short) -1) { rn->code = (u_char) code; goto next; @@ -1548,6 +1552,8 @@ ngx_resolver_process_a(ngx_resolver_t *r default: /* NGX_RESOLVE_A */ + rn->naddrs = 0; + if (rn->naddrs6 == (u_short) -1) { rn->code = (u_char) code; goto next; @@ -1817,6 +1823,25 @@ ngx_resolver_process_a(ngx_resolver_t *r } } + switch (qtype) { + +#if (NGX_HAVE_INET6) + case NGX_RESOLVE_AAAA: + + if (rn->naddrs6 == (u_short) -1) { + rn->naddrs6 = 0; + } + + break; +#endif + + default: /* NGX_RESOLVE_A */ + + if (rn->naddrs == (u_short) -1) { + rn->naddrs = 0; + } + } + if (rn->naddrs != (u_short) -1 #if (NGX_HAVE_INET6) && rn->naddrs6 != (u_short) -1 From mdounin at mdounin.ru Tue Sep 16 14:42:00 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 14:42:00 +0000 Subject: [nginx] Resolver: notify all waiting requests on timeout. Message-ID: details: http://hg.nginx.org/nginx/rev/60d2cb03faee branches: stable-1.6 changeset: 5840:60d2cb03faee user: Ruslan Ermilov date: Tue Aug 19 15:43:26 2014 +0400 description: Resolver: notify all waiting requests on timeout. If a "resolver_timeout" occurs, only the first waiting request was notified. Other requests may hang forever. diffstat: src/core/ngx_resolver.c | 30 +++++++++++++++++++----------- 1 files changed, 19 insertions(+), 11 deletions(-) diffs (68 lines): diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -417,7 +417,7 @@ ngx_resolve_name_done(ngx_resolver_ctx_t /* lock name mutex */ - if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { + if (ctx->state == NGX_AGAIN) { hash = ngx_crc32_short(ctx->name.data, ctx->name.len); @@ -664,7 +664,7 @@ ngx_resolve_name_locked(ngx_resolver_t * } ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; + ctx->event->data = rn; ctx->event->log = r->log; ctx->ident = -1; @@ -857,7 +857,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx } ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; + ctx->event->data = rn; ctx->event->log = r->log; ctx->ident = -1; @@ -949,7 +949,7 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t /* lock addr mutex */ - if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { + if (ctx->state == NGX_AGAIN) { switch (ctx->addr.sockaddr->sa_family) { @@ -2791,13 +2791,21 @@ done: static void ngx_resolver_timeout_handler(ngx_event_t *ev) { - ngx_resolver_ctx_t *ctx; - - ctx = ev->data; - - ctx->state = NGX_RESOLVE_TIMEDOUT; - - ctx->handler(ctx); + ngx_resolver_ctx_t *ctx, *next; + ngx_resolver_node_t *rn; + + rn = ev->data; + ctx = rn->waiting; + rn->waiting = NULL; + + do { + ctx->state = NGX_RESOLVE_TIMEDOUT; + next = ctx->next; + + ctx->handler(ctx); + + ctx = next; + } while (ctx); } From mdounin at mdounin.ru Tue Sep 16 14:42:08 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 14:42:08 +0000 Subject: [nginx] SSL: session id context now includes certificate hash. Message-ID: details: http://hg.nginx.org/nginx/rev/1ee1db30c9b9 branches: stable-1.6 changeset: 5841:1ee1db30c9b9 user: Maxim Dounin date: Mon Sep 15 17:59:47 2014 +0400 description: SSL: session id context now includes certificate hash. This prevents inappropriate session reuse in unrelated server{} blocks, while preserving ability to restore sessions on other servers when using TLS Session Tickets. Additionally, session context is now set even if there is no session cache configured. This is needed as it's also used for TLS Session Tickets. Thanks to Antoine Delignat-Lavaud and Piotr Sikora. diffstat: src/event/ngx_event_openssl.c | 98 ++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 96 insertions(+), 2 deletions(-) diffs (127 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -27,6 +27,8 @@ static void ngx_ssl_connection_error(ngx ngx_err_t err, char *text); static void ngx_ssl_clear_error(ngx_log_t *log); +static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl, + ngx_str_t *sess_ctx); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess); @@ -1729,13 +1731,15 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng SSL_CTX_set_timeout(ssl->ctx, (long) timeout); + if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) { + return NGX_ERROR; + } + if (builtin_session_cache == NGX_SSL_NO_SCACHE) { SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); return NGX_OK; } - SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len); - if (builtin_session_cache == NGX_SSL_NONE_SCACHE) { /* @@ -1792,6 +1796,96 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng } +static ngx_int_t +ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) +{ + int n, i; + X509 *cert; + X509_NAME *name; + EVP_MD_CTX md; + unsigned int len; + STACK_OF(X509_NAME) *list; + u_char buf[EVP_MAX_MD_SIZE]; + + /* + * Session ID context is set based on the string provided, + * the server certificate, and the client CA list. + */ + + EVP_MD_CTX_init(&md); + + if (EVP_DigestInit_ex(&md, EVP_sha1(), NULL) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestInit_ex() failed"); + goto failed; + } + + if (EVP_DigestUpdate(&md, sess_ctx->data, sess_ctx->len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + + if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "X509_digest() failed"); + goto failed; + } + + if (EVP_DigestUpdate(&md, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + + list = SSL_CTX_get_client_CA_list(ssl->ctx); + + if (list != NULL) { + n = sk_X509_NAME_num(list); + + for (i = 0; i < n; i++) { + name = sk_X509_NAME_value(list, i); + + if (X509_NAME_digest(name, EVP_sha1(), buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "X509_NAME_digest() failed"); + goto failed; + } + + if (EVP_DigestUpdate(&md, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + } + } + + if (EVP_DigestFinal_ex(&md, buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + + EVP_MD_CTX_cleanup(&md); + + if (SSL_CTX_set_session_id_context(ssl->ctx, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_session_id_context() failed"); + return NGX_ERROR; + } + + return NGX_OK; + +failed: + + EVP_MD_CTX_cleanup(&md); + + return NGX_ERROR; +} + + ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data) { From mdounin at mdounin.ru Tue Sep 16 14:42:11 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 14:42:11 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: http://hg.nginx.org/nginx/rev/15e4e2014566 branches: stable-1.6 changeset: 5842:15e4e2014566 user: Maxim Dounin date: Mon Sep 15 18:03:49 2014 +0400 description: Updated OpenSSL used for win32 builds. diffstat: misc/GNUmakefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/misc/GNUmakefile b/misc/GNUmakefile --- a/misc/GNUmakefile +++ b/misc/GNUmakefile @@ -5,7 +5,7 @@ NGINX = nginx-$(VER) TEMP = tmp OBJS = objs.msvc8 -OPENSSL = openssl-1.0.1h +OPENSSL = openssl-1.0.1i ZLIB = zlib-1.2.8 PCRE = pcre-8.35 From mdounin at mdounin.ru Tue Sep 16 14:42:13 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 14:42:13 +0000 Subject: [nginx] nginx-1.6.2-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/7dab18c28f45 branches: stable-1.6 changeset: 5843:7dab18c28f45 user: Maxim Dounin date: Tue Sep 16 16:23:18 2014 +0400 description: nginx-1.6.2-RELEASE diffstat: docs/xml/nginx/changes.xml | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 45 insertions(+), 0 deletions(-) diffs (55 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,51 @@ + + + + +??? ????????????? ?????? ??? ?????????? ?????? server +???????????? ???? SSL-?????? ??? ?????? ????? ??? ?????????? +TLS session tickets ???? ???????? ???????? ???????????? +SSL-?????? ? ????????? ??????? ????? server (CVE-2014-3616).
+??????? Antoine Delignat-Lavaud. +
+ +it was possible to reuse SSL sessions in unrelated contexts +if a shared SSL session cache or the same TLS session ticket key +was used for multiple "server" blocks (CVE-2014-3616).
+Thanks to Antoine Delignat-Lavaud. +
+
+ + + +??????? ????? ????????, ???? ????????????? resolver +? DNS-?????? ????????? ???????????? ?????; +?????? ????????? ? 1.5.8. + + +requests might hang if resolver was used +and a DNS server returned a malformed response; +the bug had appeared in 1.5.8. + + + + + +??????? ????? ????????, ???? ????????????? resolver +? ? ???????? ????????? ? DNS-??????? ?????????? ???????. + + +requests might hang if resolver was used +and a timeout occurred during a DNS request. + + + +
+ + From mdounin at mdounin.ru Tue Sep 16 14:42:16 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Sep 2014 14:42:16 +0000 Subject: [nginx] release-1.6.2 tag Message-ID: details: http://hg.nginx.org/nginx/rev/d0e39ec4f23f branches: stable-1.6 changeset: 5844:d0e39ec4f23f user: Maxim Dounin date: Tue Sep 16 16:23:19 2014 +0400 description: release-1.6.2 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -371,3 +371,4 @@ 97b47d95e4449cbde976657cf8cbbc118351ffe0 fd722b890eabc600394349730a093f50dac31639 release-1.5.13 daa5384fd526a9c18fff4f5135646743628f6bc7 release-1.6.0 0cf84a39c1db6d6477a1a5b68aee345289d4d87a release-1.6.1 +7dab18c28f451ce5dd58f11b9f5c8c433953ea09 release-1.6.2 From kpariani at zimbra.com Wed Sep 17 00:23:47 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Tue, 16 Sep 2014 19:23:47 -0500 (CDT) Subject: [PATCH] SSL support for the mail proxy module In-Reply-To: <897609716.2187306.1410913349045.JavaMail.zimbra@zimbra.com> References: <5c2524403ab7c870b1fa.1410650071@zdev-vm048.eng.zimbra.com> <8B3FA009-99B4-43AD-A207-5BE41FA58ECD@gmail.com> <607846621.1950104.1410852617470.JavaMail.zimbra@zimbra.com> <20140916120306.GF59236@mdounin.ru> Message-ID: <1497581210.2187358.1410913427096.JavaMail.zimbra@zimbra.com> I guess these diffs can still be applied with limitation of having the same ssl setting for all upstreams until the support to return a name by the auth script is added later ? Thanks -Kunal ----- Original Message ----- From: "Maxim Dounin" To: "nginx-devel" Sent: Tuesday, September 16, 2014 5:03:06 AM Subject: Re: [PATCH] SSL support for the mail proxy module Hello! On Tue, Sep 16, 2014 at 02:30:17AM -0500, Kunal Pariani wrote: > Updated the diffs after addressing the first 2 issues. > Regarding the 3rd comment, you are correct. Only 1 set of ssl > settings for all the mail backends with my patch. I guess this > will be a limitation with the current mail proxy workflow ? Am > not sure of the exact changes that will be required to address > this issue completely. Probably, returning a name by the auth script is a way to go. -- Maxim Dounin http://nginx.org/ _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From yatiohi at ideopolis.gr Wed Sep 17 07:58:40 2014 From: yatiohi at ideopolis.gr (Christos Trochalakis) Date: Wed, 17 Sep 2014 10:58:40 +0300 Subject: [nginx-announce] nginx security advisory (CVE-2014-3616) In-Reply-To: <20140916144720.GQ59236@mdounin.ru> References: <20140916144720.GQ59236@mdounin.ru> Message-ID: <20140917075840.GA7676@luke.ws.skroutz.gr> On Tue, Sep 16, 2014 at 06:47:20PM +0400, Maxim Dounin wrote: >Hello! > >A problem with SSL session cache in nginx was identified by Antoine >Delignat-Lavaud. It was possible to reuse cached SSL sessions in >unrelated contexts, allowing virtual host confusion attacks in some >configurations by an attacker in a privileged network position >(CVE-2014-3616). > >The problem affects nginx 0.5.6 - 1.7.4 if the same shared >ssl_session_cache and/or ssl_session_ticket_key are used for multiple >server{} blocks. > >The problem is fixed in nginx 1.7.5, 1.6.2. > >Further details can be found in the paper by Antoine Delignat-Lavaud >et al., available at http://bh.ht.vc/vhost_confusion.pdf. > Hello all, I am one of the debian nginx maintainers. Is it possible to provide a patch for nginx-1.2 series since the relevant commit is not backportable as-is? Debian stable (wheezy) comes with nginx 1.2 and unfortunately only security fixes are allowed. Ubuntu might have a similar problem, although I have not checked the applicability of the patch there (Ubuntu comes with nginx-1.4). Thank you, chris From vbart at nginx.com Wed Sep 17 08:08:15 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 17 Sep 2014 08:08:15 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/40b24cfef18b branches: changeset: 5845:40b24cfef18b user: Valentin Bartenev date: Wed Sep 17 12:04:47 2014 +0400 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 4062a5d59d41 -r 40b24cfef18b src/core/nginx.h --- a/src/core/nginx.h Tue Sep 16 16:19:03 2014 +0400 +++ b/src/core/nginx.h Wed Sep 17 12:04:47 2014 +0400 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1007005 -#define NGINX_VERSION "1.7.5" +#define nginx_version 1007006 +#define NGINX_VERSION "1.7.6" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From vbart at nginx.com Wed Sep 17 08:08:18 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 17 Sep 2014 08:08:18 +0000 Subject: [nginx] Limit req: don't truncate key value to 255 bytes. Message-ID: details: http://hg.nginx.org/nginx/rev/cda4fcb9294c branches: changeset: 5846:cda4fcb9294c user: Valentin Bartenev date: Tue Sep 16 21:12:51 2014 +0400 description: Limit req: don't truncate key value to 255 bytes. While the module allows to use values up to 65535 bytes as a key, that actually never worked properly. diffstat: src/http/modules/ngx_http_limit_req_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 40b24cfef18b -r cda4fcb9294c src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c Wed Sep 17 12:04:47 2014 +0400 +++ b/src/http/modules/ngx_http_limit_req_module.c Tue Sep 16 21:12:51 2014 +0400 @@ -461,7 +461,7 @@ ngx_http_limit_req_lookup(ngx_http_limit lr = (ngx_http_limit_req_node_t *) &node->color; - lr->len = (u_char) len; + lr->len = (u_short) len; lr->excess = 0; ngx_memcpy(lr->data, data, len); From flygoast at 126.com Wed Sep 17 15:08:39 2014 From: flygoast at 126.com (flygoast) Date: Wed, 17 Sep 2014 23:08:39 +0800 (CST) Subject: [PATCH]Avoided to add duplicate hash key in ngx_http_types_slot(). Message-ID: # HG changeset patch # User Gu Feng # Date 1410965522 -28800 # Wed Sep 17 22:52:02 2014 +0800 # Node ID 5af55dbe8c301357e021bfefb99f0c359cfde7fd # Parent cda4fcb9294c8f5a0998e7c5d57c5143457db766 Avoided to add duplicate hash key in ngx_http_types_slot(). diff -r cda4fcb9294c -r 5af55dbe8c30 src/http/ngx_http.c --- a/src/http/ngx_http.cTue Sep 16 21:12:51 2014 +0400 +++ b/src/http/ngx_http.cWed Sep 17 22:52:02 2014 +0800 @@ -2005,7 +2005,7 @@ ngx_http_types_slot(ngx_conf_t *cf, ngx_ if (ngx_strcmp(value[i].data, type[n].key.data) == 0) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate MIME type \"%V\"", &value[i]); - continue; + goto next; } } @@ -2017,6 +2017,10 @@ ngx_http_types_slot(ngx_conf_t *cf, ngx_ type->key = value[i]; type->key_hash = hash; type->value = (void *) 4; + + next: + + continue; } return NGX_CONF_OK; -------------- next part -------------- An HTML attachment was scrubbed... URL: From agentzh at gmail.com Wed Sep 17 19:56:33 2014 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Wed, 17 Sep 2014 12:56:33 -0700 Subject: [nginx-announce] nginx security advisory (CVE-2014-3616) In-Reply-To: <20140917075840.GA7676@luke.ws.skroutz.gr> References: <20140916144720.GQ59236@mdounin.ru> <20140917075840.GA7676@luke.ws.skroutz.gr> Message-ID: Hello! On Wed, Sep 17, 2014 at 12:58 AM, Christos Trochalakis wrote: > I am one of the debian nginx maintainers. Is it possible to provide a > patch for nginx-1.2 series since the relevant commit is not backportable > as-is? > +1 I also hope there is a standalone patch that can (also) be applied to older versions in the 1.7.x series. Because I do not want to immediately upgrade to 1.7.5 which contains unrelated changes that breaks some 3rd-party modules like ngx_drizzle, ngx_postgres, and ngx_lua. Regards, -agentzh From kpariani at zimbra.com Wed Sep 17 20:45:14 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Wed, 17 Sep 2014 15:45:14 -0500 Subject: [PATCH] Update mail parsing to be per protocol (imap/pop/smtp) Message-ID: # HG changeset patch # User Kunal Pariani # Date 1410986530 18000 # Wed Sep 17 15:42:10 2014 -0500 # Node ID dfc11aa2a98e697a562b2aee092a77e3dc13f55a # Parent 65988e6762de9c2c98f5f028fddecf45bc05a913 Update mail parsing to be per protocol (imap/pop/smtp) diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail.h Wed Sep 17 15:42:10 2014 -0500 @@ -248,6 +248,7 @@ typedef struct { u_char *arg_start; u_char *arg_end; ngx_uint_t literal_len; + ngx_uint_t eargs; /* expected #args for command */ } ngx_mail_session_t; @@ -315,7 +316,12 @@ typedef struct { #define NGX_MAIL_AUTH_NONE_ENABLED 0x0020 -#define NGX_MAIL_PARSE_INVALID_COMMAND 20 +#define NGX_MAIL_PARSE_INVALID_COMMAND 20 +#define NGX_MAIL_PARSE_INVALID_AUTH_MECH 30 +#define NGX_MAIL_AUTH_ABORT 40 +#define NGX_MAIL_AUTH_ARGUMENT 50 +#define NGX_MAIL_AUTH_FAILED 60 +#define NGX_MAIL_LOGIN_FAILED 70 typedef void (*ngx_mail_init_session_pt)(ngx_mail_session_t *s, @@ -399,6 +405,13 @@ ngx_int_t ngx_mail_auth_parse(ngx_mail_s void ngx_mail_send(ngx_event_t *wev); ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_set_imap_parse_state_start(ngx_mail_session_t * s); +void ngx_mail_set_pop3_parse_state_start(ngx_mail_session_t * s); +void ngx_mail_set_smtp_parse_state_start(ngx_mail_session_t * s); +void ngx_mail_set_imap_parse_state_argument(ngx_mail_session_t * s); +void ngx_mail_set_pop3_parse_state_argument(ngx_mail_session_t * s); +void ngx_mail_set_smtp_parse_state_argument(ngx_mail_session_t * s); +void ngx_mail_reset_parse_buffer(ngx_mail_session_t * s); void ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c); void ngx_mail_close_connection(ngx_connection_t *c); void ngx_mail_session_internal_server_error(ngx_mail_session_t *s); diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail_imap_handler.c --- a/src/mail/ngx_mail_imap_handler.c Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail_imap_handler.c Wed Sep 17 15:42:10 2014 -0500 @@ -21,7 +21,6 @@ static ngx_int_t ngx_mail_imap_capabilit static ngx_int_t ngx_mail_imap_starttls(ngx_mail_session_t *s, ngx_connection_t *c); - static u_char imap_greeting[] = "* OK IMAP4 ready" CRLF; static u_char imap_star[] = "* "; static u_char imap_ok[] = "OK completed" CRLF; @@ -31,7 +30,11 @@ static u_char imap_username[] = "+ VXNl static u_char imap_password[] = "+ UGFzc3dvcmQ6" CRLF; static u_char imap_bye[] = "* BYE" CRLF; static u_char imap_invalid_command[] = "BAD invalid command" CRLF; - +static u_char imap_unsupported_mech[] = "NO mechanism not supported" CRLF; +static u_char imap_nocleartext[] = "NO cleartext logins disabled" CRLF; +static u_char imap_authaborted[] = "BAD AUTHENTICATE aborted" CRLF; +static u_char imap_login_failed[] = "NO LOGIN failed" CRLF; +static u_char imap_authenticate_failed[] = "NO AUTHENTICATE failed" CRLF; void ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c) @@ -235,15 +238,74 @@ ngx_mail_imap_auth_state(ngx_event_t *re ngx_mail_auth(s, c); return; + case NGX_OK: + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + + case NGX_MAIL_AUTH_ABORT: + ngx_str_set(&s->out, imap_authaborted); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + case NGX_ERROR: ngx_mail_session_internal_server_error(s); return; + case NGX_MAIL_AUTH_FAILED: + ngx_str_set(&s->out, imap_authenticate_failed); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + + case NGX_MAIL_LOGIN_FAILED: + ngx_str_set(&s->out, imap_login_failed); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + + case NGX_MAIL_PARSE_INVALID_AUTH_MECH: + ngx_log_debug0 (NGX_LOG_DEBUG_MAIL, c->log, 0, + "unsupported IMAP auth mechanism"); + ngx_str_set(&s->out, imap_unsupported_mech); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + case NGX_MAIL_PARSE_INVALID_COMMAND: - s->state = 0; ngx_str_set(&s->out, imap_invalid_command); s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); break; + + case NGX_MAIL_AUTH_ARGUMENT: + ngx_mail_set_imap_parse_state_argument(s); + /* preserve tag, since tag's memory is allocated in buffer, need to set the + * buffer pos after tag + */ + s->arg_start = s->buffer->start + s->tag.len; + s->buffer->pos = s->arg_start; + s->buffer->last = s->arg_start; + tag = 0; /* just output s->out */ + break; + + case NGX_IMAP_NEXT: + /* do nothing, preserve all the state, including s->state, s->mail_state, + * s->buffer, s->arg_start + */ + break; } if (tag) { @@ -300,6 +362,7 @@ ngx_mail_imap_login(ngx_mail_session_t * #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { + ngx_str_set(&s->text, imap_nocleartext); return NGX_MAIL_PARSE_INVALID_COMMAND; } #endif @@ -342,7 +405,7 @@ ngx_mail_imap_login(ngx_mail_session_t * static ngx_int_t ngx_mail_imap_authenticate(ngx_mail_session_t *s, ngx_connection_t *c) { - ngx_int_t rc; + ngx_int_t rc, res; ngx_mail_core_srv_conf_t *cscf; ngx_mail_imap_srv_conf_t *iscf; @@ -353,36 +416,48 @@ ngx_mail_imap_authenticate(ngx_mail_sess #endif rc = ngx_mail_auth_parse(s, c); + iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); switch (rc) { case NGX_MAIL_AUTH_LOGIN: + if (!(iscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, imap_username); s->mail_state = ngx_imap_auth_login_username; - return NGX_OK; + return NGX_MAIL_AUTH_ARGUMENT; case NGX_MAIL_AUTH_LOGIN_USERNAME: - ngx_str_set(&s->out, imap_password); - s->mail_state = ngx_imap_auth_login_password; - - return ngx_mail_auth_login_username(s, c, 1); + if (!(iscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } + res = ngx_mail_auth_login_username(s, c, 1); + if (res == NGX_MAIL_AUTH_ARGUMENT) { + ngx_str_set(&s->out, imap_password); + s->mail_state = ngx_imap_auth_login_password; + return NGX_MAIL_AUTH_ARGUMENT; + } else { + return res; + } case NGX_MAIL_AUTH_PLAIN: + if (!(iscf->auth_methods & NGX_MAIL_AUTH_PLAIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, imap_plain_next); s->mail_state = ngx_imap_auth_plain; - return NGX_OK; + return NGX_MAIL_AUTH_ARGUMENT; case NGX_MAIL_AUTH_CRAM_MD5: - iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); - if (!(iscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { - return NGX_MAIL_PARSE_INVALID_COMMAND; + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; } if (s->salt.data == NULL) { diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail_parse.c Wed Sep 17 15:42:10 2014 -0500 @@ -13,20 +13,73 @@ #include #include +typedef enum { + swi_start = 0, + swi_spaces_before_command, + swi_command, + swi_spaces_before_argument, + swi_argument, + swi_backslash, + swi_literal, + swi_no_sync_literal_argument, + swi_start_literal_argument, + swi_literal_argument, + swi_end_literal_argument, + swi_almost_done, +} ngx_imap_parse_state_e; + +typedef enum { + swp_start = 0, + swp_spaces_before_argument, + swp_argument, + swp_almost_done +} ngx_pop3_parse_state_e; + +typedef enum { + sws_start = 0, + sws_command, + sws_spaces_before_argument, + sws_argument, + sws_almost_done, + sws_invalid +} ngx_smtp_parse_state_e; + +inline void ngx_mail_set_imap_parse_state_start(ngx_mail_session_t * s) { + s->state = swi_start; +} + +inline void ngx_mail_set_pop3_parse_state_start(ngx_mail_session_t * s) { + s->state = swp_start; +} + +inline void ngx_mail_set_smtp_parse_state_start(ngx_mail_session_t * s) { + s->state = sws_start; +} + +inline void ngx_mail_set_imap_parse_state_argument(ngx_mail_session_t * s) { + s->state = swi_argument; +} + +inline void ngx_mail_set_pop3_parse_state_argument(ngx_mail_session_t * s) { + s->state = swp_argument; +} + +inline void ngx_mail_set_smtp_parse_state_argument(ngx_mail_session_t * s) { + s->state = sws_argument; +} + +inline void ngx_mail_reset_parse_buffer(ngx_mail_session_t * s) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; +} ngx_int_t ngx_mail_pop3_parse_command(ngx_mail_session_t *s) { u_char ch, *p, *c, c0, c1, c2, c3; ngx_str_t *arg; - enum { - sw_start = 0, - sw_spaces_before_argument, - sw_argument, - sw_almost_done - } state; - state = s->state; + ngx_pop3_parse_state_e state = s->state; for (p = s->buffer->pos; p < s->buffer->last; p++) { ch = *p; @@ -34,7 +87,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses switch (state) { /* POP3 command */ - case sw_start: + case swp_start: if (ch == ' ' || ch == CR || ch == LF) { c = s->buffer->start; @@ -87,10 +140,10 @@ ngx_mail_pop3_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = swp_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swp_almost_done; break; case LF: goto done; @@ -104,12 +157,12 @@ ngx_mail_pop3_parse_command(ngx_mail_ses break; - case sw_spaces_before_argument: + case swp_spaces_before_argument: switch (ch) { case ' ': break; case CR: - state = sw_almost_done; + state = swp_almost_done; s->arg_end = p; break; case LF: @@ -117,7 +170,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses goto done; default: if (s->args.nelts <= 2) { - state = sw_argument; + state = swp_argument; s->arg_start = p; break; } @@ -125,7 +178,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses } break; - case sw_argument: + case swp_argument: switch (ch) { case ' ': @@ -155,10 +208,10 @@ ngx_mail_pop3_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = swp_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swp_almost_done; break; case LF: goto done; @@ -170,7 +223,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses } break; - case sw_almost_done: + case swp_almost_done: switch (ch) { case LF: goto done; @@ -199,13 +252,11 @@ done: s->arg_start = NULL; } - s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument; - return NGX_OK; invalid: - s->state = sw_start; + s->state = swp_start; s->arg_start = NULL; return NGX_MAIL_PARSE_INVALID_COMMAND; @@ -217,22 +268,8 @@ ngx_mail_imap_parse_command(ngx_mail_ses { u_char ch, *p, *c; ngx_str_t *arg; - enum { - sw_start = 0, - sw_spaces_before_command, - sw_command, - sw_spaces_before_argument, - sw_argument, - sw_backslash, - sw_literal, - sw_no_sync_literal_argument, - sw_start_literal_argument, - sw_literal_argument, - sw_end_literal_argument, - sw_almost_done - } state; - - state = s->state; + p = NULL; + ngx_imap_parse_state_e state = s->state; for (p = s->buffer->pos; p < s->buffer->last; p++) { ch = *p; @@ -240,40 +277,41 @@ ngx_mail_imap_parse_command(ngx_mail_ses switch (state) { /* IMAP tag */ - case sw_start: + case swi_start: switch (ch) { case ' ': - s->tag.len = p - s->buffer->start + 1; + s->tag.len = p - s->buffer->start; s->tag.data = s->buffer->start; - state = sw_spaces_before_command; + state = swi_spaces_before_command; + s->eargs = 0; break; - case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; - case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + case CR: /* walk through */ + case LF: /* walk through */ + case '\x0': + s->tag.len = p - s->buffer->start; + s->tag.data = s->buffer->start; + s->state = swi_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; } break; - case sw_spaces_before_command: + case swi_spaces_before_command: switch (ch) { case ' ': break; - case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; - case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + case CR: /* walk through */ + case LF: /* walk through */ + case '\x0': + s->state = swi_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; default: s->cmd_start = p; - state = sw_command; + state = swi_command; break; } break; - case sw_command: + case swi_command: if (ch == ' ' || ch == CR || ch == LF) { c = s->cmd_start; @@ -287,7 +325,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[3] == 'P'|| c[3] == 'p')) { s->command = NGX_IMAP_NOOP; - + s->eargs = 0; } else { goto invalid; } @@ -301,7 +339,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[4] == 'N'|| c[4] == 'n')) { s->command = NGX_IMAP_LOGIN; - + s->eargs = 2; } else { goto invalid; } @@ -316,7 +354,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[5] == 'T'|| c[5] == 't')) { s->command = NGX_IMAP_LOGOUT; - + s->eargs = 0; } else { goto invalid; } @@ -334,7 +372,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[7] == 'S'|| c[7] == 's')) { s->command = NGX_IMAP_STARTTLS; - + s->eargs = 0; } else { goto invalid; } @@ -354,7 +392,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[9] == 'Y'|| c[9] == 'y')) { s->command = NGX_IMAP_CAPABILITY; - + s->eargs = 0; } else { goto invalid; } @@ -374,8 +412,12 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[10] == 'T'|| c[10] == 't') && (c[11] == 'E'|| c[11] == 'e')) { - s->command = NGX_IMAP_AUTHENTICATE; - + if (ch != ' ') { + goto invalid; + } else { + s->command = NGX_IMAP_AUTHENTICATE; + s->eargs = 1; + } } else { goto invalid; } @@ -387,10 +429,13 @@ ngx_mail_imap_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + if (s->command == NGX_IMAP_CAPABILITY) { + goto invalid; + } + state = swi_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swi_almost_done; break; case LF: goto done; @@ -404,42 +449,48 @@ ngx_mail_imap_parse_command(ngx_mail_ses break; - case sw_spaces_before_argument: + case swi_spaces_before_argument: switch (ch) { case ' ': break; case CR: - state = sw_almost_done; + if (s->args.nelts == 0) { + goto invalid; /* no argument */ + } + state = swi_almost_done; s->arg_end = p; break; case LF: + if ( s->args.nelts == 0) { + goto invalid; /* no argument */ + } s->arg_end = p; goto done; case '"': - if (s->args.nelts <= 2) { + if (s->args.nelts <= s->eargs) { s->quoted = 1; s->arg_start = p + 1; - state = sw_argument; + state = swi_argument; break; } goto invalid; case '{': - if (s->args.nelts <= 2) { - state = sw_literal; + if (s->args.nelts <= s->eargs) { + state = swi_literal; break; } goto invalid; default: - if (s->args.nelts <= 2) { + if (s->args.nelts <= s->eargs) { s->arg_start = p; - state = sw_argument; + state = swi_argument; break; } goto invalid; } break; - case sw_argument: + case swi_argument: if (ch == ' ' && s->quoted) { break; } @@ -465,10 +516,10 @@ ngx_mail_imap_parse_command(ngx_mail_ses switch (ch) { case '"': case ' ': - state = sw_spaces_before_argument; + state = swi_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swi_almost_done; break; case LF: goto done; @@ -477,46 +528,52 @@ ngx_mail_imap_parse_command(ngx_mail_ses case '\\': if (s->quoted) { s->backslash = 1; - state = sw_backslash; + state = swi_backslash; } break; } break; - case sw_backslash: + case swi_backslash: switch (ch) { case CR: case LF: goto invalid; + case '\\': + case '"': + /* (RFC3501) + a backslash may only escape another backslash, or a double quote */ + state = swi_argument; + break; default: - state = sw_argument; + goto invalid; } break; - case sw_literal: + case swi_literal: if (ch >= '0' && ch <= '9') { s->literal_len = s->literal_len * 10 + (ch - '0'); break; } if (ch == '}') { - state = sw_start_literal_argument; + state = swi_start_literal_argument; break; } if (ch == '+') { - state = sw_no_sync_literal_argument; + state = swi_no_sync_literal_argument; break; } goto invalid; - case sw_no_sync_literal_argument: + case swi_no_sync_literal_argument: if (ch == '}') { s->no_sync_literal = 1; - state = sw_start_literal_argument; + state = swi_start_literal_argument; break; } goto invalid; - case sw_start_literal_argument: + case swi_start_literal_argument: switch (ch) { case CR: break; @@ -524,10 +581,10 @@ ngx_mail_imap_parse_command(ngx_mail_ses s->buffer->pos = p + 1; s->arg_start = p + 1; if (s->no_sync_literal == 0) { - s->state = sw_literal_argument; + s->state = swi_literal_argument; return NGX_IMAP_NEXT; } - state = sw_literal_argument; + state = swi_literal_argument; s->no_sync_literal = 0; break; default: @@ -535,7 +592,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses } break; - case sw_literal_argument: + case swi_literal_argument: if (s->literal_len && --s->literal_len) { break; } @@ -547,36 +604,39 @@ ngx_mail_imap_parse_command(ngx_mail_ses arg->len = p + 1 - s->arg_start; arg->data = s->arg_start; s->arg_start = NULL; - state = sw_end_literal_argument; + state = swi_end_literal_argument; break; - case sw_end_literal_argument: + case swi_end_literal_argument: switch (ch) { case '{': - if (s->args.nelts <= 2) { - state = sw_literal; + if (s->args.nelts <= s->eargs) { + state = swi_literal; break; } goto invalid; case CR: - state = sw_almost_done; + state = swi_almost_done; break; case LF: goto done; default: - state = sw_spaces_before_argument; + state = swi_spaces_before_argument; break; } break; - case sw_almost_done: + case swi_almost_done: switch (ch) { case LF: goto done; default: goto invalid; } + + default: + break; /* for avoid warning only */ } } @@ -604,13 +664,11 @@ done: s->literal_len = 0; } - s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument; - return NGX_OK; invalid: - s->state = sw_start; + s->state = swi_start; s->quoted = 0; s->no_sync_literal = 0; s->literal_len = 0; @@ -624,16 +682,8 @@ ngx_mail_smtp_parse_command(ngx_mail_ses { u_char ch, *p, *c, c0, c1, c2, c3; ngx_str_t *arg; - enum { - sw_start = 0, - sw_command, - sw_invalid, - sw_spaces_before_argument, - sw_argument, - sw_almost_done - } state; - state = s->state; + ngx_smtp_parse_state_e state = s->state; for (p = s->buffer->pos; p < s->buffer->last; p++) { ch = *p; @@ -641,13 +691,13 @@ ngx_mail_smtp_parse_command(ngx_mail_ses switch (state) { /* SMTP command */ - case sw_start: + case sws_start: s->cmd_start = p; - state = sw_command; + state = sws_command; /* fall through */ - case sw_command: + case sws_command: if (ch == ' ' || ch == CR || ch == LF) { c = s->cmd_start; @@ -732,10 +782,10 @@ ngx_mail_smtp_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = sws_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = sws_almost_done; break; case LF: goto done; @@ -749,15 +799,15 @@ ngx_mail_smtp_parse_command(ngx_mail_ses break; - case sw_invalid: + case sws_invalid: goto invalid; - case sw_spaces_before_argument: + case sws_spaces_before_argument: switch (ch) { case ' ': break; case CR: - state = sw_almost_done; + state = sws_almost_done; s->arg_end = p; break; case LF: @@ -765,7 +815,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses goto done; default: if (s->args.nelts <= 10) { - state = sw_argument; + state = sws_argument; s->arg_start = p; break; } @@ -773,7 +823,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses } break; - case sw_argument: + case sws_argument: switch (ch) { case ' ': case CR: @@ -788,10 +838,10 @@ ngx_mail_smtp_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = sws_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = sws_almost_done; break; case LF: goto done; @@ -803,7 +853,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses } break; - case sw_almost_done: + case sws_almost_done: switch (ch) { case LF: goto done; @@ -832,20 +882,18 @@ done: s->arg_start = NULL; } - s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument; - return NGX_OK; invalid: - s->state = sw_invalid; + s->state = sws_invalid; s->arg_start = NULL; /* skip invalid command till LF */ for (p = s->buffer->pos; p < s->buffer->last; p++) { if (*p == LF) { - s->state = sw_start; + s->state = sws_start; p++; break; } @@ -882,7 +930,7 @@ ngx_mail_auth_parse(ngx_mail_session_t * return NGX_MAIL_AUTH_LOGIN; } - if (s->args.nelts == 2) { + if (s->args.nelts == 2) { /* initial response */ return NGX_MAIL_AUTH_LOGIN_USERNAME; } @@ -895,7 +943,7 @@ ngx_mail_auth_parse(ngx_mail_session_t * return NGX_MAIL_AUTH_PLAIN; } - if (s->args.nelts == 2) { + if (s->args.nelts == 2) { /* initial response */ return ngx_mail_auth_plain(s, c, 1); } } @@ -914,5 +962,5 @@ ngx_mail_auth_parse(ngx_mail_session_t * } } - return NGX_MAIL_PARSE_INVALID_COMMAND; + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; } diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail_pop3_handler.c --- a/src/mail/ngx_mail_pop3_handler.c Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail_pop3_handler.c Wed Sep 17 15:42:10 2014 -0500 @@ -27,7 +27,11 @@ static u_char pop3_next[] = "+ " CRLF; static u_char pop3_username[] = "+ VXNlcm5hbWU6" CRLF; static u_char pop3_password[] = "+ UGFzc3dvcmQ6" CRLF; static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF; - +static u_char pop3_unsupported_mech[] = "-ERR mechanism not supported" CRLF; +static u_char pop3_nocleartext[] = "-ERR cleartext logins disabled" CRLF; +static u_char pop3_authaborted[] = "-ERR authentication aborted" CRLF; +static u_char pop3_login_failed[] = "-ERR invalid username/password" CRLF; +static u_char pop3_auth_failed[] = "-ERR line is too long" CRLF; void ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c) @@ -109,6 +113,7 @@ ngx_mail_pop3_init_protocol(ngx_event_t } } + ngx_mail_set_pop3_parse_state_start(s); s->mail_state = ngx_pop3_start; c->read->handler = ngx_mail_pop3_auth_state; @@ -249,30 +254,63 @@ ngx_mail_pop3_auth_state(ngx_event_t *re ngx_mail_auth(s, c); return; + case NGX_OK: + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + + case NGX_MAIL_AUTH_ABORT: + ngx_str_set(&s->out, pop3_authaborted); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + case NGX_ERROR: ngx_mail_session_internal_server_error(s); return; + case NGX_MAIL_LOGIN_FAILED: + ngx_str_set(&s->out, pop3_login_failed); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + + case NGX_MAIL_AUTH_FAILED: + ngx_str_set(&s->out, pop3_auth_failed); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + + case NGX_MAIL_PARSE_INVALID_AUTH_MECH: + ngx_log_debug0 (NGX_LOG_DEBUG_MAIL, c->log, 0, + "unsupported POP auth mechanism"); + ngx_str_set(&s->out, pop3_unsupported_mech); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + case NGX_MAIL_PARSE_INVALID_COMMAND: + ngx_str_set(&s->out, pop3_invalid_command); s->mail_state = ngx_pop3_start; - s->state = 0; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; - ngx_str_set(&s->out, pop3_invalid_command); + case NGX_MAIL_AUTH_ARGUMENT: + s->arg_start = s->buffer->start; + ngx_mail_set_pop3_parse_state_argument(s); + break; - /* fall through */ + } - case NGX_OK: + s->args.nelts = 0; + ngx_mail_reset_parse_buffer(s); - s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; - - if (s->state) { - s->arg_start = s->buffer->start; - } - - ngx_mail_send(c->write); - } + ngx_mail_send(c->write); } static ngx_int_t @@ -282,6 +320,7 @@ ngx_mail_pop3_user(ngx_mail_session_t *s #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { + ngx_str_set(&s->out, pop3_nocleartext); return NGX_MAIL_PARSE_INVALID_COMMAND; } #endif @@ -451,10 +490,7 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); if (s->args.nelts == 0) { - s->out = pscf->auth_capability; - s->state = 0; - - return NGX_OK; + return NGX_MAIL_PARSE_INVALID_COMMAND; } rc = ngx_mail_auth_parse(s, c); @@ -463,6 +499,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s case NGX_MAIL_AUTH_LOGIN: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, pop3_username); s->mail_state = ngx_pop3_auth_login_username; @@ -470,6 +509,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s case NGX_MAIL_AUTH_LOGIN_USERNAME: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, pop3_password); s->mail_state = ngx_pop3_auth_login_password; @@ -477,6 +519,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s case NGX_MAIL_AUTH_PLAIN: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_PLAIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, pop3_next); s->mail_state = ngx_pop3_auth_plain; @@ -494,6 +539,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s } return NGX_ERROR; + + default: + break; } return rc; From kpariani at zimbra.com Wed Sep 17 20:49:50 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Wed, 17 Sep 2014 15:49:50 -0500 (CDT) Subject: [PATCH] Update mail parsing to be per protocol (imap/pop/smtp) In-Reply-To: <1729225955.2387482.1410986975220.JavaMail.zimbra@zimbra.com> References: Message-ID: <1273114156.2387485.1410986989995.JavaMail.zimbra@zimbra.com> Hello, This patch adds separate mail parsing states per protocol (imap/pop/smtp), specific error codes for parsing/auth/login failures. Also includes some minor bug fixes in the mail parsing code. Requesting to include this patch as Zimbra has been using this since nginx 0.5.37, so it's quite heavily tested. Thanks -Kunal ----- Original Message ----- From: "Kunal Pariani" To: "nginx-devel" Sent: Wednesday, September 17, 2014 1:45:14 PM Subject: [PATCH] Update mail parsing to be per protocol (imap/pop/smtp) # HG changeset patch # User Kunal Pariani # Date 1410986530 18000 # Wed Sep 17 15:42:10 2014 -0500 # Node ID dfc11aa2a98e697a562b2aee092a77e3dc13f55a # Parent 65988e6762de9c2c98f5f028fddecf45bc05a913 Update mail parsing to be per protocol (imap/pop/smtp) diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail.h Wed Sep 17 15:42:10 2014 -0500 @@ -248,6 +248,7 @@ typedef struct { u_char *arg_start; u_char *arg_end; ngx_uint_t literal_len; + ngx_uint_t eargs; /* expected #args for command */ } ngx_mail_session_t; @@ -315,7 +316,12 @@ typedef struct { #define NGX_MAIL_AUTH_NONE_ENABLED 0x0020 -#define NGX_MAIL_PARSE_INVALID_COMMAND 20 +#define NGX_MAIL_PARSE_INVALID_COMMAND 20 +#define NGX_MAIL_PARSE_INVALID_AUTH_MECH 30 +#define NGX_MAIL_AUTH_ABORT 40 +#define NGX_MAIL_AUTH_ARGUMENT 50 +#define NGX_MAIL_AUTH_FAILED 60 +#define NGX_MAIL_LOGIN_FAILED 70 typedef void (*ngx_mail_init_session_pt)(ngx_mail_session_t *s, @@ -399,6 +405,13 @@ ngx_int_t ngx_mail_auth_parse(ngx_mail_s void ngx_mail_send(ngx_event_t *wev); ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_set_imap_parse_state_start(ngx_mail_session_t * s); +void ngx_mail_set_pop3_parse_state_start(ngx_mail_session_t * s); +void ngx_mail_set_smtp_parse_state_start(ngx_mail_session_t * s); +void ngx_mail_set_imap_parse_state_argument(ngx_mail_session_t * s); +void ngx_mail_set_pop3_parse_state_argument(ngx_mail_session_t * s); +void ngx_mail_set_smtp_parse_state_argument(ngx_mail_session_t * s); +void ngx_mail_reset_parse_buffer(ngx_mail_session_t * s); void ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c); void ngx_mail_close_connection(ngx_connection_t *c); void ngx_mail_session_internal_server_error(ngx_mail_session_t *s); diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail_imap_handler.c --- a/src/mail/ngx_mail_imap_handler.c Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail_imap_handler.c Wed Sep 17 15:42:10 2014 -0500 @@ -21,7 +21,6 @@ static ngx_int_t ngx_mail_imap_capabilit static ngx_int_t ngx_mail_imap_starttls(ngx_mail_session_t *s, ngx_connection_t *c); - static u_char imap_greeting[] = "* OK IMAP4 ready" CRLF; static u_char imap_star[] = "* "; static u_char imap_ok[] = "OK completed" CRLF; @@ -31,7 +30,11 @@ static u_char imap_username[] = "+ VXNl static u_char imap_password[] = "+ UGFzc3dvcmQ6" CRLF; static u_char imap_bye[] = "* BYE" CRLF; static u_char imap_invalid_command[] = "BAD invalid command" CRLF; - +static u_char imap_unsupported_mech[] = "NO mechanism not supported" CRLF; +static u_char imap_nocleartext[] = "NO cleartext logins disabled" CRLF; +static u_char imap_authaborted[] = "BAD AUTHENTICATE aborted" CRLF; +static u_char imap_login_failed[] = "NO LOGIN failed" CRLF; +static u_char imap_authenticate_failed[] = "NO AUTHENTICATE failed" CRLF; void ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c) @@ -235,15 +238,74 @@ ngx_mail_imap_auth_state(ngx_event_t *re ngx_mail_auth(s, c); return; + case NGX_OK: + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + + case NGX_MAIL_AUTH_ABORT: + ngx_str_set(&s->out, imap_authaborted); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + case NGX_ERROR: ngx_mail_session_internal_server_error(s); return; + case NGX_MAIL_AUTH_FAILED: + ngx_str_set(&s->out, imap_authenticate_failed); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + + case NGX_MAIL_LOGIN_FAILED: + ngx_str_set(&s->out, imap_login_failed); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + + case NGX_MAIL_PARSE_INVALID_AUTH_MECH: + ngx_log_debug0 (NGX_LOG_DEBUG_MAIL, c->log, 0, + "unsupported IMAP auth mechanism"); + ngx_str_set(&s->out, imap_unsupported_mech); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + case NGX_MAIL_PARSE_INVALID_COMMAND: - s->state = 0; ngx_str_set(&s->out, imap_invalid_command); s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); break; + + case NGX_MAIL_AUTH_ARGUMENT: + ngx_mail_set_imap_parse_state_argument(s); + /* preserve tag, since tag's memory is allocated in buffer, need to set the + * buffer pos after tag + */ + s->arg_start = s->buffer->start + s->tag.len; + s->buffer->pos = s->arg_start; + s->buffer->last = s->arg_start; + tag = 0; /* just output s->out */ + break; + + case NGX_IMAP_NEXT: + /* do nothing, preserve all the state, including s->state, s->mail_state, + * s->buffer, s->arg_start + */ + break; } if (tag) { @@ -300,6 +362,7 @@ ngx_mail_imap_login(ngx_mail_session_t * #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { + ngx_str_set(&s->text, imap_nocleartext); return NGX_MAIL_PARSE_INVALID_COMMAND; } #endif @@ -342,7 +405,7 @@ ngx_mail_imap_login(ngx_mail_session_t * static ngx_int_t ngx_mail_imap_authenticate(ngx_mail_session_t *s, ngx_connection_t *c) { - ngx_int_t rc; + ngx_int_t rc, res; ngx_mail_core_srv_conf_t *cscf; ngx_mail_imap_srv_conf_t *iscf; @@ -353,36 +416,48 @@ ngx_mail_imap_authenticate(ngx_mail_sess #endif rc = ngx_mail_auth_parse(s, c); + iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); switch (rc) { case NGX_MAIL_AUTH_LOGIN: + if (!(iscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, imap_username); s->mail_state = ngx_imap_auth_login_username; - return NGX_OK; + return NGX_MAIL_AUTH_ARGUMENT; case NGX_MAIL_AUTH_LOGIN_USERNAME: - ngx_str_set(&s->out, imap_password); - s->mail_state = ngx_imap_auth_login_password; - - return ngx_mail_auth_login_username(s, c, 1); + if (!(iscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } + res = ngx_mail_auth_login_username(s, c, 1); + if (res == NGX_MAIL_AUTH_ARGUMENT) { + ngx_str_set(&s->out, imap_password); + s->mail_state = ngx_imap_auth_login_password; + return NGX_MAIL_AUTH_ARGUMENT; + } else { + return res; + } case NGX_MAIL_AUTH_PLAIN: + if (!(iscf->auth_methods & NGX_MAIL_AUTH_PLAIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, imap_plain_next); s->mail_state = ngx_imap_auth_plain; - return NGX_OK; + return NGX_MAIL_AUTH_ARGUMENT; case NGX_MAIL_AUTH_CRAM_MD5: - iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); - if (!(iscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { - return NGX_MAIL_PARSE_INVALID_COMMAND; + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; } if (s->salt.data == NULL) { diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail_parse.c Wed Sep 17 15:42:10 2014 -0500 @@ -13,20 +13,73 @@ #include #include +typedef enum { + swi_start = 0, + swi_spaces_before_command, + swi_command, + swi_spaces_before_argument, + swi_argument, + swi_backslash, + swi_literal, + swi_no_sync_literal_argument, + swi_start_literal_argument, + swi_literal_argument, + swi_end_literal_argument, + swi_almost_done, +} ngx_imap_parse_state_e; + +typedef enum { + swp_start = 0, + swp_spaces_before_argument, + swp_argument, + swp_almost_done +} ngx_pop3_parse_state_e; + +typedef enum { + sws_start = 0, + sws_command, + sws_spaces_before_argument, + sws_argument, + sws_almost_done, + sws_invalid +} ngx_smtp_parse_state_e; + +inline void ngx_mail_set_imap_parse_state_start(ngx_mail_session_t * s) { + s->state = swi_start; +} + +inline void ngx_mail_set_pop3_parse_state_start(ngx_mail_session_t * s) { + s->state = swp_start; +} + +inline void ngx_mail_set_smtp_parse_state_start(ngx_mail_session_t * s) { + s->state = sws_start; +} + +inline void ngx_mail_set_imap_parse_state_argument(ngx_mail_session_t * s) { + s->state = swi_argument; +} + +inline void ngx_mail_set_pop3_parse_state_argument(ngx_mail_session_t * s) { + s->state = swp_argument; +} + +inline void ngx_mail_set_smtp_parse_state_argument(ngx_mail_session_t * s) { + s->state = sws_argument; +} + +inline void ngx_mail_reset_parse_buffer(ngx_mail_session_t * s) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; +} ngx_int_t ngx_mail_pop3_parse_command(ngx_mail_session_t *s) { u_char ch, *p, *c, c0, c1, c2, c3; ngx_str_t *arg; - enum { - sw_start = 0, - sw_spaces_before_argument, - sw_argument, - sw_almost_done - } state; - state = s->state; + ngx_pop3_parse_state_e state = s->state; for (p = s->buffer->pos; p < s->buffer->last; p++) { ch = *p; @@ -34,7 +87,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses switch (state) { /* POP3 command */ - case sw_start: + case swp_start: if (ch == ' ' || ch == CR || ch == LF) { c = s->buffer->start; @@ -87,10 +140,10 @@ ngx_mail_pop3_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = swp_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swp_almost_done; break; case LF: goto done; @@ -104,12 +157,12 @@ ngx_mail_pop3_parse_command(ngx_mail_ses break; - case sw_spaces_before_argument: + case swp_spaces_before_argument: switch (ch) { case ' ': break; case CR: - state = sw_almost_done; + state = swp_almost_done; s->arg_end = p; break; case LF: @@ -117,7 +170,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses goto done; default: if (s->args.nelts <= 2) { - state = sw_argument; + state = swp_argument; s->arg_start = p; break; } @@ -125,7 +178,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses } break; - case sw_argument: + case swp_argument: switch (ch) { case ' ': @@ -155,10 +208,10 @@ ngx_mail_pop3_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = swp_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swp_almost_done; break; case LF: goto done; @@ -170,7 +223,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses } break; - case sw_almost_done: + case swp_almost_done: switch (ch) { case LF: goto done; @@ -199,13 +252,11 @@ done: s->arg_start = NULL; } - s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument; - return NGX_OK; invalid: - s->state = sw_start; + s->state = swp_start; s->arg_start = NULL; return NGX_MAIL_PARSE_INVALID_COMMAND; @@ -217,22 +268,8 @@ ngx_mail_imap_parse_command(ngx_mail_ses { u_char ch, *p, *c; ngx_str_t *arg; - enum { - sw_start = 0, - sw_spaces_before_command, - sw_command, - sw_spaces_before_argument, - sw_argument, - sw_backslash, - sw_literal, - sw_no_sync_literal_argument, - sw_start_literal_argument, - sw_literal_argument, - sw_end_literal_argument, - sw_almost_done - } state; - - state = s->state; + p = NULL; + ngx_imap_parse_state_e state = s->state; for (p = s->buffer->pos; p < s->buffer->last; p++) { ch = *p; @@ -240,40 +277,41 @@ ngx_mail_imap_parse_command(ngx_mail_ses switch (state) { /* IMAP tag */ - case sw_start: + case swi_start: switch (ch) { case ' ': - s->tag.len = p - s->buffer->start + 1; + s->tag.len = p - s->buffer->start; s->tag.data = s->buffer->start; - state = sw_spaces_before_command; + state = swi_spaces_before_command; + s->eargs = 0; break; - case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; - case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + case CR: /* walk through */ + case LF: /* walk through */ + case '\x0': + s->tag.len = p - s->buffer->start; + s->tag.data = s->buffer->start; + s->state = swi_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; } break; - case sw_spaces_before_command: + case swi_spaces_before_command: switch (ch) { case ' ': break; - case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; - case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + case CR: /* walk through */ + case LF: /* walk through */ + case '\x0': + s->state = swi_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; default: s->cmd_start = p; - state = sw_command; + state = swi_command; break; } break; - case sw_command: + case swi_command: if (ch == ' ' || ch == CR || ch == LF) { c = s->cmd_start; @@ -287,7 +325,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[3] == 'P'|| c[3] == 'p')) { s->command = NGX_IMAP_NOOP; - + s->eargs = 0; } else { goto invalid; } @@ -301,7 +339,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[4] == 'N'|| c[4] == 'n')) { s->command = NGX_IMAP_LOGIN; - + s->eargs = 2; } else { goto invalid; } @@ -316,7 +354,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[5] == 'T'|| c[5] == 't')) { s->command = NGX_IMAP_LOGOUT; - + s->eargs = 0; } else { goto invalid; } @@ -334,7 +372,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[7] == 'S'|| c[7] == 's')) { s->command = NGX_IMAP_STARTTLS; - + s->eargs = 0; } else { goto invalid; } @@ -354,7 +392,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[9] == 'Y'|| c[9] == 'y')) { s->command = NGX_IMAP_CAPABILITY; - + s->eargs = 0; } else { goto invalid; } @@ -374,8 +412,12 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[10] == 'T'|| c[10] == 't') && (c[11] == 'E'|| c[11] == 'e')) { - s->command = NGX_IMAP_AUTHENTICATE; - + if (ch != ' ') { + goto invalid; + } else { + s->command = NGX_IMAP_AUTHENTICATE; + s->eargs = 1; + } } else { goto invalid; } @@ -387,10 +429,13 @@ ngx_mail_imap_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + if (s->command == NGX_IMAP_CAPABILITY) { + goto invalid; + } + state = swi_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swi_almost_done; break; case LF: goto done; @@ -404,42 +449,48 @@ ngx_mail_imap_parse_command(ngx_mail_ses break; - case sw_spaces_before_argument: + case swi_spaces_before_argument: switch (ch) { case ' ': break; case CR: - state = sw_almost_done; + if (s->args.nelts == 0) { + goto invalid; /* no argument */ + } + state = swi_almost_done; s->arg_end = p; break; case LF: + if ( s->args.nelts == 0) { + goto invalid; /* no argument */ + } s->arg_end = p; goto done; case '"': - if (s->args.nelts <= 2) { + if (s->args.nelts <= s->eargs) { s->quoted = 1; s->arg_start = p + 1; - state = sw_argument; + state = swi_argument; break; } goto invalid; case '{': - if (s->args.nelts <= 2) { - state = sw_literal; + if (s->args.nelts <= s->eargs) { + state = swi_literal; break; } goto invalid; default: - if (s->args.nelts <= 2) { + if (s->args.nelts <= s->eargs) { s->arg_start = p; - state = sw_argument; + state = swi_argument; break; } goto invalid; } break; - case sw_argument: + case swi_argument: if (ch == ' ' && s->quoted) { break; } @@ -465,10 +516,10 @@ ngx_mail_imap_parse_command(ngx_mail_ses switch (ch) { case '"': case ' ': - state = sw_spaces_before_argument; + state = swi_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swi_almost_done; break; case LF: goto done; @@ -477,46 +528,52 @@ ngx_mail_imap_parse_command(ngx_mail_ses case '\\': if (s->quoted) { s->backslash = 1; - state = sw_backslash; + state = swi_backslash; } break; } break; - case sw_backslash: + case swi_backslash: switch (ch) { case CR: case LF: goto invalid; + case '\\': + case '"': + /* (RFC3501) + a backslash may only escape another backslash, or a double quote */ + state = swi_argument; + break; default: - state = sw_argument; + goto invalid; } break; - case sw_literal: + case swi_literal: if (ch >= '0' && ch <= '9') { s->literal_len = s->literal_len * 10 + (ch - '0'); break; } if (ch == '}') { - state = sw_start_literal_argument; + state = swi_start_literal_argument; break; } if (ch == '+') { - state = sw_no_sync_literal_argument; + state = swi_no_sync_literal_argument; break; } goto invalid; - case sw_no_sync_literal_argument: + case swi_no_sync_literal_argument: if (ch == '}') { s->no_sync_literal = 1; - state = sw_start_literal_argument; + state = swi_start_literal_argument; break; } goto invalid; - case sw_start_literal_argument: + case swi_start_literal_argument: switch (ch) { case CR: break; @@ -524,10 +581,10 @@ ngx_mail_imap_parse_command(ngx_mail_ses s->buffer->pos = p + 1; s->arg_start = p + 1; if (s->no_sync_literal == 0) { - s->state = sw_literal_argument; + s->state = swi_literal_argument; return NGX_IMAP_NEXT; } - state = sw_literal_argument; + state = swi_literal_argument; s->no_sync_literal = 0; break; default: @@ -535,7 +592,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses } break; - case sw_literal_argument: + case swi_literal_argument: if (s->literal_len && --s->literal_len) { break; } @@ -547,36 +604,39 @@ ngx_mail_imap_parse_command(ngx_mail_ses arg->len = p + 1 - s->arg_start; arg->data = s->arg_start; s->arg_start = NULL; - state = sw_end_literal_argument; + state = swi_end_literal_argument; break; - case sw_end_literal_argument: + case swi_end_literal_argument: switch (ch) { case '{': - if (s->args.nelts <= 2) { - state = sw_literal; + if (s->args.nelts <= s->eargs) { + state = swi_literal; break; } goto invalid; case CR: - state = sw_almost_done; + state = swi_almost_done; break; case LF: goto done; default: - state = sw_spaces_before_argument; + state = swi_spaces_before_argument; break; } break; - case sw_almost_done: + case swi_almost_done: switch (ch) { case LF: goto done; default: goto invalid; } + + default: + break; /* for avoid warning only */ } } @@ -604,13 +664,11 @@ done: s->literal_len = 0; } - s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument; - return NGX_OK; invalid: - s->state = sw_start; + s->state = swi_start; s->quoted = 0; s->no_sync_literal = 0; s->literal_len = 0; @@ -624,16 +682,8 @@ ngx_mail_smtp_parse_command(ngx_mail_ses { u_char ch, *p, *c, c0, c1, c2, c3; ngx_str_t *arg; - enum { - sw_start = 0, - sw_command, - sw_invalid, - sw_spaces_before_argument, - sw_argument, - sw_almost_done - } state; - state = s->state; + ngx_smtp_parse_state_e state = s->state; for (p = s->buffer->pos; p < s->buffer->last; p++) { ch = *p; @@ -641,13 +691,13 @@ ngx_mail_smtp_parse_command(ngx_mail_ses switch (state) { /* SMTP command */ - case sw_start: + case sws_start: s->cmd_start = p; - state = sw_command; + state = sws_command; /* fall through */ - case sw_command: + case sws_command: if (ch == ' ' || ch == CR || ch == LF) { c = s->cmd_start; @@ -732,10 +782,10 @@ ngx_mail_smtp_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = sws_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = sws_almost_done; break; case LF: goto done; @@ -749,15 +799,15 @@ ngx_mail_smtp_parse_command(ngx_mail_ses break; - case sw_invalid: + case sws_invalid: goto invalid; - case sw_spaces_before_argument: + case sws_spaces_before_argument: switch (ch) { case ' ': break; case CR: - state = sw_almost_done; + state = sws_almost_done; s->arg_end = p; break; case LF: @@ -765,7 +815,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses goto done; default: if (s->args.nelts <= 10) { - state = sw_argument; + state = sws_argument; s->arg_start = p; break; } @@ -773,7 +823,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses } break; - case sw_argument: + case sws_argument: switch (ch) { case ' ': case CR: @@ -788,10 +838,10 @@ ngx_mail_smtp_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = sws_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = sws_almost_done; break; case LF: goto done; @@ -803,7 +853,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses } break; - case sw_almost_done: + case sws_almost_done: switch (ch) { case LF: goto done; @@ -832,20 +882,18 @@ done: s->arg_start = NULL; } - s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument; - return NGX_OK; invalid: - s->state = sw_invalid; + s->state = sws_invalid; s->arg_start = NULL; /* skip invalid command till LF */ for (p = s->buffer->pos; p < s->buffer->last; p++) { if (*p == LF) { - s->state = sw_start; + s->state = sws_start; p++; break; } @@ -882,7 +930,7 @@ ngx_mail_auth_parse(ngx_mail_session_t * return NGX_MAIL_AUTH_LOGIN; } - if (s->args.nelts == 2) { + if (s->args.nelts == 2) { /* initial response */ return NGX_MAIL_AUTH_LOGIN_USERNAME; } @@ -895,7 +943,7 @@ ngx_mail_auth_parse(ngx_mail_session_t * return NGX_MAIL_AUTH_PLAIN; } - if (s->args.nelts == 2) { + if (s->args.nelts == 2) { /* initial response */ return ngx_mail_auth_plain(s, c, 1); } } @@ -914,5 +962,5 @@ ngx_mail_auth_parse(ngx_mail_session_t * } } - return NGX_MAIL_PARSE_INVALID_COMMAND; + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; } diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail_pop3_handler.c --- a/src/mail/ngx_mail_pop3_handler.c Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail_pop3_handler.c Wed Sep 17 15:42:10 2014 -0500 @@ -27,7 +27,11 @@ static u_char pop3_next[] = "+ " CRLF; static u_char pop3_username[] = "+ VXNlcm5hbWU6" CRLF; static u_char pop3_password[] = "+ UGFzc3dvcmQ6" CRLF; static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF; - +static u_char pop3_unsupported_mech[] = "-ERR mechanism not supported" CRLF; +static u_char pop3_nocleartext[] = "-ERR cleartext logins disabled" CRLF; +static u_char pop3_authaborted[] = "-ERR authentication aborted" CRLF; +static u_char pop3_login_failed[] = "-ERR invalid username/password" CRLF; +static u_char pop3_auth_failed[] = "-ERR line is too long" CRLF; void ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c) @@ -109,6 +113,7 @@ ngx_mail_pop3_init_protocol(ngx_event_t } } + ngx_mail_set_pop3_parse_state_start(s); s->mail_state = ngx_pop3_start; c->read->handler = ngx_mail_pop3_auth_state; @@ -249,30 +254,63 @@ ngx_mail_pop3_auth_state(ngx_event_t *re ngx_mail_auth(s, c); return; + case NGX_OK: + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + + case NGX_MAIL_AUTH_ABORT: + ngx_str_set(&s->out, pop3_authaborted); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + case NGX_ERROR: ngx_mail_session_internal_server_error(s); return; + case NGX_MAIL_LOGIN_FAILED: + ngx_str_set(&s->out, pop3_login_failed); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + + case NGX_MAIL_AUTH_FAILED: + ngx_str_set(&s->out, pop3_auth_failed); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + + case NGX_MAIL_PARSE_INVALID_AUTH_MECH: + ngx_log_debug0 (NGX_LOG_DEBUG_MAIL, c->log, 0, + "unsupported POP auth mechanism"); + ngx_str_set(&s->out, pop3_unsupported_mech); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + case NGX_MAIL_PARSE_INVALID_COMMAND: + ngx_str_set(&s->out, pop3_invalid_command); s->mail_state = ngx_pop3_start; - s->state = 0; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; - ngx_str_set(&s->out, pop3_invalid_command); + case NGX_MAIL_AUTH_ARGUMENT: + s->arg_start = s->buffer->start; + ngx_mail_set_pop3_parse_state_argument(s); + break; - /* fall through */ + } - case NGX_OK: + s->args.nelts = 0; + ngx_mail_reset_parse_buffer(s); - s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; - - if (s->state) { - s->arg_start = s->buffer->start; - } - - ngx_mail_send(c->write); - } + ngx_mail_send(c->write); } static ngx_int_t @@ -282,6 +320,7 @@ ngx_mail_pop3_user(ngx_mail_session_t *s #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { + ngx_str_set(&s->out, pop3_nocleartext); return NGX_MAIL_PARSE_INVALID_COMMAND; } #endif @@ -451,10 +490,7 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); if (s->args.nelts == 0) { - s->out = pscf->auth_capability; - s->state = 0; - - return NGX_OK; + return NGX_MAIL_PARSE_INVALID_COMMAND; } rc = ngx_mail_auth_parse(s, c); @@ -463,6 +499,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s case NGX_MAIL_AUTH_LOGIN: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, pop3_username); s->mail_state = ngx_pop3_auth_login_username; @@ -470,6 +509,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s case NGX_MAIL_AUTH_LOGIN_USERNAME: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, pop3_password); s->mail_state = ngx_pop3_auth_login_password; @@ -477,6 +519,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s case NGX_MAIL_AUTH_PLAIN: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_PLAIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, pop3_next); s->mail_state = ngx_pop3_auth_plain; @@ -494,6 +539,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s } return NGX_ERROR; + + default: + break; } return rc; _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From kpariani at zimbra.com Wed Sep 17 22:59:23 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Wed, 17 Sep 2014 17:59:23 -0500 Subject: [PATCH] Add 'version' parameter for http upstream server directive Message-ID: <1cad46e7189fc43d50a2.1410994763@zdev-vm048.eng.zimbra.com> # HG changeset patch # User Kunal Pariani # Date 1410994128 18000 # Wed Sep 17 17:48:48 2014 -0500 # Node ID 1cad46e7189fc43d50a24735f61793f710f78967 # Parent dfc11aa2a98e697a562b2aee092a77e3dc13f55a Add 'version' parameter for http upstream server directive diff -r dfc11aa2a98e -r 1cad46e7189f src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Wed Sep 17 15:42:10 2014 -0500 +++ b/src/http/ngx_http_upstream.c Wed Sep 17 17:48:48 2014 -0500 @@ -4870,7 +4870,8 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_co |NGX_HTTP_UPSTREAM_MAX_FAILS |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT |NGX_HTTP_UPSTREAM_DOWN - |NGX_HTTP_UPSTREAM_BACKUP); + |NGX_HTTP_UPSTREAM_BACKUP + |NGX_HTTP_UPSTREAM_VERSION); if (uscf == NULL) { return NGX_CONF_ERROR; } @@ -4966,7 +4967,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *uscf = conf; time_t fail_timeout; - ngx_str_t *value, s; + ngx_str_t *value, s, version; ngx_url_t u; ngx_int_t weight, max_fails; ngx_uint_t i; @@ -4984,6 +4985,8 @@ ngx_http_upstream_server(ngx_conf_t *cf, weight = 1; max_fails = 1; fail_timeout = 10; + version.len = 0; + version.data = NULL; for (i = 2; i < cf->args->nelts; i++) { @@ -5057,6 +5060,20 @@ ngx_http_upstream_server(ngx_conf_t *cf, continue; } + if (ngx_strncmp(value[i].data, "version=", 8) == 0) { + + if (!(uscf->flags & NGX_HTTP_UPSTREAM_VERSION)) { + goto invalid; + } + + s.len = value[i].len - 8; + s.data = &value[i].data[8]; + + version = s; + + continue; + } + goto invalid; } @@ -5080,6 +5097,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, us->weight = weight; us->max_fails = max_fails; us->fail_timeout = fail_timeout; + us->version = version; return NGX_CONF_OK; diff -r dfc11aa2a98e -r 1cad46e7189f src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h Wed Sep 17 15:42:10 2014 -0500 +++ b/src/http/ngx_http_upstream.h Wed Sep 17 17:48:48 2014 -0500 @@ -93,6 +93,7 @@ typedef struct { ngx_uint_t weight; ngx_uint_t max_fails; time_t fail_timeout; + ngx_str_t version; unsigned down:1; unsigned backup:1; @@ -105,6 +106,7 @@ typedef struct { #define NGX_HTTP_UPSTREAM_FAIL_TIMEOUT 0x0008 #define NGX_HTTP_UPSTREAM_DOWN 0x0010 #define NGX_HTTP_UPSTREAM_BACKUP 0x0020 +#define NGX_HTTP_UPSTREAM_VERSION 0x0040 struct ngx_http_upstream_srv_conf_s { From yatiohi at ideopolis.gr Thu Sep 18 08:14:06 2014 From: yatiohi at ideopolis.gr (Christos Trochalakis) Date: Thu, 18 Sep 2014 11:14:06 +0300 Subject: [nginx-announce] nginx security advisory (CVE-2014-3616) In-Reply-To: <20140917075840.GA7676@luke.ws.skroutz.gr> References: <20140916144720.GQ59236@mdounin.ru> <20140917075840.GA7676@luke.ws.skroutz.gr> Message-ID: <20140918081406.GA31453@luke.ws.skroutz.gr> On Wed, Sep 17, 2014 at 10:58:40AM +0300, Christos Trochalakis wrote: >On Tue, Sep 16, 2014 at 06:47:20PM +0400, Maxim Dounin wrote: >>Hello! >> >>A problem with SSL session cache in nginx was identified by Antoine >>Delignat-Lavaud. It was possible to reuse cached SSL sessions in >>unrelated contexts, allowing virtual host confusion attacks in some >>configurations by an attacker in a privileged network position >>(CVE-2014-3616). >> >>The problem affects nginx 0.5.6 - 1.7.4 if the same shared >>ssl_session_cache and/or ssl_session_ticket_key are used for multiple >>server{} blocks. >> >>The problem is fixed in nginx 1.7.5, 1.6.2. >> >>Further details can be found in the paper by Antoine Delignat-Lavaud >>et al., available at http://bh.ht.vc/vhost_confusion.pdf. >> > >Hello all, > >I am one of the debian nginx maintainers. Is it possible to provide a >patch for nginx-1.2 series since the relevant commit is not backportable >as-is? > >Debian stable (wheezy) comes with nginx 1.2 and unfortunately only >security fixes are allowed. > >Ubuntu might have a similar problem, although I have not checked the >applicability of the patch there (Ubuntu comes with nginx-1.4). > >Thank you, >chris > Salvatore Bonaccorso (cc'd) of the Debian Security Team has prepared a combined patch backporting the upstream commit and other bits needed (ngx_ssl_certificate_index). He has uploaded the patch here: https://people.debian.org/~carnil/tmp/nginx/nginx_1.2.1-2.2+wheezy3.debdiff https://people.debian.org/~carnil/tmp/nginx/ We would appreciate it if someone could double-check the patch. Thank you, chris From luis.pedrosa at usc.edu Thu Sep 18 08:24:50 2014 From: luis.pedrosa at usc.edu (Luis David Pedrosa) Date: Thu, 18 Sep 2014 01:24:50 -0700 Subject: nginx Interoperability Analysis Message-ID: <20140918012450.19326r5phtb9cdz4@xenios.pedrosa.3-a.net> Hello everyone, I'm Luis Pedrosa and I a researcher and graduate student at the University of Southern California. My research involves using program analysis techniques on protocol implementations to automatically find interoperability issues. The idea is to automatically find scenarios that lead, for example, a client to send something to a server that is somehow rejected as an invalid message. The point being to either find bugs in the code that can be fixed or, more importantly, to find ambiguities in the standard that should clarified. To evaluate our tool we analyze open-source protocol code and find potential bugs. I've been analyzing the SPDY protocol using the spdylay library as a client and nginx as as a server. We found a few situations where interoperability breaks down between these two, and would like to hear from the nginx-devel community on whether these issues are legitimate and relevant. The issue we found are: - nginx doesn't support "HTTP/0.9" in the "version" header and rejects the message as a bad request. Actually, I believe it looks for anything starting with the following pattern: "HTTP/[1-9]". Is there a reason for HTTP/0.9 to be rejected, while HTTP/3 onwards would be accepted, especially since nginx does support HTTP/0.9 outside of SPDY? spdylay doesn't understand the semantics of the header and let's anything through. The SPDY draft doesn't really offer any insight into allowed values here other than the example "HTTP/1.1". Should the SPDY specification be more clear about the semantics here? - When parsing the path header, nginx must un-escape percent-encoded characters (e.g. %20 for space). If the path has a %, followed by something other than two hexadecimal digits (e.g. path="/%%"), nginx rejects the message as a bad request. Again, spdylay doesn't care about the semantics of the header. The SPDY draft refers to RFC-3986 for URIs, which does require two hex digits after a percent. In your opinion, is automatic character escaping and percent encoding something the client should do, or is this something that should be left up to whoever made the link in the first place? - We also found a deeper issue with correctly formatted percent-encoded characters. It turns out that nginx explicitly blocks the correctly encoded NUL character (%00) in the path header. As before, spdylay doesn't care about such things. RFC-3986 explicitly allows the decoder to reject this character if it does not want to handle it. Is there a particular reason for nginx to reject this encoded character, or is it just a can of worms no one wants to open? - nginx does not allow either the carriage-return ('\r') or the line-feed ('\n') character in header values. spdylay doesn't check for this. I don't believe the SPDY draft mentions this as a problem, but if this were pure HTTP the constraint would make sense as it would start the next header. Should the SPDY draft mention something about handling this corner case? - As nginx parses the path, it keeps track of the hierarchy depth and rejects requests that try to break out of the web-root directory (path="/a/../../"). This is a sane security policy, as this was a huge problem in the early years of the web. spdylay doesn't understand the semantics of the path header and lets anything through. I was surprised to see this being handled in parsing code. Is there a reason that this would be handled as a bad request, instead of a permission issue? Is it just such a bad idea that the sooner it's shot down the better? - nginx doesn't allow the TRACE method header value. This is a perfectly fine message to send, so spdylay let's it out. Is there a particular reason why such a simple HTTP method isn't handled? Please let me know what you think of these issues and of the ability to find them mostly automatically. Thank you. Best regards, Luis D. Pedrosa From mp+nginx at hezmatt.org Thu Sep 18 09:18:28 2014 From: mp+nginx at hezmatt.org (Matt Palmer) Date: Thu, 18 Sep 2014 19:18:28 +1000 Subject: nginx security advisory (CVE-2014-3616) In-Reply-To: <20140918081406.GA31453@luke.ws.skroutz.gr> References: <20140916144720.GQ59236@mdounin.ru> <20140917075840.GA7676@luke.ws.skroutz.gr> <20140918081406.GA31453@luke.ws.skroutz.gr> Message-ID: <20140918091822.GH25667@hezmatt.org> On Thu, Sep 18, 2014 at 11:14:06AM +0300, Christos Trochalakis wrote: > Salvatore Bonaccorso (cc'd) of the Debian Security Team has prepared a > combined patch backporting the upstream commit and other bits needed > (ngx_ssl_certificate_index). He has uploaded the patch here: > > https://people.debian.org/~carnil/tmp/nginx/nginx_1.2.1-2.2+wheezy3.debdiff > https://people.debian.org/~carnil/tmp/nginx/ > > We would appreciate it if someone could double-check the patch. Yeah, that ain't going to fly. The data behind ngx_ssl_certificate_index is never getting initialized. Why don't you just use the patch I put together for the LTS upload I did a couple of days ago? - Matt From mdounin at mdounin.ru Thu Sep 18 10:54:21 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 18 Sep 2014 14:54:21 +0400 Subject: nginx security advisory (CVE-2014-3616) In-Reply-To: <20140918091822.GH25667@hezmatt.org> References: <20140916144720.GQ59236@mdounin.ru> <20140917075840.GA7676@luke.ws.skroutz.gr> <20140918081406.GA31453@luke.ws.skroutz.gr> <20140918091822.GH25667@hezmatt.org> Message-ID: <20140918105421.GN91749@mdounin.ru> Hello! On Thu, Sep 18, 2014 at 07:18:28PM +1000, Matt Palmer wrote: > On Thu, Sep 18, 2014 at 11:14:06AM +0300, Christos Trochalakis wrote: > > Salvatore Bonaccorso (cc'd) of the Debian Security Team has prepared a > > combined patch backporting the upstream commit and other bits needed > > (ngx_ssl_certificate_index). He has uploaded the patch here: > > > > https://people.debian.org/~carnil/tmp/nginx/nginx_1.2.1-2.2+wheezy3.debdiff > > https://people.debian.org/~carnil/tmp/nginx/ > > > > We would appreciate it if someone could double-check the patch. > > Yeah, that ain't going to fly. The data behind ngx_ssl_certificate_index is > never getting initialized. Why don't you just use the patch I put together > for the LTS upload I did a couple of days ago? I haven't seen the patch you've prepared, but for 1.2.x and 1.4.x it should be better to avoid complexity introduced in the 1.7.x/1.6.x and just use a random value for session id context, as there is no support for shared TLS Session Tickets. Patch should be as trivial as: --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1531,14 +1531,16 @@ ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout) { - long cache_mode; + long cache_mode; + u_char buf[16]; if (builtin_session_cache == NGX_SSL_NO_SCACHE) { SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); return NGX_OK; } - SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len); + RAND_pseudo_bytes(buf, 16); + SSL_CTX_set_session_id_context(ssl->ctx, buf, 16); if (builtin_session_cache == NGX_SSL_NONE_SCACHE) { (Against stable-1.2 branch in nginx repo.) Alternatively, trivial configuration-level workarounds can be used to avoid virtual host confusion if it can be important in a particular configuration, see the paper for details. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Sep 18 11:00:32 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 18 Sep 2014 15:00:32 +0400 Subject: [PATCH] Update mail parsing to be per protocol (imap/pop/smtp) In-Reply-To: <1273114156.2387485.1410986989995.JavaMail.zimbra@zimbra.com> References: <1273114156.2387485.1410986989995.JavaMail.zimbra@zimbra.com> Message-ID: <20140918110032.GO91749@mdounin.ru> Hello! On Wed, Sep 17, 2014 at 03:49:50PM -0500, Kunal Pariani wrote: > Hello, > This patch adds separate mail parsing states per protocol > (imap/pop/smtp), specific error codes for parsing/auth/login > failures. Also includes some minor bug fixes in the mail parsing > code. Requesting to include this patch as Zimbra has been using > this since nginx 0.5.37, so it's quite heavily tested. Mail parsing code a bit changed since 0.5.37, so this is more like an argument against. In any case, it's not clear what the patch tries to achieve. It's highly unlikely that it will be considered, see http://nginx.org/en/docs/contributing_changes.html. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Sep 18 11:00:54 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 18 Sep 2014 15:00:54 +0400 Subject: [PATCH] Add 'version' parameter for http upstream server directive In-Reply-To: <1cad46e7189fc43d50a2.1410994763@zdev-vm048.eng.zimbra.com> References: <1cad46e7189fc43d50a2.1410994763@zdev-vm048.eng.zimbra.com> Message-ID: <20140918110054.GP91749@mdounin.ru> Hello! On Wed, Sep 17, 2014 at 05:59:23PM -0500, Kunal Pariani wrote: > # HG changeset patch > # User Kunal Pariani > # Date 1410994128 18000 > # Wed Sep 17 17:48:48 2014 -0500 > # Node ID 1cad46e7189fc43d50a24735f61793f710f78967 > # Parent dfc11aa2a98e697a562b2aee092a77e3dc13f55a > Add 'version' parameter for http upstream server directive http://nginx.org/en/docs/contributing_changes.html "Try to make it clear why the suggested change is needed, and provide a use case, if possible." -- Maxim Dounin http://nginx.org/ From arut at nginx.com Thu Sep 18 12:41:19 2014 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 18 Sep 2014 12:41:19 +0000 Subject: [nginx] FastCGI: fixed start pointers in request buffers. Message-ID: details: http://hg.nginx.org/nginx/rev/52b4984d2b3c branches: changeset: 5847:52b4984d2b3c user: Roman Arutyunyan date: Thu Sep 18 16:37:14 2014 +0400 description: FastCGI: fixed start pointers in request buffers. The start pointers are used in ngx_http_upstream_reinit() to reinit FastCGI requests. diffstat: src/http/modules/ngx_http_fastcgi_module.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r cda4fcb9294c -r 52b4984d2b3c src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c Tue Sep 16 21:12:51 2014 +0400 +++ b/src/http/modules/ngx_http_fastcgi_module.c Thu Sep 18 16:37:14 2014 +0400 @@ -1129,6 +1129,7 @@ ngx_http_fastcgi_create_request(ngx_http } else { b->pos = pos; + b->start = pos; pos += 32 * 1024; if (pos >= body->buf->last) { From arut at nginx.com Thu Sep 18 12:41:23 2014 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 18 Sep 2014 12:41:23 +0000 Subject: [nginx] Upstream: fixed file buffers reinit in ngx_http_upstream... Message-ID: details: http://hg.nginx.org/nginx/rev/106a8bfa4f42 branches: changeset: 5848:106a8bfa4f42 user: Roman Arutyunyan date: Thu Sep 18 16:37:16 2014 +0400 description: Upstream: fixed file buffers reinit in ngx_http_upstream_reinit(). Previously, a file buffer start position was reset to the file start. Now it's reset to the previous file buffer end. This fixes reinitialization of requests having multiple successive parts of a single file. Such requests are generated by fastcgi module. diffstat: src/http/ngx_http_upstream.c | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-) diffs (30 lines): diff -r 52b4984d2b3c -r 106a8bfa4f42 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Thu Sep 18 16:37:14 2014 +0400 +++ b/src/http/ngx_http_upstream.c Thu Sep 18 16:37:16 2014 +0400 @@ -1570,6 +1570,7 @@ done: static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u) { + off_t file_pos; ngx_chain_t *cl; if (u->reinit_request(r) != NGX_OK) { @@ -1591,9 +1592,17 @@ ngx_http_upstream_reinit(ngx_http_reques /* reinit the request chain */ + file_pos = 0; + for (cl = u->request_bufs; cl; cl = cl->next) { cl->buf->pos = cl->buf->start; - cl->buf->file_pos = 0; + + /* there is at most one file */ + + if (cl->buf->in_file) { + cl->buf->file_pos = file_pos; + file_pos = cl->buf->file_last; + } } /* reinit the subrequest's ngx_output_chain() context */ From kpariani at zimbra.com Thu Sep 18 17:17:05 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Thu, 18 Sep 2014 12:17:05 -0500 (CDT) Subject: [PATCH] Add 'version' parameter for http upstream server directive In-Reply-To: <627441849.2542184.1411060539793.JavaMail.zimbra@zimbra.com> References: <1cad46e7189fc43d50a2.1410994763@zdev-vm048.eng.zimbra.com> <20140918110054.GP91749@mdounin.ru> Message-ID: <231051583.2542257.1411060625939.JavaMail.zimbra@zimbra.com> We have added this so as to do Round robin among the upstreams running the same version as the version of the upstream where the client's mail account resides (which i agree is again specific to us). Although i didn't include our changes in ngx_http_upstream_round_robin.c (as its based on our implementation of how the 'version' string looks like), i thought atleast the generic change of supporting 'version' in server directive can be used upstream by nginx too ? Thanks -Kunal ----- Original Message ----- From: "Maxim Dounin" To: "nginx-devel" Sent: Thursday, September 18, 2014 4:00:54 AM Subject: Re: [PATCH] Add 'version' parameter for http upstream server directive Hello! On Wed, Sep 17, 2014 at 05:59:23PM -0500, Kunal Pariani wrote: > # HG changeset patch > # User Kunal Pariani > # Date 1410994128 18000 > # Wed Sep 17 17:48:48 2014 -0500 > # Node ID 1cad46e7189fc43d50a24735f61793f710f78967 > # Parent dfc11aa2a98e697a562b2aee092a77e3dc13f55a > Add 'version' parameter for http upstream server directive http://nginx.org/en/docs/contributing_changes.html "Try to make it clear why the suggested change is needed, and provide a use case, if possible." -- Maxim Dounin http://nginx.org/ _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From kpariani at zimbra.com Thu Sep 18 17:32:48 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Thu, 18 Sep 2014 12:32:48 -0500 (CDT) Subject: [PATCH] Update mail parsing to be per protocol (imap/pop/smtp) In-Reply-To: <610179311.2543167.1411061563818.JavaMail.zimbra@zimbra.com> References: <1273114156.2387485.1410986989995.JavaMail.zimbra@zimbra.com> <20140918110032.GO91749@mdounin.ru> Message-ID: <1644005643.2543169.1411061568638.JavaMail.zimbra@zimbra.com> The patch certainly adds more intelligence in the mail parser per protocol (adding more specific states & error codes) and seems valid even with the latest nginx mainline. Thanks -Kunal ----- Original Message ----- From: "Maxim Dounin" To: "nginx-devel" Sent: Thursday, September 18, 2014 4:00:32 AM Subject: Re: [PATCH] Update mail parsing to be per protocol (imap/pop/smtp) Hello! On Wed, Sep 17, 2014 at 03:49:50PM -0500, Kunal Pariani wrote: > Hello, > This patch adds separate mail parsing states per protocol > (imap/pop/smtp), specific error codes for parsing/auth/login > failures. Also includes some minor bug fixes in the mail parsing > code. Requesting to include this patch as Zimbra has been using > this since nginx 0.5.37, so it's quite heavily tested. Mail parsing code a bit changed since 0.5.37, so this is more like an argument against. In any case, it's not clear what the patch tries to achieve. It's highly unlikely that it will be considered, see http://nginx.org/en/docs/contributing_changes.html. -- Maxim Dounin http://nginx.org/ _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From kpariani at zimbra.com Thu Sep 18 17:59:46 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Thu, 18 Sep 2014 12:59:46 -0500 (CDT) Subject: IMAP ID support in the mail proxy for NGINX Message-ID: <1858807036.2546083.1411063186680.JavaMail.zimbra@zimbra.com> Zimbra has a patch implementing this IMAP ID command (http://www.rfc-base.org/txt/rfc-2971.txt). Would anyone from the nginx team comment on if they would like this from us ? Thanks -Kunal -------------- next part -------------- An HTML attachment was scrubbed... URL: From info at phpgangsta.de Thu Sep 18 18:42:10 2014 From: info at phpgangsta.de (Michael Kliewe) Date: Thu, 18 Sep 2014 20:42:10 +0200 Subject: IMAP ID support in the mail proxy for NGINX In-Reply-To: <1858807036.2546083.1411063186680.JavaMail.zimbra@zimbra.com> References: <1858807036.2546083.1411063186680.JavaMail.zimbra@zimbra.com> Message-ID: <541B2782.2010605@phpgangsta.de> Hi, Am 18.09.2014 um 19:59 schrieb Kunal Pariani: > Zimbra has a patch implementing this IMAP ID command > (http://www.rfc-base.org/txt/rfc-2971.txt). Would anyone from the > nginx team comment on if they would like this from us ? > > Thanks > -Kunal Please see the following patch, which Filipe implemented for me, but it has never been added to nginx ;-( http://mailman.nginx.org/pipermail/nginx-devel/2014-January/004791.html I would be very happy to see IMAP ID support in nginx. Michael -------------- next part -------------- An HTML attachment was scrubbed... URL: From kpariani at zimbra.com Thu Sep 18 19:20:03 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Thu, 18 Sep 2014 14:20:03 -0500 (CDT) Subject: IMAP ID support in the mail proxy for NGINX In-Reply-To: <542456475.2553756.1411068000410.JavaMail.zimbra@zimbra.com> References: <1858807036.2546083.1411063186680.JavaMail.zimbra@zimbra.com> <541B2782.2010605@phpgangsta.de> Message-ID: <1313251441.2553760.1411068003242.JavaMail.zimbra@zimbra.com> Good to know this. Hope it gets included soon considering so many requests already :) Thanks -Kunal From: "Michael Kliewe" To: "nginx-devel" Sent: Thursday, September 18, 2014 11:42:10 AM Subject: Re: IMAP ID support in the mail proxy for NGINX Hi, Am 18.09.2014 um 19:59 schrieb Kunal Pariani: Zimbra has a patch implementing this IMAP ID command ( http://www.rfc-base.org/txt/rfc-2971.txt ). Would anyone from the nginx team comment on if they would like this from us ? Thanks -Kunal Please see the following patch, which Filipe implemented for me, but it has never been added to nginx ;-( http://mailman.nginx.org/pipermail/nginx-devel/2014-January/004791.html I would be very happy to see IMAP ID support in nginx. Michael _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From yingqi.lu at intel.com Thu Sep 18 20:05:39 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Thu, 18 Sep 2014 20:05:39 +0000 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37BA72E@ORSMSX113.amr.corp.intel.com> Dear All, Here is the updated patch for SO_REUSEPORT support enablement on Linux OS (attached below). The changes in this version are: 1. Solve the issue with "binary upgrade on the fly" feature. Thanks to Sepherosa Ziehau for his feedback! With this version of patch, there is no issue or connection loss during the binary upgrade. I tested on RHEL 6.5 (with kernel 3.13.9) and CentOS 7. Both are working fine. The new master process inherited all the previous listen sockets during the upgrade and new children processes inherited from the new master. Also, the workload data show there is no connection loss or performance impact during the binary upgrade. 2. Make the duplication of listen sockets happen in the function ngx_http_init_listening instead of ngx_init_cycle. Please review it and let me know your questions and comments. Thanks very much for your time reviewing the patch. Thanks, Yingqi Lu # HG changeset patch # User Yingqi Lu # Date 1411067116 25200 # Thu Sep 18 12:05:16 2014 -0700 # Node ID 222e0a18a7fd4d61d219ed6e7a2443716978cc71 # Parent 45aef9a5b176d8e522277b9abf6c09fb874ab044 These are the patch files to enable SO_REUSEPORT support (patch is based on nginx-106a8bfa4f42.tar.gz) diff -r 45aef9a5b176 -r 222e0a18a7fd src/core/ngx_connection.c --- a/src/core/ngx_connection.c Thu Sep 18 12:03:41 2014 -0700 +++ b/src/core/ngx_connection.c Thu Sep 18 12:05:16 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -369,6 +370,23 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) diff -r 45aef9a5b176 -r 222e0a18a7fd src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Thu Sep 18 12:03:41 2014 -0700 +++ b/src/core/ngx_cycle.c Thu Sep 18 12:05:16 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,36 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + ngx_so_reuseport_enabled = 0; + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_ONLN); +#else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +146,7 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +196,7 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +263,7 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, (10 * ngx_num_dup_sockets), sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +518,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +526,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +573,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +781,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 45aef9a5b176 -r 222e0a18a7fd src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Thu Sep 18 12:03:41 2014 -0700 +++ b/src/core/ngx_cycle.h Thu Sep 18 12:05:16 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 45aef9a5b176 -r 222e0a18a7fd src/http/ngx_http.c --- a/src/http/ngx_http.c Thu Sep 18 12:03:41 2014 -0700 +++ b/src/http/ngx_http.c Thu Sep 18 12:05:16 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,42 +1703,43 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } - addr++; last--; } 1. Software and workloads used in performance tests may have been optimized for performance only on Intel microprocessors. Performance tests, such as SYSmark and MobileMark, are measured using specific computer systems, components, software, operations and functions. Any change to any of those factors may cause the results to vary. You should consult other information and performance tests to assist you in fully evaluating your contemplated purchases, including the performance of that product when combined with other products. -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Wednesday, August 27, 2014 10:33 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, I am resending this patch with plain text instead of HTML format. I will also post the patch at the end of this email. Hope this will be easier for all of you to review. Please let me know if you have trouble viewing the message or the patch itself. This is our first time submitting the patch here. Your feedback and suggestions are highly appreciated. The "SO_REUSEPORT support for listen sockets support" patches submitted by Sepherosa Ziehau are posted and discussed in [1] and [2]. Last update on the threads was 09/05/2013 and the patch is not included in the current Nginx code. Reading from the discussion, my understanding is that his patch makes a dedicated listen socket for each of the child process. In order to make sure at any given time there is always a listen socket available, the patch makes the first worker process different/special than the rest. Here, I am proposing a simpler way to enable the SO_REUSEPORT support. It is just to create and configure certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the children processes can inherit. In this case, we do not need to worry about ensuring 1 available listen socket at the run time. The number of the listen sockets to be created is calculated based on the number of active CPU threads. With big system that has more CPU threads (where we have the scalability issue), there are more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. This makes sure duplicated listen sockets only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it will fall back to the default/original behavior (this is tested on Linux kernel 3.8.8 where SO_REUSEPORT is not supported). This prototype patch has been tested on an Intel modern dual socket platform with a three tier open source web server workload (PHP+Nginx/memcached/MySQL). The web server has 2 IP network interfaces configured for testing. The Linux kernel used for testing is 3.13.9. Data show: Case 1: with single listen statement (Listen 80) specified in the configuration file, there is 46.3% throughout increase. Case 2: with dual listen statements (for example, Listen 192.168.1.1:80 and Listen 192.168.1.2:80), there is 10% throughput increase. Both testing cases keep everything the same except the patch itself to get above result. The reason that Case1 has bigger performance gains is that Case1 by default only has 1 listen socket while Case2 by default already has 2. Please review it and let me know your questions and comments. Thanks very much for your time reviewing the patch. Thanks, Yingqi Lu [1] http://forum.nginx.org/read.php?29,241283,241283 [2] http://forum.nginx.org/read.php?29,241470,241470 # HG changeset patch # User Yingqi Lu # Date 1408145210 25200 # Fri Aug 15 16:26:50 2014 -0700 # Node ID d9c7259d275dbcae8a0d001ee9703b13312b3263 # Parent 6edcb183e62d610808addebbd18249abb7224a0a These are the patch files for SO_REUSEPORT support. diff -r 6edcb183e62d -r d9c7259d275d ngx_connection.c --- a/ngx_connection.c Fri Aug 15 16:25:32 2014 -0700 +++ b/ngx_connection.c Fri Aug 15 16:26:50 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 6edcb183e62d -r d9c7259d275d ngx_cycle.c --- a/ngx_cycle.c Fri Aug 15 16:25:32 2014 -0700 +++ b/ngx_cycle.c Fri Aug 15 16:26:50 2014 -0700 @@ -25,7 +25,7 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; - +ngx_uint_t so_reuseport_enabled; #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -55,6 +55,34 @@ ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t j, num_cores, num_dup_sockets, orig_nelts; + ngx_socket_t temp_s; + int one = 1; + so_reuseport_enabled = 0; + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); #ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 #endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + so_reuseport_enabled = 1; + } + ngx_close_socket(temp_s); + + if (so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_ONLN); #else + num_cores = 1; +#endif + if (num_cores > 8) { + num_dup_sockets = num_cores/8; + } else { + num_dup_sockets = 1; + } + } else { + num_dup_sockets = 1; + } ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +142,7 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10 * + num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +192,7 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10 * + num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +259,7 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, (10 * num_dup_sockets), + sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -575,7 +603,15 @@ #endif } } + orig_nelts = cycle->listening.nelts; + cycle->listening.nelts = cycle->listening.nelts * num_dup_sockets; + ls = cycle->listening.elts; + for (i = 0; i < num_dup_sockets; i++) { + for(j = 0; j < orig_nelts; j++) { + ls[j + i * orig_nelts] = ls[j]; + } + } if (ngx_open_listening_sockets(cycle) != NGX_OK) { goto failed; } @@ -747,7 +783,7 @@ exit(1); } - n = 10; + n = 10 * num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 6edcb183e62d -r d9c7259d275d ngx_cycle.h --- a/ngx_cycle.h Fri Aug 15 16:25:32 2014 -0700 +++ b/ngx_cycle.h Fri Aug 15 16:26:50 2014 -0700 @@ -136,6 +136,7 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t so_reuseport_enabled; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif 1. Software and workloads used in performance tests may have been optimized for performance only on Intel microprocessors. Performance tests, such as SYSmark and MobileMark, are measured using specific computer systems, components, software, operations and functions. Any change to any of those factors may cause the results to vary. You should consult other information and performance tests to assist you in fully evaluating your contemplated purchases, including the performance of that product when combined with other products. _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From vbart at nginx.com Fri Sep 19 08:37:24 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Fri, 19 Sep 2014 12:37:24 +0400 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <9ACD5B67AAC5594CB6268234CF29CF9AA37BA72E@ORSMSX113.amr.corp.intel.com> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BA72E@ORSMSX113.amr.corp.intel.com> Message-ID: <1984759.coG7FlzylE@vbart-laptop> On Thursday 18 September 2014 20:05:39 Lu, Yingqi wrote: > Dear All, > > Here is the updated patch for SO_REUSEPORT support enablement on Linux OS > (attached below). The changes in this version are: > > 1. Solve the issue with "binary upgrade on the fly" feature. Thanks to > Sepherosa Ziehau for his feedback! With this version of patch, there is no > issue or connection loss during the binary upgrade. I tested on RHEL 6.5 > (with kernel 3.13.9) and CentOS 7. Both are working fine. The new master > process inherited all the previous listen sockets during the upgrade and new > children processes inherited from the new master. Also, the workload data > show there is no connection loss or performance impact during the binary > upgrade. > > 2. Make the duplication of listen sockets happen in the function > ngx_http_init_listening instead of ngx_init_cycle. > > Please review it and let me know your questions and comments. Thanks very > much for your time reviewing the patch. [..] How do you deal with changed number of online cpus since last reload? Please note, that there's no way for a patch to be approved with such number of style issues. You should consult with: http://nginx.org/en/docs/contributing_changes.html#formatting_changes wbr, Valentin V. Bartenev From vbart at nginx.com Fri Sep 19 09:21:21 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 19 Sep 2014 09:21:21 +0000 Subject: [nginx] Fixed writev() debug log message in ngx_darwin_sendfile_... Message-ID: details: http://hg.nginx.org/nginx/rev/810e97260edc branches: changeset: 5849:810e97260edc user: Valentin Bartenev date: Wed Aug 13 15:11:45 2014 +0400 description: Fixed writev() debug log message in ngx_darwin_sendfile_chain(). diffstat: src/os/unix/ngx_darwin_sendfile_chain.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 106a8bfa4f42 -r 810e97260edc src/os/unix/ngx_darwin_sendfile_chain.c --- a/src/os/unix/ngx_darwin_sendfile_chain.c Thu Sep 18 16:37:16 2014 +0400 +++ b/src/os/unix/ngx_darwin_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -285,7 +285,7 @@ ngx_darwin_sendfile_chain(ngx_connection rc = writev(c->fd, header.elts, header.nelts); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "writev: %d of %uz", rc, send); + "writev: %d of %O", rc, header_size); if (rc == -1) { err = ngx_errno; From yingqi.lu at intel.com Fri Sep 19 15:52:35 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Fri, 19 Sep 2014 15:52:35 +0000 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <1984759.coG7FlzylE@vbart-laptop> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BA72E@ORSMSX113.amr.corp.intel.com> <1984759.coG7FlzylE@vbart-laptop> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> Hi Valentin, Thanks very much for your email. Regarding to your first question, I did following test: 1. Start Nginx 2. Offline half of the CPU threads by "echo 0 > /sys/devices/system/cpu/"cpu#"/online 3. Reload Nginx and check the worker process, the number of listen sockets is actually reduced to half. 4. Then, I put back the offlined CPU threads back online, and reload the Nginx again. 5. The new worker process now has 2X listen sockets as the CPU threads doubled since the previous reload. Every time Nginx reloads, my understanding is it will run Ngx_init_cycle. CPU_num_check is there. Is above testing the correct way to check if reload works? Please let me know if I missed anything. Regarding to your second question, I will double check the code style and resend an update. Thanks again for your help and comments! Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Valentin V. Bartenev Sent: Friday, September 19, 2014 1:37 AM To: nginx-devel at nginx.org Subject: Re: [Patch] SO_REUSEPORT support from master process On Thursday 18 September 2014 20:05:39 Lu, Yingqi wrote: > Dear All, > > Here is the updated patch for SO_REUSEPORT support enablement on Linux > OS (attached below). The changes in this version are: > > 1. Solve the issue with "binary upgrade on the fly" feature. Thanks to > Sepherosa Ziehau for his feedback! With this version of patch, there > is no issue or connection loss during the binary upgrade. I tested on > RHEL 6.5 (with kernel 3.13.9) and CentOS 7. Both are working fine. The > new master process inherited all the previous listen sockets during > the upgrade and new children processes inherited from the new master. > Also, the workload data show there is no connection loss or > performance impact during the binary upgrade. > > 2. Make the duplication of listen sockets happen in the function > ngx_http_init_listening instead of ngx_init_cycle. > > Please review it and let me know your questions and comments. Thanks > very much for your time reviewing the patch. [..] How do you deal with changed number of online cpus since last reload? Please note, that there's no way for a patch to be approved with such number of style issues. You should consult with: http://nginx.org/en/docs/contributing_changes.html#formatting_changes wbr, Valentin V. Bartenev _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From vbart at nginx.com Fri Sep 19 16:48:16 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Fri, 19 Sep 2014 20:48:16 +0400 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <1984759.coG7FlzylE@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> Message-ID: <27675150.0d46n4LCFt@vbart-laptop> On Friday 19 September 2014 15:52:35 Lu, Yingqi wrote: > Hi Valentin, > > Thanks very much for your email. > > Regarding to your first question, I did following test: > 1. Start Nginx > 2. Offline half of the CPU threads by "echo 0 > /sys/devices/system/cpu/"cpu#"/online > 3. Reload Nginx and check the worker process, the number of listen sockets is actually > reduced to half. > 4. Then, I put back the offlined CPU threads back online, and reload the Nginx again. > 5. The new worker process now has 2X listen sockets as the CPU threads doubled since the > previous reload. > > Every time Nginx reloads, my understanding is it will run Ngx_init_cycle. CPU_num_check is > there. Is above testing the correct way to check if reload works? Please let me know if I > missed anything. [..] What happens if you shutdown half of your cpus again, and try to reload nginx under high load? As I understand right, with your patch it will close half of listen sockets, and all the connections that have been waiting to be accepted on these sockets will be lost. wbr, Valentin V. Bartenev From yingqi.lu at intel.com Fri Sep 19 17:34:10 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Fri, 19 Sep 2014 17:34:10 +0000 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <27675150.0d46n4LCFt@vbart-laptop> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <1984759.coG7FlzylE@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> <27675150.0d46n4LCFt@vbart-laptop> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37BB059@ORSMSX113.amr.corp.intel.com> Hi Valentin, I just tested the exact case you mentioned and you are right! There is a connection drop, but it got recovered really quickly. The new connections will only go to the remaining listen sockets on a round robin fashion after the reload. I will change the check of "active cpu" to "all cpu". This will make the number of listen sockets a constant as long as the system remain active. Thank you very much for your hint! I will also check the coding style again and resend the patch. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Valentin V. Bartenev Sent: Friday, September 19, 2014 9:48 AM To: nginx-devel at nginx.org Subject: Re: [Patch] SO_REUSEPORT support from master process On Friday 19 September 2014 15:52:35 Lu, Yingqi wrote: > Hi Valentin, > > Thanks very much for your email. > > Regarding to your first question, I did following test: > 1. Start Nginx > 2. Offline half of the CPU threads by "echo 0 > > /sys/devices/system/cpu/"cpu#"/online > 3. Reload Nginx and check the worker process, the number of listen > sockets is actually reduced to half. > 4. Then, I put back the offlined CPU threads back online, and reload the Nginx again. > 5. The new worker process now has 2X listen sockets as the CPU threads > doubled since the previous reload. > > Every time Nginx reloads, my understanding is it will run Ngx_init_cycle. CPU_num_check is > there. Is above testing the correct way to check if reload works? Please let me know if I > missed anything. [..] What happens if you shutdown half of your cpus again, and try to reload nginx under high load? As I understand right, with your patch it will close half of listen sockets, and all the connections that have been waiting to be accepted on these sockets will be lost. wbr, Valentin V. Bartenev _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From vbart at nginx.com Fri Sep 19 22:14:51 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 19 Sep 2014 22:14:51 +0000 Subject: [nginx] Moved the code for adjusting sent buffers in a separate ... Message-ID: details: http://hg.nginx.org/nginx/rev/f9c83484d9ce branches: changeset: 5850:f9c83484d9ce user: Valentin Bartenev date: Wed Aug 13 15:11:45 2014 +0400 description: Moved the code for adjusting sent buffers in a separate function. diffstat: src/core/ngx_buf.c | 46 ++++++++++++++++++++++++++++++ src/core/ngx_buf.h | 1 + src/os/unix/ngx_darwin_sendfile_chain.c | 37 +----------------------- src/os/unix/ngx_freebsd_sendfile_chain.c | 37 +----------------------- src/os/unix/ngx_linux_sendfile_chain.c | 37 +----------------------- src/os/unix/ngx_solaris_sendfilev_chain.c | 37 +----------------------- src/os/unix/ngx_writev_chain.c | 24 +--------------- src/os/win32/ngx_wsasend_chain.c | 47 +----------------------------- 8 files changed, 54 insertions(+), 212 deletions(-) diffs (truncated from 349 to 300 lines): diff -r 810e97260edc -r f9c83484d9ce src/core/ngx_buf.c --- a/src/core/ngx_buf.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_buf.c Wed Aug 13 15:11:45 2014 +0400 @@ -218,3 +218,49 @@ ngx_chain_update_chains(ngx_pool_t *p, n *free = cl; } } + + +ngx_chain_t * +ngx_handle_sent_chain(ngx_chain_t *in, off_t sent) +{ + off_t size; + + for ( /* void */ ; in; in = in->next) { + + if (ngx_buf_special(in->buf)) { + continue; + } + + if (sent == 0) { + break; + } + + size = ngx_buf_size(in->buf); + + if (sent >= size) { + sent -= size; + + if (ngx_buf_in_memory(in->buf)) { + in->buf->pos = in->buf->last; + } + + if (in->buf->in_file) { + in->buf->file_pos = in->buf->file_last; + } + + continue; + } + + if (ngx_buf_in_memory(in->buf)) { + in->buf->pos += (size_t) sent; + } + + if (in->buf->in_file) { + in->buf->file_pos += sent; + } + + break; + } + + return in; +} diff -r 810e97260edc -r f9c83484d9ce src/core/ngx_buf.h --- a/src/core/ngx_buf.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_buf.h Wed Aug 13 15:11:45 2014 +0400 @@ -158,5 +158,6 @@ ngx_chain_t *ngx_chain_get_free_buf(ngx_ void ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy, ngx_chain_t **out, ngx_buf_tag_t tag); +ngx_chain_t *ngx_handle_sent_chain(ngx_chain_t *in, off_t sent); #endif /* _NGX_BUF_H_INCLUDED_ */ diff -r 810e97260edc -r f9c83484d9ce src/os/unix/ngx_darwin_sendfile_chain.c --- a/src/os/unix/ngx_darwin_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_darwin_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -317,42 +317,7 @@ ngx_darwin_sendfile_chain(ngx_connection c->sent += sent; - for ( /* void */ ; in; in = in->next) { - - if (ngx_buf_special(in->buf)) { - continue; - } - - if (sent == 0) { - break; - } - - size = ngx_buf_size(in->buf); - - if (sent >= size) { - sent -= size; - - if (ngx_buf_in_memory(in->buf)) { - in->buf->pos = in->buf->last; - } - - if (in->buf->in_file) { - in->buf->file_pos = in->buf->file_last; - } - - continue; - } - - if (ngx_buf_in_memory(in->buf)) { - in->buf->pos += (size_t) sent; - } - - if (in->buf->in_file) { - in->buf->file_pos += sent; - } - - break; - } + in = ngx_handle_sent_chain(in, sent); if (eintr) { continue; diff -r 810e97260edc -r f9c83484d9ce src/os/unix/ngx_freebsd_sendfile_chain.c --- a/src/os/unix/ngx_freebsd_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -368,42 +368,7 @@ ngx_freebsd_sendfile_chain(ngx_connectio c->sent += sent; - for ( /* void */ ; in; in = in->next) { - - if (ngx_buf_special(in->buf)) { - continue; - } - - if (sent == 0) { - break; - } - - size = ngx_buf_size(in->buf); - - if (sent >= size) { - sent -= size; - - if (ngx_buf_in_memory(in->buf)) { - in->buf->pos = in->buf->last; - } - - if (in->buf->in_file) { - in->buf->file_pos = in->buf->file_last; - } - - continue; - } - - if (ngx_buf_in_memory(in->buf)) { - in->buf->pos += (size_t) sent; - } - - if (in->buf->in_file) { - in->buf->file_pos += sent; - } - - break; - } + in = ngx_handle_sent_chain(in, sent); #if (NGX_HAVE_AIO_SENDFILE) if (c->busy_sendfile) { diff -r 810e97260edc -r f9c83484d9ce src/os/unix/ngx_linux_sendfile_chain.c --- a/src/os/unix/ngx_linux_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_linux_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -325,42 +325,7 @@ ngx_linux_sendfile_chain(ngx_connection_ c->sent += sent; - for ( /* void */ ; in; in = in->next) { - - if (ngx_buf_special(in->buf)) { - continue; - } - - if (sent == 0) { - break; - } - - size = ngx_buf_size(in->buf); - - if (sent >= size) { - sent -= size; - - if (ngx_buf_in_memory(in->buf)) { - in->buf->pos = in->buf->last; - } - - if (in->buf->in_file) { - in->buf->file_pos = in->buf->file_last; - } - - continue; - } - - if (ngx_buf_in_memory(in->buf)) { - in->buf->pos += (size_t) sent; - } - - if (in->buf->in_file) { - in->buf->file_pos += sent; - } - - break; - } + in = ngx_handle_sent_chain(in, sent); if (eintr) { continue; diff -r 810e97260edc -r f9c83484d9ce src/os/unix/ngx_solaris_sendfilev_chain.c --- a/src/os/unix/ngx_solaris_sendfilev_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_solaris_sendfilev_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -207,42 +207,7 @@ ngx_solaris_sendfilev_chain(ngx_connecti c->sent += sent; - for ( /* void */ ; in; in = in->next) { - - if (ngx_buf_special(in->buf)) { - continue; - } - - if (sent == 0) { - break; - } - - size = ngx_buf_size(in->buf); - - if ((off_t) sent >= size) { - sent = (size_t) ((off_t) sent - size); - - if (ngx_buf_in_memory(in->buf)) { - in->buf->pos = in->buf->last; - } - - if (in->buf->in_file) { - in->buf->file_pos = in->buf->file_last; - } - - continue; - } - - if (ngx_buf_in_memory(in->buf)) { - in->buf->pos += sent; - } - - if (in->buf->in_file) { - in->buf->file_pos += sent; - } - - break; - } + in = ngx_handle_sent_chain(in, sent); if (eintr) { continue; diff -r 810e97260edc -r f9c83484d9ce src/os/unix/ngx_writev_chain.c --- a/src/os/unix/ngx_writev_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_writev_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -143,29 +143,7 @@ ngx_writev_chain(ngx_connection_t *c, ng c->sent += sent; - for (cl = in; cl; cl = cl->next) { - - if (ngx_buf_special(cl->buf)) { - continue; - } - - if (sent == 0) { - break; - } - - size = cl->buf->last - cl->buf->pos; - - if (sent >= size) { - sent -= size; - cl->buf->pos = cl->buf->last; - - continue; - } - - cl->buf->pos += sent; - - break; - } + cl = ngx_handle_sent_chain(in, sent); if (eintr) { continue; diff -r 810e97260edc -r f9c83484d9ce src/os/win32/ngx_wsasend_chain.c --- a/src/os/win32/ngx_wsasend_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/win32/ngx_wsasend_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -119,29 +119,7 @@ ngx_wsasend_chain(ngx_connection_t *c, n c->sent += sent; - for (cl = in; cl; cl = cl->next) { - - if (ngx_buf_special(cl->buf)) { - continue; - } - - if (sent == 0) { - break; From vbart at nginx.com Fri Sep 19 22:14:54 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 19 Sep 2014 22:14:54 +0000 Subject: [nginx] Removed the "complete" variable from various send chain ... Message-ID: details: http://hg.nginx.org/nginx/rev/150df089fe47 branches: changeset: 5851:150df089fe47 user: Valentin Bartenev date: Wed Aug 13 15:11:45 2014 +0400 description: Removed the "complete" variable from various send chain functions. It was made redundant by the previous change, since the "sent" variable is no longer modified. diffstat: src/os/unix/ngx_darwin_sendfile_chain.c | 9 ++------- src/os/unix/ngx_freebsd_sendfile_chain.c | 9 ++------- src/os/unix/ngx_linux_sendfile_chain.c | 9 ++------- src/os/unix/ngx_solaris_sendfilev_chain.c | 9 ++------- src/os/unix/ngx_writev_chain.c | 9 ++------- src/os/win32/ngx_wsasend_chain.c | 8 +------- 6 files changed, 11 insertions(+), 42 deletions(-) diffs (236 lines): diff -r f9c83484d9ce -r 150df089fe47 src/os/unix/ngx_darwin_sendfile_chain.c --- a/src/os/unix/ngx_darwin_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_darwin_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -43,7 +43,7 @@ ngx_darwin_sendfile_chain(ngx_connection u_char *prev; off_t size, send, prev_send, aligned, sent, fprev; off_t header_size, file_size; - ngx_uint_t eintr, complete; + ngx_uint_t eintr; ngx_err_t err; ngx_buf_t *file; ngx_array_t header, trailer; @@ -92,7 +92,6 @@ ngx_darwin_sendfile_chain(ngx_connection file_size = 0; header_size = 0; eintr = 0; - complete = 0; prev_send = send; header.nelts = 0; @@ -311,10 +310,6 @@ ngx_darwin_sendfile_chain(ngx_connection sent = rc > 0 ? rc : 0; } - if (send - prev_send == sent) { - complete = 1; - } - c->sent += sent; in = ngx_handle_sent_chain(in, sent); @@ -323,7 +318,7 @@ ngx_darwin_sendfile_chain(ngx_connection continue; } - if (!complete) { + if (send - prev_send != sent) { wev->ready = 0; return in; } diff -r f9c83484d9ce -r 150df089fe47 src/os/unix/ngx_freebsd_sendfile_chain.c --- a/src/os/unix/ngx_freebsd_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -45,7 +45,7 @@ ngx_freebsd_sendfile_chain(ngx_connectio u_char *prev; off_t size, send, prev_send, aligned, sent, fprev; size_t header_size, file_size; - ngx_uint_t eintr, eagain, complete; + ngx_uint_t eintr, eagain; ngx_err_t err; ngx_buf_t *file; ngx_array_t header, trailer; @@ -96,7 +96,6 @@ ngx_freebsd_sendfile_chain(ngx_connectio file_size = 0; header_size = 0; eintr = 0; - complete = 0; prev_send = send; header.nelts = 0; @@ -362,10 +361,6 @@ ngx_freebsd_sendfile_chain(ngx_connectio sent = rc > 0 ? rc : 0; } - if (send - prev_send == sent) { - complete = 1; - } - c->sent += sent; in = ngx_handle_sent_chain(in, sent); @@ -393,7 +388,7 @@ ngx_freebsd_sendfile_chain(ngx_connectio continue; } - if (!complete) { + if (send - prev_send != sent) { wev->ready = 0; return in; } diff -r f9c83484d9ce -r 150df089fe47 src/os/unix/ngx_linux_sendfile_chain.c --- a/src/os/unix/ngx_linux_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_linux_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -43,7 +43,7 @@ ngx_linux_sendfile_chain(ngx_connection_ size_t file_size; ngx_err_t err; ngx_buf_t *file; - ngx_uint_t eintr, complete; + ngx_uint_t eintr; ngx_array_t header; ngx_event_t *wev; ngx_chain_t *cl; @@ -79,7 +79,6 @@ ngx_linux_sendfile_chain(ngx_connection_ file = NULL; file_size = 0; eintr = 0; - complete = 0; prev_send = send; header.nelts = 0; @@ -319,10 +318,6 @@ ngx_linux_sendfile_chain(ngx_connection_ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O", sent); } - if (send - prev_send == sent) { - complete = 1; - } - c->sent += sent; in = ngx_handle_sent_chain(in, sent); @@ -331,7 +326,7 @@ ngx_linux_sendfile_chain(ngx_connection_ continue; } - if (!complete) { + if (send - prev_send != sent) { wev->ready = 0; return in; } diff -r f9c83484d9ce -r 150df089fe47 src/os/unix/ngx_solaris_sendfilev_chain.c --- a/src/os/unix/ngx_solaris_sendfilev_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_solaris_sendfilev_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -51,7 +51,7 @@ ngx_solaris_sendfilev_chain(ngx_connecti off_t size, send, prev_send, aligned, fprev; size_t sent; ssize_t n; - ngx_int_t eintr, complete; + ngx_int_t eintr; ngx_err_t err; sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS]; ngx_array_t vec; @@ -89,7 +89,6 @@ ngx_solaris_sendfilev_chain(ngx_connecti fprev = 0; sfv = NULL; eintr = 0; - complete = 0; sent = 0; prev_send = send; @@ -201,10 +200,6 @@ ngx_solaris_sendfilev_chain(ngx_connecti ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfilev: %z %z", n, sent); - if (send - prev_send == (off_t) sent) { - complete = 1; - } - c->sent += sent; in = ngx_handle_sent_chain(in, sent); @@ -213,7 +208,7 @@ ngx_solaris_sendfilev_chain(ngx_connecti continue; } - if (!complete) { + if (send - prev_send != (off_t) sent) { wev->ready = 0; return in; } diff -r f9c83484d9ce -r 150df089fe47 src/os/unix/ngx_writev_chain.c --- a/src/os/unix/ngx_writev_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_writev_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -23,7 +23,7 @@ ngx_writev_chain(ngx_connection_t *c, ng u_char *prev; ssize_t n, size, sent; off_t send, prev_send; - ngx_uint_t eintr, complete; + ngx_uint_t eintr; ngx_err_t err; ngx_array_t vec; ngx_chain_t *cl; @@ -64,7 +64,6 @@ ngx_writev_chain(ngx_connection_t *c, ng prev = NULL; iov = NULL; eintr = 0; - complete = 0; prev_send = send; vec.nelts = 0; @@ -137,10 +136,6 @@ ngx_writev_chain(ngx_connection_t *c, ng ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent); - if (send - prev_send == sent) { - complete = 1; - } - c->sent += sent; cl = ngx_handle_sent_chain(in, sent); @@ -149,7 +144,7 @@ ngx_writev_chain(ngx_connection_t *c, ng continue; } - if (!complete) { + if (send - prev_send != sent) { wev->ready = 0; return cl; } diff -r f9c83484d9ce -r 150df089fe47 src/os/win32/ngx_wsasend_chain.c --- a/src/os/win32/ngx_wsasend_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/win32/ngx_wsasend_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -19,7 +19,6 @@ ngx_wsasend_chain(ngx_connection_t *c, n int rc; u_char *prev; u_long size, sent, send, prev_send; - ngx_uint_t complete; ngx_err_t err; ngx_event_t *wev; ngx_array_t vec; @@ -40,7 +39,6 @@ ngx_wsasend_chain(ngx_connection_t *c, n } send = 0; - complete = 0; /* * WSABUFs must be 4-byte aligned otherwise @@ -113,15 +111,11 @@ ngx_wsasend_chain(ngx_connection_t *c, n ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "WSASend: fd:%d, s:%ul", c->fd, sent); - if (send - prev_send == sent) { - complete = 1; - } - c->sent += sent; cl = ngx_handle_sent_chain(in, sent); - if (!complete) { + if (send - prev_send != sent) { wev->ready = 0; return cl; } From vbart at nginx.com Fri Sep 19 22:14:57 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 19 Sep 2014 22:14:57 +0000 Subject: [nginx] Merged implementations of ngx_readv_chain(). Message-ID: details: http://hg.nginx.org/nginx/rev/43512a33e8f2 branches: changeset: 5852:43512a33e8f2 user: Valentin Bartenev date: Wed Aug 13 15:11:45 2014 +0400 description: Merged implementations of ngx_readv_chain(). There's no real need in two separate implementations, with and without kqueue support. diffstat: src/os/unix/ngx_readv_chain.c | 106 +++-------------------------------------- 1 files changed, 9 insertions(+), 97 deletions(-) diffs (148 lines): diff -r 150df089fe47 -r 43512a33e8f2 src/os/unix/ngx_readv_chain.c --- a/src/os/unix/ngx_readv_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_readv_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -17,8 +17,6 @@ #endif -#if (NGX_HAVE_KQUEUE) - ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain) { @@ -31,6 +29,8 @@ ngx_readv_chain(ngx_connection_t *c, ngx rev = c->read; +#if (NGX_HAVE_KQUEUE) + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "readv: eof:%d, avail:%d, err:%d", @@ -58,6 +58,8 @@ ngx_readv_chain(ngx_connection_t *c, ngx } } +#endif + prev = NULL; iov = NULL; size = 0; @@ -102,6 +104,9 @@ ngx_readv_chain(ngx_connection_t *c, ngx n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts); if (n >= 0) { + +#if (NGX_HAVE_KQUEUE) + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { rev->available -= n; @@ -141,6 +146,8 @@ ngx_readv_chain(ngx_connection_t *c, ngx return n; } +#endif /* NGX_HAVE_KQUEUE */ + if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) { rev->ready = 0; } @@ -174,98 +181,3 @@ ngx_readv_chain(ngx_connection_t *c, ngx return n; } - -#else /* ! NGX_HAVE_KQUEUE */ - -ssize_t -ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain) -{ - u_char *prev; - ssize_t n, size; - ngx_err_t err; - ngx_array_t vec; - ngx_event_t *rev; - struct iovec *iov, iovs[NGX_IOVS]; - - prev = NULL; - iov = NULL; - size = 0; - - vec.elts = iovs; - vec.nelts = 0; - vec.size = sizeof(struct iovec); - vec.nalloc = NGX_IOVS; - vec.pool = c->pool; - - /* coalesce the neighbouring bufs */ - - while (chain) { - if (prev == chain->buf->last) { - iov->iov_len += chain->buf->end - chain->buf->last; - - } else { - if (vec.nelts >= IOV_MAX) { - break; - } - - iov = ngx_array_push(&vec); - if (iov == NULL) { - return NGX_ERROR; - } - - iov->iov_base = (void *) chain->buf->last; - iov->iov_len = chain->buf->end - chain->buf->last; - } - - size += chain->buf->end - chain->buf->last; - prev = chain->buf->end; - chain = chain->next; - } - - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "readv: %d:%d", vec.nelts, iov->iov_len); - - rev = c->read; - - do { - n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts); - - if (n == 0) { - rev->ready = 0; - rev->eof = 1; - - return n; - - } else if (n > 0) { - - if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) { - rev->ready = 0; - } - - return n; - } - - err = ngx_socket_errno; - - if (err == NGX_EAGAIN || err == NGX_EINTR) { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, - "readv() not ready"); - n = NGX_AGAIN; - - } else { - n = ngx_connection_error(c, err, "readv() failed"); - break; - } - - } while (err == NGX_EINTR); - - rev->ready = 0; - - if (n == NGX_ERROR) { - c->read->error = 1; - } - - return n; -} - -#endif /* NGX_HAVE_KQUEUE */ From yingqi.lu at intel.com Sat Sep 20 22:23:05 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Sat, 20 Sep 2014 22:23:05 +0000 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <9ACD5B67AAC5594CB6268234CF29CF9AA37BB059@ORSMSX113.amr.corp.intel.com> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <1984759.coG7FlzylE@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> <27675150.0d46n4LCFt@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BB059@ORSMSX113.amr.corp.intel.com> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37BBD5D@ORSMSX113.amr.corp.intel.com> Dear All, Here is another updated version of the patch. Thanks very much to Valentin Bartenev for his valuable feedback! Here are the changes in this version: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. The way we created the patch below is: we clone the code from http://hg.nginx.org/nginx, modified 4 files and then committed the changes. After that, we export the patch and attached here. Please let me know if there is anything missing here. This is the first time we prototype the patch for Nginx. Your comments and feedback are highly appreciated. Thanks, Yingqi # HG changeset patch # User Yingqi Lu # Date 1411248953 25200 # Sat Sep 20 14:35:53 2014 -0700 # Node ID 04abfbb10a7f5e4efd5187d1382a880483a79294 # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f Added SO_REUSEPORT support. It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 14:35:53 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 14:35:53 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); +#else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 14:35:53 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r 04abfbb10a7f src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 14:35:53 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Friday, September 19, 2014 10:34 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Hi Valentin, I just tested the exact case you mentioned and you are right! There is a connection drop, but it got recovered really quickly. The new connections will only go to the remaining listen sockets on a round robin fashion after the reload. I will change the check of "active cpu" to "all cpu". This will make the number of listen sockets a constant as long as the system remain active. Thank you very much for your hint! I will also check the coding style again and resend the patch. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Valentin V. Bartenev Sent: Friday, September 19, 2014 9:48 AM To: nginx-devel at nginx.org Subject: Re: [Patch] SO_REUSEPORT support from master process On Friday 19 September 2014 15:52:35 Lu, Yingqi wrote: > Hi Valentin, > > Thanks very much for your email. > > Regarding to your first question, I did following test: > 1. Start Nginx > 2. Offline half of the CPU threads by "echo 0 > > /sys/devices/system/cpu/"cpu#"/online > 3. Reload Nginx and check the worker process, the number of listen > sockets is actually reduced to half. > 4. Then, I put back the offlined CPU threads back online, and reload the Nginx again. > 5. The new worker process now has 2X listen sockets as the CPU threads > doubled since the previous reload. > > Every time Nginx reloads, my understanding is it will run Ngx_init_cycle. CPU_num_check is > there. Is above testing the correct way to check if reload works? Please let me know if I > missed anything. [..] What happens if you shutdown half of your cpus again, and try to reload nginx under high load? As I understand right, with your patch it will close half of listen sockets, and all the connections that have been waiting to be accepted on these sockets will be lost. wbr, Valentin V. Bartenev _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From yingqi.lu at intel.com Sat Sep 20 23:00:18 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Sat, 20 Sep 2014 23:00:18 +0000 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <9ACD5B67AAC5594CB6268234CF29CF9AA37BBD5D@ORSMSX113.amr.corp.intel.com> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <1984759.coG7FlzylE@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> <27675150.0d46n4LCFt@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BB059@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BBD5D@ORSMSX113.amr.corp.intel.com> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37BBE21@ORSMSX113.amr.corp.intel.com> Dear All, After I sent out the patch, I noticed that the patch inserted in the email is actually with different format than the original one generated by TortoiseHg. What I did is just copying it and pasting in the email. Did I missed anything? I guess this is not the correct way to send the patch. I will try to find a way to send directly from ToriseHg. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Saturday, September 20, 2014 3:23 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, Here is another updated version of the patch. Thanks very much to Valentin Bartenev for his valuable feedback! Here are the changes in this version: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. The way we created the patch below is: we clone the code from http://hg.nginx.org/nginx, modified 4 files and then committed the changes. After that, we export the patch and attached here. Please let me know if there is anything missing here. This is the first time we prototype the patch for Nginx. Your comments and feedback are highly appreciated. Thanks, Yingqi # HG changeset patch # User Yingqi Lu # Date 1411248953 25200 # Sat Sep 20 14:35:53 2014 -0700 # Node ID 04abfbb10a7f5e4efd5187d1382a880483a79294 # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f Added SO_REUSEPORT support. It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 14:35:53 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 14:35:53 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); #else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, + sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 14:35:53 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r 04abfbb10a7f src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 14:35:53 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Friday, September 19, 2014 10:34 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Hi Valentin, I just tested the exact case you mentioned and you are right! There is a connection drop, but it got recovered really quickly. The new connections will only go to the remaining listen sockets on a round robin fashion after the reload. I will change the check of "active cpu" to "all cpu". This will make the number of listen sockets a constant as long as the system remain active. Thank you very much for your hint! I will also check the coding style again and resend the patch. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Valentin V. Bartenev Sent: Friday, September 19, 2014 9:48 AM To: nginx-devel at nginx.org Subject: Re: [Patch] SO_REUSEPORT support from master process On Friday 19 September 2014 15:52:35 Lu, Yingqi wrote: > Hi Valentin, > > Thanks very much for your email. > > Regarding to your first question, I did following test: > 1. Start Nginx > 2. Offline half of the CPU threads by "echo 0 > > /sys/devices/system/cpu/"cpu#"/online > 3. Reload Nginx and check the worker process, the number of listen > sockets is actually reduced to half. > 4. Then, I put back the offlined CPU threads back online, and reload the Nginx again. > 5. The new worker process now has 2X listen sockets as the CPU threads > doubled since the previous reload. > > Every time Nginx reloads, my understanding is it will run Ngx_init_cycle. CPU_num_check is > there. Is above testing the correct way to check if reload works? Please let me know if I > missed anything. [..] What happens if you shutdown half of your cpus again, and try to reload nginx under high load? As I understand right, with your patch it will close half of listen sockets, and all the connections that have been waiting to be accepted on these sockets will be lost. wbr, Valentin V. Bartenev _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From Yingqi.Lu at intel.com Sat Sep 20 23:03:19 2014 From: Yingqi.Lu at intel.com (Yingqi Lu) Date: Sat, 20 Sep 2014 16:03:19 -0700 Subject: [PATCH] Added SO_REUSEPORT support Message-ID: <04abfbb10a7f5e4efd51.1411254199@YLU41-MOBL2.amr.corp.intel.com> src/core/ngx_connection.c | 21 ++++++++++++++- src/core/ngx_cycle.c | 52 +++++++++++++++++++++++++++++++++---- src/core/ngx_cycle.h | 2 + src/http/ngx_http.c | 64 ++++++++++++++++++++++++---------------------- 4 files changed, 101 insertions(+), 38 deletions(-) # HG changeset patch # User Yingqi Lu # Date 1411248953 25200 # Sat Sep 20 14:35:53 2014 -0700 # Node ID 04abfbb10a7f5e4efd5187d1382a880483a79294 # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f Added SO_REUSEPORT support. It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 14:35:53 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 14:35:53 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); +#else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 14:35:53 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r 04abfbb10a7f src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 14:35:53 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; From yingqi.lu at intel.com Sat Sep 20 23:14:59 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Sat, 20 Sep 2014 23:14:59 +0000 Subject: [PATCH] Added SO_REUSEPORT support In-Reply-To: <04abfbb10a7f5e4efd51.1411254199@YLU41-MOBL2.amr.corp.intel.com> References: <04abfbb10a7f5e4efd51.1411254199@YLU41-MOBL2.amr.corp.intel.com> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37BBE84@ORSMSX113.amr.corp.intel.com> Dear All, Here is the newer version of the patch sent from ToriseHg directly. Sorry for the duplications. Please let me know if the format you see is correct and if you can apply the patch without issues. I tested here locally and it works fine. However, I am concerned about the format changes during the email delivery. Please let me know. Thanks very much to Valentin Bartenev for his valuable feedback! The 2 changes from last version are: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. By the way, if you use outlook and you see a small message on the top saying "We removed extra line breaks from this message", please click on it to "Restore line breaks". Otherwise, the code is not complete. Thanks very much! Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Yingqi Lu Sent: Saturday, September 20, 2014 4:03 PM To: nginx-devel at nginx.org Subject: [PATCH] Added SO_REUSEPORT support src/core/ngx_connection.c | 21 ++++++++++++++- src/core/ngx_cycle.c | 52 +++++++++++++++++++++++++++++++++---- src/core/ngx_cycle.h | 2 + src/http/ngx_http.c | 64 ++++++++++++++++++++++++---------------------- 4 files changed, 101 insertions(+), 38 deletions(-) # HG changeset patch # User Yingqi Lu # Date 1411248953 25200 # Sat Sep 20 14:35:53 2014 -0700 # Node ID 04abfbb10a7f5e4efd5187d1382a880483a79294 # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f Added SO_REUSEPORT support. It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 14:35:53 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 14:35:53 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); +#else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 14:35:53 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r 04abfbb10a7f src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 14:35:53 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From Yingqi.Lu at intel.com Sat Sep 20 23:28:58 2014 From: Yingqi.Lu at intel.com (Yingqi Lu) Date: Sat, 20 Sep 2014 16:28:58 -0700 Subject: [PATCH] SO_REUSEPORT support from master process In-Reply-To: References: Message-ID: src/core/ngx_connection.c | 21 ++++++++++++++- src/core/ngx_cycle.c | 52 +++++++++++++++++++++++++++++++++---- src/core/ngx_cycle.h | 2 + src/http/ngx_http.c | 64 ++++++++++++++++++++++++---------------------- 4 files changed, 101 insertions(+), 38 deletions(-) # HG changeset patch # User Yingqi Lu # Date 1411255543 25200 # Sat Sep 20 16:25:43 2014 -0700 # Node ID cf28c5af69b500ae368158df5fa4ad68f90170cc # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f SO_REUSEPORT support from master process It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r cf28c5af69b5 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 16:25:43 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r cf28c5af69b5 src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 16:25:43 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); +#else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r cf28c5af69b5 src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 16:25:43 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r cf28c5af69b5 src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 16:25:43 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; From Yingqi.Lu at intel.com Sat Sep 20 23:35:33 2014 From: Yingqi.Lu at intel.com (Yingqi Lu) Date: Sat, 20 Sep 2014 16:35:33 -0700 Subject: [PATCH] SO_REUSEPORT support from master process In-Reply-To: <[Patch] SO_REUSEPORT support from master process> References: <[Patch] SO_REUSEPORT support from master process> Message-ID: src/core/ngx_connection.c | 21 ++++++++++++++- src/core/ngx_cycle.c | 52 +++++++++++++++++++++++++++++++++---- src/core/ngx_cycle.h | 2 + src/http/ngx_http.c | 64 ++++++++++++++++++++++++---------------------- 4 files changed, 101 insertions(+), 38 deletions(-) # HG changeset patch # User Yingqi Lu # Date 1411255543 25200 # Sat Sep 20 16:25:43 2014 -0700 # Node ID cf28c5af69b500ae368158df5fa4ad68f90170cc # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f SO_REUSEPORT support from master process It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r cf28c5af69b5 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 16:25:43 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r cf28c5af69b5 src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 16:25:43 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); +#else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r cf28c5af69b5 src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 16:25:43 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r cf28c5af69b5 src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 16:25:43 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; From yingqi.lu at intel.com Sat Sep 20 23:45:29 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Sat, 20 Sep 2014 23:45:29 +0000 Subject: [Patch] SO_REUSEPORT support from master process References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <1984759.coG7FlzylE@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> <27675150.0d46n4LCFt@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BB059@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BBD5D@ORSMSX113.amr.corp.intel.com> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37BBF2E@ORSMSX113.amr.corp.intel.com> Dear All, I just sent the new patch directly from ToriseHg. Thanks again very much to Valentin Bartenev for his valuable feedback! The 2 changes from last version are: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. However, it is automatically named as "[PATCH] SO_REUSEPORT support from master process" instead of "[Patch] SO_REUSEPORT support from master process". Therefore, it does not show in this thread. The patch is available at a separate thread at http://forum.nginx.org/read.php?29,253446. Can anyone help to move the patch to the main thread and delete the duplicated copies? By the way, if you use outlook and you see a small message on the top saying "We removed extra line breaks from this message", please click on it to "Restore line breaks". Otherwise, the code shown there is not complete. The patch is tested locally, but I am concerned about the format changes during the email delivery. Please let me know if you see wrong format or cannot apply the patch. Thank you very much for your help! Yingqi -----Original Message----- From: Lu, Yingqi Sent: Saturday, September 20, 2014 4:00 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, After I sent out the patch, I noticed that the patch inserted in the email is actually with different format than the original one generated by TortoiseHg. What I did is just copying it and pasting in the email. Did I missed anything? I guess this is not the correct way to send the patch. I will try to find a way to send directly from ToriseHg. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Saturday, September 20, 2014 3:23 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, Here is another updated version of the patch. Thanks very much to Valentin Bartenev for his valuable feedback! Here are the changes in this version: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. The way we created the patch below is: we clone the code from http://hg.nginx.org/nginx, modified 4 files and then committed the changes. After that, we export the patch and attached here. Please let me know if there is anything missing here. This is the first time we prototype the patch for Nginx. Your comments and feedback are highly appreciated. Thanks, Yingqi # HG changeset patch # User Yingqi Lu # Date 1411248953 25200 # Sat Sep 20 14:35:53 2014 -0700 # Node ID 04abfbb10a7f5e4efd5187d1382a880483a79294 # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f Added SO_REUSEPORT support. It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 14:35:53 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 14:35:53 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); #else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, + sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 14:35:53 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r 04abfbb10a7f src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 14:35:53 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Friday, September 19, 2014 10:34 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Hi Valentin, I just tested the exact case you mentioned and you are right! There is a connection drop, but it got recovered really quickly. The new connections will only go to the remaining listen sockets on a round robin fashion after the reload. I will change the check of "active cpu" to "all cpu". This will make the number of listen sockets a constant as long as the system remain active. Thank you very much for your hint! I will also check the coding style again and resend the patch. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Valentin V. Bartenev Sent: Friday, September 19, 2014 9:48 AM To: nginx-devel at nginx.org Subject: Re: [Patch] SO_REUSEPORT support from master process On Friday 19 September 2014 15:52:35 Lu, Yingqi wrote: > Hi Valentin, > > Thanks very much for your email. > > Regarding to your first question, I did following test: > 1. Start Nginx > 2. Offline half of the CPU threads by "echo 0 > > /sys/devices/system/cpu/"cpu#"/online > 3. Reload Nginx and check the worker process, the number of listen > sockets is actually reduced to half. > 4. Then, I put back the offlined CPU threads back online, and reload the Nginx again. > 5. The new worker process now has 2X listen sockets as the CPU threads > doubled since the previous reload. > > Every time Nginx reloads, my understanding is it will run Ngx_init_cycle. CPU_num_check is > there. Is above testing the correct way to check if reload works? Please let me know if I > missed anything. [..] What happens if you shutdown half of your cpus again, and try to reload nginx under high load? As I understand right, with your patch it will close half of listen sockets, and all the connections that have been waiting to be accepted on these sockets will be lost. wbr, Valentin V. Bartenev _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From vbart at nginx.com Sun Sep 21 11:35:21 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Sun, 21 Sep 2014 11:35:21 +0000 Subject: [nginx] Reduced difference between the send chain functions. Message-ID: details: http://hg.nginx.org/nginx/rev/a6e83ac70af9 branches: changeset: 5853:a6e83ac70af9 user: Valentin Bartenev date: Wed Aug 13 15:11:45 2014 +0400 description: Reduced difference between the send chain functions. No functional changes. This follows the change from ad137a80919f. diffstat: src/os/unix/ngx_writev_chain.c | 10 ++++------ src/os/win32/ngx_wsasend_chain.c | 16 +++++++--------- 2 files changed, 11 insertions(+), 15 deletions(-) diffs (73 lines): diff -r 43512a33e8f2 -r a6e83ac70af9 src/os/unix/ngx_writev_chain.c --- a/src/os/unix/ngx_writev_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_writev_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -138,7 +138,7 @@ ngx_writev_chain(ngx_connection_t *c, ng c->sent += sent; - cl = ngx_handle_sent_chain(in, sent); + in = ngx_handle_sent_chain(in, sent); if (eintr) { continue; @@ -146,13 +146,11 @@ ngx_writev_chain(ngx_connection_t *c, ng if (send - prev_send != sent) { wev->ready = 0; - return cl; + return in; } - if (send >= limit || cl == NULL) { - return cl; + if (send >= limit || in == NULL) { + return in; } - - in = cl; } } diff -r 43512a33e8f2 -r a6e83ac70af9 src/os/win32/ngx_wsasend_chain.c --- a/src/os/win32/ngx_wsasend_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/win32/ngx_wsasend_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -113,18 +113,16 @@ ngx_wsasend_chain(ngx_connection_t *c, n c->sent += sent; - cl = ngx_handle_sent_chain(in, sent); + in = ngx_handle_sent_chain(in, sent); if (send - prev_send != sent) { wev->ready = 0; - return cl; + return in; } - if (send >= limit || cl == NULL) { - return cl; + if (send >= limit || in == NULL) { + return in; } - - in = cl; } } @@ -280,14 +278,14 @@ ngx_overlapped_wsasend_chain(ngx_connect c->sent += sent; - cl = ngx_handle_sent_chain(in, sent); + in = ngx_handle_sent_chain(in, sent); - if (cl) { + if (in) { wev->ready = 0; } else { wev->ready = 1; } - return cl; + return in; } From vbart at nginx.com Sun Sep 21 12:20:36 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Sun, 21 Sep 2014 12:20:36 +0000 Subject: [nginx] Generalized definitions of the number of preallocated io... Message-ID: details: http://hg.nginx.org/nginx/rev/b63e829621ab branches: changeset: 5854:b63e829621ab user: Valentin Bartenev date: Wed Aug 13 15:11:45 2014 +0400 description: Generalized definitions of the number of preallocated iovec's. No functional changes. diffstat: src/os/unix/ngx_darwin_sendfile_chain.c | 17 +++++------------ src/os/unix/ngx_freebsd_sendfile_chain.c | 17 +++++------------ src/os/unix/ngx_linux_sendfile_chain.c | 11 ++--------- src/os/unix/ngx_os.h | 7 +++++++ src/os/unix/ngx_readv_chain.c | 11 ++--------- src/os/unix/ngx_solaris_sendfilev_chain.c | 7 +------ src/os/unix/ngx_writev_chain.c | 11 ++--------- 7 files changed, 24 insertions(+), 57 deletions(-) diffs (229 lines): diff -r a6e83ac70af9 -r b63e829621ab src/os/unix/ngx_darwin_sendfile_chain.c --- a/src/os/unix/ngx_darwin_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_darwin_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -27,15 +27,6 @@ */ -#if (IOV_MAX > 64) -#define NGX_HEADERS 64 -#define NGX_TRAILERS 64 -#else -#define NGX_HEADERS IOV_MAX -#define NGX_TRAILERS IOV_MAX -#endif - - ngx_chain_t * ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { @@ -50,7 +41,9 @@ ngx_darwin_sendfile_chain(ngx_connection ngx_event_t *wev; ngx_chain_t *cl; struct sf_hdtr hdtr; - struct iovec *iov, headers[NGX_HEADERS], trailers[NGX_TRAILERS]; + struct iovec *iov; + struct iovec headers[NGX_IOVS_PREALLOCATE]; + struct iovec trailers[NGX_IOVS_PREALLOCATE]; wev = c->write; @@ -79,12 +72,12 @@ ngx_darwin_sendfile_chain(ngx_connection header.elts = headers; header.size = sizeof(struct iovec); - header.nalloc = NGX_HEADERS; + header.nalloc = NGX_IOVS_PREALLOCATE; header.pool = c->pool; trailer.elts = trailers; trailer.size = sizeof(struct iovec); - trailer.nalloc = NGX_TRAILERS; + trailer.nalloc = NGX_IOVS_PREALLOCATE; trailer.pool = c->pool; for ( ;; ) { diff -r a6e83ac70af9 -r b63e829621ab src/os/unix/ngx_freebsd_sendfile_chain.c --- a/src/os/unix/ngx_freebsd_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -29,15 +29,6 @@ */ -#if (IOV_MAX > 64) -#define NGX_HEADERS 64 -#define NGX_TRAILERS 64 -#else -#define NGX_HEADERS IOV_MAX -#define NGX_TRAILERS IOV_MAX -#endif - - ngx_chain_t * ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { @@ -52,7 +43,9 @@ ngx_freebsd_sendfile_chain(ngx_connectio ngx_event_t *wev; ngx_chain_t *cl; struct sf_hdtr hdtr; - struct iovec *iov, headers[NGX_HEADERS], trailers[NGX_TRAILERS]; + struct iovec *iov; + struct iovec headers[NGX_IOVS_PREALLOCATE]; + struct iovec trailers[NGX_IOVS_PREALLOCATE]; wev = c->write; @@ -83,12 +76,12 @@ ngx_freebsd_sendfile_chain(ngx_connectio header.elts = headers; header.size = sizeof(struct iovec); - header.nalloc = NGX_HEADERS; + header.nalloc = NGX_IOVS_PREALLOCATE; header.pool = c->pool; trailer.elts = trailers; trailer.size = sizeof(struct iovec); - trailer.nalloc = NGX_TRAILERS; + trailer.nalloc = NGX_IOVS_PREALLOCATE; trailer.pool = c->pool; for ( ;; ) { diff -r a6e83ac70af9 -r b63e829621ab src/os/unix/ngx_linux_sendfile_chain.c --- a/src/os/unix/ngx_linux_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_linux_sendfile_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -27,13 +27,6 @@ #define NGX_SENDFILE_MAXSIZE 2147483647L -#if (IOV_MAX > 64) -#define NGX_HEADERS 64 -#else -#define NGX_HEADERS IOV_MAX -#endif - - ngx_chain_t * ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { @@ -47,7 +40,7 @@ ngx_linux_sendfile_chain(ngx_connection_ ngx_array_t header; ngx_event_t *wev; ngx_chain_t *cl; - struct iovec *iov, headers[NGX_HEADERS]; + struct iovec *iov, headers[NGX_IOVS_PREALLOCATE]; #if (NGX_HAVE_SENDFILE64) off_t offset; #else @@ -72,7 +65,7 @@ ngx_linux_sendfile_chain(ngx_connection_ header.elts = headers; header.size = sizeof(struct iovec); - header.nalloc = NGX_HEADERS; + header.nalloc = NGX_IOVS_PREALLOCATE; header.pool = c->pool; for ( ;; ) { diff -r a6e83ac70af9 -r b63e829621ab src/os/unix/ngx_os.h --- a/src/os/unix/ngx_os.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_os.h Wed Aug 13 15:11:45 2014 +0400 @@ -56,6 +56,13 @@ ngx_chain_t *ngx_aio_write_chain(ngx_con #endif +#if (IOV_MAX > 64) +#define NGX_IOVS_PREALLOCATE 64 +#else +#define NGX_IOVS_PREALLOCATE IOV_MAX +#endif + + extern ngx_os_io_t ngx_os_io; extern ngx_int_t ngx_ncpu; extern ngx_int_t ngx_max_sockets; diff -r a6e83ac70af9 -r b63e829621ab src/os/unix/ngx_readv_chain.c --- a/src/os/unix/ngx_readv_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_readv_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -10,13 +10,6 @@ #include -#if (IOV_MAX > 64) -#define NGX_IOVS 64 -#else -#define NGX_IOVS IOV_MAX -#endif - - ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain) { @@ -25,7 +18,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx ngx_err_t err; ngx_array_t vec; ngx_event_t *rev; - struct iovec *iov, iovs[NGX_IOVS]; + struct iovec *iov, iovs[NGX_IOVS_PREALLOCATE]; rev = c->read; @@ -67,7 +60,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx vec.elts = iovs; vec.nelts = 0; vec.size = sizeof(struct iovec); - vec.nalloc = NGX_IOVS; + vec.nalloc = NGX_IOVS_PREALLOCATE; vec.pool = c->pool; /* coalesce the neighbouring bufs */ diff -r a6e83ac70af9 -r b63e829621ab src/os/unix/ngx_solaris_sendfilev_chain.c --- a/src/os/unix/ngx_solaris_sendfilev_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_solaris_sendfilev_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -35,12 +35,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain #endif -#if (IOV_MAX > 64) -#define NGX_SENDFILEVECS 64 -#else -#define NGX_SENDFILEVECS IOV_MAX -#endif - +#define NGX_SENDFILEVECS NGX_IOVS_PREALLOCATE ngx_chain_t * diff -r a6e83ac70af9 -r b63e829621ab src/os/unix/ngx_writev_chain.c --- a/src/os/unix/ngx_writev_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_writev_chain.c Wed Aug 13 15:11:45 2014 +0400 @@ -10,13 +10,6 @@ #include -#if (IOV_MAX > 64) -#define NGX_IOVS 64 -#else -#define NGX_IOVS IOV_MAX -#endif - - ngx_chain_t * ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { @@ -28,7 +21,7 @@ ngx_writev_chain(ngx_connection_t *c, ng ngx_array_t vec; ngx_chain_t *cl; ngx_event_t *wev; - struct iovec *iov, iovs[NGX_IOVS]; + struct iovec *iov, iovs[NGX_IOVS_PREALLOCATE]; wev = c->write; @@ -57,7 +50,7 @@ ngx_writev_chain(ngx_connection_t *c, ng vec.elts = iovs; vec.size = sizeof(struct iovec); - vec.nalloc = NGX_IOVS; + vec.nalloc = NGX_IOVS_PREALLOCATE; vec.pool = c->pool; for ( ;; ) { From richard at fussenegger.info Mon Sep 22 11:39:43 2014 From: richard at fussenegger.info (Richard Fussenegger, BSc) Date: Mon, 22 Sep 2014 13:39:43 +0200 Subject: Session Ticket Rotation Message-ID: <54200A7F.3030408@fussenegger.info> I'd like to implement built-in session ticket rotation. I know that it this was discussed before but it was never implemented. Right now a custom external ticket key system is supported. Admins with single installations and not enough knowledge about the topic are left with keys that are valid for the complete lifetime nginx is running. I thought about a rotation scheme that introduces a single new configuration variable (e.g. ssl_session_ticket_key_rotation or ssl_session_ticket_key_interval) that defines the interval in which the ticket key should be rotated. I think a default setting of 24 hours would be enough for most installations. One key is always used for decryption and encryption and the most recently expired key is only used for decryption. This means that we have a de- and encrypt key for 24 hours and a decrypt key for 48 hours with the default setting. The best place for this would be in ngx_event_openssl.c#2640 after the if (paths == NULL) by checking if the aforementioned variable is set (default) and if the currently used key has expired. If it hasn't return NGX_OK (as it is now) otherwise copy current key to old key and generate new key. Unsolved questions: Implementation: Currently OpenSSL is generating and keeping track of the key (this would still be the case if the newly introduced setting is set to "0"). We'd have to introduce two variables - one for the current and one for the old key plus timestamps - and let OpenSSL know about the key before attempting to decrypt sent session data. Per server keys: CVE-2014-3616 from Antoine Delignat-Lavaud was dealing with this. I have to review his patches but I guess that the variables have to be arrays and we'd have to keep different current and old keys per server. But what if one wants to share the sessions among servers? I guess this has to depend on the location the configuration was set. As I said, I have to review his patches to gather more knowledge for this problem. Restarts: Apache is storing the key to file, that would allow the process to read the last used keys. But of course this isn't very secure and we may need an additional setting to define the path where these intermediate keys should be stored. Of course we could also simply ignore restarts, as it is now. But we'd loose the ability to decrypt old sessions tickets. Any thoughts from your side are highly appreciated. Richard From kyprizel at gmail.com Mon Sep 22 12:23:52 2014 From: kyprizel at gmail.com (kyprizel) Date: Mon, 22 Sep 2014 16:23:52 +0400 Subject: Session Ticket Rotation In-Reply-To: <54200A7F.3030408@fussenegger.info> References: <54200A7F.3030408@fussenegger.info> Message-ID: What about sharing keys b/w the physical instances? On Mon, Sep 22, 2014 at 3:39 PM, Richard Fussenegger, BSc < richard at fussenegger.info> wrote: > I'd like to implement built-in session ticket rotation. I know that it > this was discussed before but it was never implemented. Right now a custom > external ticket key system is supported. Admins with single installations > and not enough knowledge about the topic are left with keys that are valid > for the complete lifetime nginx is running. > > I thought about a rotation scheme that introduces a single new > configuration variable (e.g. ssl_session_ticket_key_rotation or > ssl_session_ticket_key_interval) that defines the interval in which the > ticket key should be rotated. I think a default setting of 24 hours would > be enough for most installations. One key is always used for decryption and > encryption and the most recently expired key is only used for decryption. > This means that we have a de- and encrypt key for 24 hours and a decrypt > key for 48 hours with the default setting. The best place for this would be > in ngx_event_openssl.c#2640 after the if (paths == NULL) by checking if the > aforementioned variable is set (default) and if the currently used key has > expired. If it hasn't return NGX_OK (as it is now) otherwise copy current > key to old key and generate new key. > > Unsolved questions: > > Implementation: Currently OpenSSL is generating and keeping track of the > key (this would still be the case if the newly introduced setting is set to > "0"). We'd have to introduce two variables - one for the current and one > for the old key plus timestamps - and let OpenSSL know about the key before > attempting to decrypt sent session data. > > Per server keys: CVE-2014-3616 from Antoine Delignat-Lavaud was dealing > with this. I have to review his patches but I guess that the variables have > to be arrays and we'd have to keep different current and old keys per > server. But what if one wants to share the sessions among servers? I guess > this has to depend on the location the configuration was set. As I said, I > have to review his patches to gather more knowledge for this problem. > > Restarts: Apache is storing the key to file, that would allow the process > to read the last used keys. But of course this isn't very secure and we may > need an additional setting to define the path where these intermediate keys > should be stored. Of course we could also simply ignore restarts, as it is > now. But we'd loose the ability to decrypt old sessions tickets. > > Any thoughts from your side are highly appreciated. > > Richard > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From richard at fussenegger.info Mon Sep 22 12:26:24 2014 From: richard at fussenegger.info (Richard Fussenegger, BSc) Date: Mon, 22 Sep 2014 14:26:24 +0200 Subject: Session Ticket Rotation In-Reply-To: References: <54200A7F.3030408@fussenegger.info> Message-ID: <54201570.6030304@fussenegger.info> We already have the file based ticket keys. They require an external rotation, but I think that this requirement is okay for admins that already have to think of an exchange between several instances. Richard On 9/22/2014 2:23 PM, kyprizel wrote: > What about sharing keys b/w the physical instances? > > On Mon, Sep 22, 2014 at 3:39 PM, Richard Fussenegger, BSc > > wrote: > > I'd like to implement built-in session ticket rotation. I know > that it this was discussed before but it was never implemented. > Right now a custom external ticket key system is supported. Admins > with single installations and not enough knowledge about the topic > are left with keys that are valid for the complete lifetime nginx > is running. > > I thought about a rotation scheme that introduces a single new > configuration variable (e.g. ssl_session_ticket_key_rotation or > ssl_session_ticket_key_interval) that defines the interval in > which the ticket key should be rotated. I think a default setting > of 24 hours would be enough for most installations. One key is > always used for decryption and encryption and the most recently > expired key is only used for decryption. This means that we have a > de- and encrypt key for 24 hours and a decrypt key for 48 hours > with the default setting. The best place for this would be in > ngx_event_openssl.c#2640 after the if (paths == NULL) by checking > if the aforementioned variable is set (default) and if the > currently used key has expired. If it hasn't return NGX_OK (as it > is now) otherwise copy current key to old key and generate new key. > > Unsolved questions: > > Implementation: Currently OpenSSL is generating and keeping track > of the key (this would still be the case if the newly introduced > setting is set to "0"). We'd have to introduce two variables - one > for the current and one for the old key plus timestamps - and let > OpenSSL know about the key before attempting to decrypt sent > session data. > > Per server keys: CVE-2014-3616 from Antoine Delignat-Lavaud was > dealing with this. I have to review his patches but I guess that > the variables have to be arrays and we'd have to keep different > current and old keys per server. But what if one wants to share > the sessions among servers? I guess this has to depend on the > location the configuration was set. As I said, I have to review > his patches to gather more knowledge for this problem. > > Restarts: Apache is storing the key to file, that would allow the > process to read the last used keys. But of course this isn't very > secure and we may need an additional setting to define the path > where these intermediate keys should be stored. Of course we could > also simply ignore restarts, as it is now. But we'd loose the > ability to decrypt old sessions tickets. > > Any thoughts from your side are highly appreciated. > > Richard > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Sep 22 12:38:09 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 22 Sep 2014 16:38:09 +0400 Subject: Session Ticket Rotation In-Reply-To: <54200A7F.3030408@fussenegger.info> References: <54200A7F.3030408@fussenegger.info> Message-ID: <20140922123809.GE80160@mdounin.ru> Hello! On Mon, Sep 22, 2014 at 01:39:43PM +0200, Richard Fussenegger, BSc wrote: > I'd like to implement built-in session ticket rotation. I know that it this > was discussed before but it was never implemented. Right now a custom > external ticket key system is supported. Admins with single installations > and not enough knowledge about the topic are left with keys that are valid > for the complete lifetime nginx is running. That's not really true: ticket keys are regenerated on each configuration reload. > I thought about a rotation scheme that introduces a single new configuration > variable (e.g. ssl_session_ticket_key_rotation or > ssl_session_ticket_key_interval) that defines the interval in which the > ticket key should be rotated. I think a default setting of 24 hours would be > enough for most installations. One key is always used for decryption and > encryption and the most recently expired key is only used for decryption. > This means that we have a de- and encrypt key for 24 hours and a decrypt key > for 48 hours with the default setting. The best place for this would be in > ngx_event_openssl.c#2640 after the if (paths == NULL) by checking if the > aforementioned variable is set (default) and if the currently used key has > expired. If it hasn't return NGX_OK (as it is now) otherwise copy current > key to old key and generate new key. Checking expiration in the ngx_ssl_session_ticket_keys() function doesn't make sense: creating new SSL context means new random keys. So if the ngx_ssl_session_ticket_keys() is called, which only happens while reading a configuration, we currently have a new key anyway. > Unsolved questions: > > Implementation: Currently OpenSSL is generating and keeping track of the key > (this would still be the case if the newly introduced setting is set to > "0"). We'd have to introduce two variables - one for the current and one for > the old key plus timestamps - and let OpenSSL know about the key before > attempting to decrypt sent session data. The main problem here is how to share keys between worker processes, to ensure different workers will be able to decrypt tickets. So automatic rotation of ticket keys will likely require shared SSL session cache to be configured as well, and using a SSL session cache to store ticket keys. > Per server keys: CVE-2014-3616 from Antoine Delignat-Lavaud was dealing with > this. I have to review his patches but I guess that the variables have to be > arrays and we'd have to keep different current and old keys per server. But > what if one wants to share the sessions among servers? I guess this has to > depend on the location the configuration was set. As I said, I have to > review his patches to gather more knowledge for this problem. As of now, session tickets can't be decrypted in other server{} blocks (unless ssl_session_ticket_key is explicitly used to set keys). I don't see any reasons to change this behaviour. > Restarts: Apache is storing the key to file, that would allow the process to > read the last used keys. But of course this isn't very secure and we may > need an additional setting to define the path where these intermediate keys > should be stored. Of course we could also simply ignore restarts, as it is > now. But we'd loose the ability to decrypt old sessions tickets. Current behaviour is believed to be good enough. -- Maxim Dounin http://nginx.org/ From richard at fussenegger.info Mon Sep 22 13:49:26 2014 From: richard at fussenegger.info (Richard Fussenegger, BSc) Date: Mon, 22 Sep 2014 15:49:26 +0200 Subject: Session Ticket Rotation In-Reply-To: <20140922123809.GE80160@mdounin.ru> References: <54200A7F.3030408@fussenegger.info> <20140922123809.GE80160@mdounin.ru> Message-ID: <542028E6.10207@fussenegger.info> On 9/22/2014 2:38 PM, Maxim Dounin wrote: > Hello! > > On Mon, Sep 22, 2014 at 01:39:43PM +0200, Richard Fussenegger, BSc wrote: > >> I'd like to implement built-in session ticket rotation. I know that it this >> was discussed before but it was never implemented. Right now a custom >> external ticket key system is supported. Admins with single installations >> and not enough knowledge about the topic are left with keys that are valid >> for the complete lifetime nginx is running. > That's not really true: ticket keys are regenerated on each > configuration reload. Exactly but nginx isn't able to decrypt older ticket keys and admins might not be aware of this and will never implement the required cron job. >> I thought about a rotation scheme that introduces a single new configuration >> variable (e.g. ssl_session_ticket_key_rotation or >> ssl_session_ticket_key_interval) that defines the interval in which the >> ticket key should be rotated. I think a default setting of 24 hours would be >> enough for most installations. One key is always used for decryption and >> encryption and the most recently expired key is only used for decryption. >> This means that we have a de- and encrypt key for 24 hours and a decrypt key >> for 48 hours with the default setting. The best place for this would be in >> ngx_event_openssl.c#2640 after the if (paths == NULL) by checking if the >> aforementioned variable is set (default) and if the currently used key has >> expired. If it hasn't return NGX_OK (as it is now) otherwise copy current >> key to old key and generate new key. > Checking expiration in the ngx_ssl_session_ticket_keys() function > doesn't make sense: creating new SSL context means new random > keys. So if the ngx_ssl_session_ticket_keys() is called, which > only happens while reading a configuration, we currently have > a new key anyway. Thanks for the insight on this, I'll investigate the source further unless you have an idea (or pointer for me) where it should go. >> Unsolved questions: >> >> Implementation: Currently OpenSSL is generating and keeping track of the key >> (this would still be the case if the newly introduced setting is set to >> "0"). We'd have to introduce two variables - one for the current and one for >> the old key plus timestamps - and let OpenSSL know about the key before >> attempting to decrypt sent session data. > The main problem here is how to share keys between worker > processes, to ensure different workers will be able to decrypt > tickets. So automatic rotation of ticket keys will likely require > shared SSL session cache to be configured as well, and using a SSL > session cache to store ticket keys. Having the session cache as a requirement for ticket rotation isn't a problem for HTTP context. Not all major browsers support tickets and a configuration that relies only on tickets doesn't make sense. Of course it's a problem for the default configuration which is using tickets only. >> Per server keys: CVE-2014-3616 from Antoine Delignat-Lavaud was dealing with >> this. I have to review his patches but I guess that the variables have to be >> arrays and we'd have to keep different current and old keys per server. But >> what if one wants to share the sessions among servers? I guess this has to >> depend on the location the configuration was set. As I said, I have to >> review his patches to gather more knowledge for this problem. > As of now, session tickets can't be decrypted in other server{} > blocks (unless ssl_session_ticket_key is explicitly used to set > keys). I don't see any reasons to change this behaviour. Me neither and it's great if it's already working this way. >> Restarts: Apache is storing the key to file, that would allow the process to >> read the last used keys. But of course this isn't very secure and we may >> need an additional setting to define the path where these intermediate keys >> should be stored. Of course we could also simply ignore restarts, as it is >> now. But we'd loose the ability to decrypt old sessions tickets. > Current behaviour is believed to be good enough. I think so too, losing the ability to decrypt old tickets isn't a big deal but storing keys to files would be in my book. Richard From vbart at nginx.com Mon Sep 22 15:49:04 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 22 Sep 2014 15:49:04 +0000 Subject: [nginx] Removed duplicate initialization of the "rev" variable. Message-ID: details: http://hg.nginx.org/nginx/rev/a0a14319968b branches: changeset: 5855:a0a14319968b user: Valentin Bartenev date: Mon Sep 22 19:48:23 2014 +0400 description: Removed duplicate initialization of the "rev" variable. diffstat: src/os/unix/ngx_readv_chain.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diffs (12 lines): diff -r b63e829621ab -r a0a14319968b src/os/unix/ngx_readv_chain.c --- a/src/os/unix/ngx_readv_chain.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/os/unix/ngx_readv_chain.c Mon Sep 22 19:48:23 2014 +0400 @@ -91,8 +91,6 @@ ngx_readv_chain(ngx_connection_t *c, ngx ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "readv: %d, last:%d", vec.nelts, iov->iov_len); - rev = c->read; - do { n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts); From s7v7nislands at gmail.com Tue Sep 23 02:00:06 2014 From: s7v7nislands at gmail.com (XiaoBing Jiang) Date: Tue, 23 Sep 2014 10:00:06 +0800 Subject: [PATCH] Fix typo Message-ID: # HG changeset patch # User s7v7nislands # Date 1411437071 -28800 # Tue Sep 23 09:51:11 2014 +0800 # Branch fix_typo # Node ID 34a7a94c3dab57fd302fe731b013d90be4354efe # Parent a0a14319968b2d978d306f5a91e81e9e4e3e7ce6 Fix typo diff -r a0a14319968b -r 34a7a94c3dab src/event/ngx_event_mutex.c --- a/src/event/ngx_event_mutex.c Mon Sep 22 19:48:23 2014 +0400 +++ b/src/event/ngx_event_mutex.c Tue Sep 23 09:51:11 2014 +0800 @@ -28,7 +28,7 @@ m->last = ev; ev->next = NULL; -#if (NGX_THREADS0) +#if (NGX_THREADS) ev->light = 1; #endif From vbart at nginx.com Tue Sep 23 08:04:23 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Tue, 23 Sep 2014 12:04:23 +0400 Subject: [PATCH] Fix typo In-Reply-To: References: Message-ID: <2742311.119GAPK7M2@vbart-laptop> On Tuesday 23 September 2014 10:00:06 XiaoBing Jiang wrote: > # HG changeset patch > # User s7v7nislands > # Date 1411437071 -28800 > # Tue Sep 23 09:51:11 2014 +0800 > # Branch fix_typo > # Node ID 34a7a94c3dab57fd302fe731b013d90be4354efe > # Parent a0a14319968b2d978d306f5a91e81e9e4e3e7ce6 > Fix typo > > diff -r a0a14319968b -r 34a7a94c3dab src/event/ngx_event_mutex.c > --- a/src/event/ngx_event_mutex.c Mon Sep 22 19:48:23 2014 +0400 > +++ b/src/event/ngx_event_mutex.c Tue Sep 23 09:51:11 2014 +0800 > @@ -28,7 +28,7 @@ > m->last = ev; > ev->next = NULL; > > -#if (NGX_THREADS0) > +#if (NGX_THREADS) > ev->light = 1; > #endif > No, thanks, that's not a typo. wbr, Valentin V. Bartenev From yingqi.lu at intel.com Tue Sep 23 15:35:47 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Tue, 23 Sep 2014 15:35:47 +0000 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <9ACD5B67AAC5594CB6268234CF29CF9AA37BBF2E@ORSMSX113.amr.corp.intel.com> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <1984759.coG7FlzylE@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> <27675150.0d46n4LCFt@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BB059@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BBD5D@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BBF2E@ORSMSX113.amr.corp.intel.com> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37BD313@ORSMSX113.amr.corp.intel.com> I am wondering if there are any more feedback/comments/concerns? Also, does the format look OK to all of you? Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Saturday, September 20, 2014 4:45 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, I just sent the new patch directly from ToriseHg. Thanks again very much to Valentin Bartenev for his valuable feedback! The 2 changes from last version are: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. However, it is automatically named as "[PATCH] SO_REUSEPORT support from master process" instead of "[Patch] SO_REUSEPORT support from master process". Therefore, it does not show in this thread. The patch is available at a separate thread at http://forum.nginx.org/read.php?29,253446. Can anyone help to move the patch to the main thread and delete the duplicated copies? By the way, if you use outlook and you see a small message on the top saying "We removed extra line breaks from this message", please click on it to "Restore line breaks". Otherwise, the code shown there is not complete. The patch is tested locally, but I am concerned about the format changes during the email delivery. Please let me know if you see wrong format or cannot apply the patch. Thank you very much for your help! Yingqi -----Original Message----- From: Lu, Yingqi Sent: Saturday, September 20, 2014 4:00 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, After I sent out the patch, I noticed that the patch inserted in the email is actually with different format than the original one generated by TortoiseHg. What I did is just copying it and pasting in the email. Did I missed anything? I guess this is not the correct way to send the patch. I will try to find a way to send directly from ToriseHg. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Saturday, September 20, 2014 3:23 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, Here is another updated version of the patch. Thanks very much to Valentin Bartenev for his valuable feedback! Here are the changes in this version: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. The way we created the patch below is: we clone the code from http://hg.nginx.org/nginx, modified 4 files and then committed the changes. After that, we export the patch and attached here. Please let me know if there is anything missing here. This is the first time we prototype the patch for Nginx. Your comments and feedback are highly appreciated. Thanks, Yingqi # HG changeset patch # User Yingqi Lu # Date 1411248953 25200 # Sat Sep 20 14:35:53 2014 -0700 # Node ID 04abfbb10a7f5e4efd5187d1382a880483a79294 # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f Added SO_REUSEPORT support. It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 14:35:53 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 14:35:53 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); #else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, + sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 14:35:53 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r 04abfbb10a7f src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 14:35:53 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Friday, September 19, 2014 10:34 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Hi Valentin, I just tested the exact case you mentioned and you are right! There is a connection drop, but it got recovered really quickly. The new connections will only go to the remaining listen sockets on a round robin fashion after the reload. I will change the check of "active cpu" to "all cpu". This will make the number of listen sockets a constant as long as the system remain active. Thank you very much for your hint! I will also check the coding style again and resend the patch. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Valentin V. Bartenev Sent: Friday, September 19, 2014 9:48 AM To: nginx-devel at nginx.org Subject: Re: [Patch] SO_REUSEPORT support from master process On Friday 19 September 2014 15:52:35 Lu, Yingqi wrote: > Hi Valentin, > > Thanks very much for your email. > > Regarding to your first question, I did following test: > 1. Start Nginx > 2. Offline half of the CPU threads by "echo 0 > > /sys/devices/system/cpu/"cpu#"/online > 3. Reload Nginx and check the worker process, the number of listen > sockets is actually reduced to half. > 4. Then, I put back the offlined CPU threads back online, and reload the Nginx again. > 5. The new worker process now has 2X listen sockets as the CPU threads > doubled since the previous reload. > > Every time Nginx reloads, my understanding is it will run Ngx_init_cycle. CPU_num_check is > there. Is above testing the correct way to check if reload works? Please let me know if I > missed anything. [..] What happens if you shutdown half of your cpus again, and try to reload nginx under high load? As I understand right, with your patch it will close half of listen sockets, and all the connections that have been waiting to be accepted on these sockets will be lost. wbr, Valentin V. Bartenev _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From yingqi.lu at intel.com Tue Sep 23 15:46:34 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Tue, 23 Sep 2014 15:46:34 +0000 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <9ACD5B67AAC5594CB6268234CF29CF9AA37BD313@ORSMSX113.amr.corp.intel.com> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <1984759.coG7FlzylE@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> <27675150.0d46n4LCFt@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BB059@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BBD5D@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BBF2E@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BD313@ORSMSX113.amr.corp.intel.com> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37BD365@ORSMSX113.amr.corp.intel.com> Forgot to ask in my last email: can anyone please help to move the patch from http://forum.nginx.org/read.php?29,253446 to this main thread? Thanks very much for your help! Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Tuesday, September 23, 2014 8:36 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process I am wondering if there are any more feedback/comments/concerns? Also, does the format look OK to all of you? Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Saturday, September 20, 2014 4:45 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, I just sent the new patch directly from ToriseHg. Thanks again very much to Valentin Bartenev for his valuable feedback! The 2 changes from last version are: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. However, it is automatically named as "[PATCH] SO_REUSEPORT support from master process" instead of "[Patch] SO_REUSEPORT support from master process". Therefore, it does not show in this thread. The patch is available at a separate thread at http://forum.nginx.org/read.php?29,253446. Can anyone help to move the patch to the main thread and delete the duplicated copies? By the way, if you use outlook and you see a small message on the top saying "We removed extra line breaks from this message", please click on it to "Restore line breaks". Otherwise, the code shown there is not complete. The patch is tested locally, but I am concerned about the format changes during the email delivery. Please let me know if you see wrong format or cannot apply the patch. Thank you very much for your help! Yingqi -----Original Message----- From: Lu, Yingqi Sent: Saturday, September 20, 2014 4:00 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, After I sent out the patch, I noticed that the patch inserted in the email is actually with different format than the original one generated by TortoiseHg. What I did is just copying it and pasting in the email. Did I missed anything? I guess this is not the correct way to send the patch. I will try to find a way to send directly from ToriseHg. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Saturday, September 20, 2014 3:23 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, Here is another updated version of the patch. Thanks very much to Valentin Bartenev for his valuable feedback! Here are the changes in this version: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. The way we created the patch below is: we clone the code from http://hg.nginx.org/nginx, modified 4 files and then committed the changes. After that, we export the patch and attached here. Please let me know if there is anything missing here. This is the first time we prototype the patch for Nginx. Your comments and feedback are highly appreciated. Thanks, Yingqi # HG changeset patch # User Yingqi Lu # Date 1411248953 25200 # Sat Sep 20 14:35:53 2014 -0700 # Node ID 04abfbb10a7f5e4efd5187d1382a880483a79294 # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f Added SO_REUSEPORT support. It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 14:35:53 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 14:35:53 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); #else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, + sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 14:35:53 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r 04abfbb10a7f src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 14:35:53 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Friday, September 19, 2014 10:34 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Hi Valentin, I just tested the exact case you mentioned and you are right! There is a connection drop, but it got recovered really quickly. The new connections will only go to the remaining listen sockets on a round robin fashion after the reload. I will change the check of "active cpu" to "all cpu". This will make the number of listen sockets a constant as long as the system remain active. Thank you very much for your hint! I will also check the coding style again and resend the patch. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Valentin V. Bartenev Sent: Friday, September 19, 2014 9:48 AM To: nginx-devel at nginx.org Subject: Re: [Patch] SO_REUSEPORT support from master process On Friday 19 September 2014 15:52:35 Lu, Yingqi wrote: > Hi Valentin, > > Thanks very much for your email. > > Regarding to your first question, I did following test: > 1. Start Nginx > 2. Offline half of the CPU threads by "echo 0 > > /sys/devices/system/cpu/"cpu#"/online > 3. Reload Nginx and check the worker process, the number of listen > sockets is actually reduced to half. > 4. Then, I put back the offlined CPU threads back online, and reload the Nginx again. > 5. The new worker process now has 2X listen sockets as the CPU threads > doubled since the previous reload. > > Every time Nginx reloads, my understanding is it will run Ngx_init_cycle. CPU_num_check is > there. Is above testing the correct way to check if reload works? Please let me know if I > missed anything. [..] What happens if you shutdown half of your cpus again, and try to reload nginx under high load? As I understand right, with your patch it will close half of listen sockets, and all the connections that have been waiting to be accepted on these sockets will be lost. wbr, Valentin V. Bartenev _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From ru at nginx.com Wed Sep 24 05:56:51 2014 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 24 Sep 2014 05:56:51 +0000 Subject: [nginx] Avoided to add duplicate hash key in ngx_http_types_slot(). Message-ID: details: http://hg.nginx.org/nginx/rev/1b8459a53e4b branches: changeset: 5856:1b8459a53e4b user: Gu Feng date: Wed Sep 17 22:52:02 2014 +0800 description: Avoided to add duplicate hash key in ngx_http_types_slot(). diffstat: src/http/ngx_http.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diffs (23 lines): diff -r a0a14319968b -r 1b8459a53e4b src/http/ngx_http.c --- a/src/http/ngx_http.c Mon Sep 22 19:48:23 2014 +0400 +++ b/src/http/ngx_http.c Wed Sep 17 22:52:02 2014 +0800 @@ -2005,7 +2005,7 @@ ngx_http_types_slot(ngx_conf_t *cf, ngx_ if (ngx_strcmp(value[i].data, type[n].key.data) == 0) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate MIME type \"%V\"", &value[i]); - continue; + goto next; } } @@ -2017,6 +2017,10 @@ ngx_http_types_slot(ngx_conf_t *cf, ngx_ type->key = value[i]; type->key_hash = hash; type->value = (void *) 4; + + next: + + continue; } return NGX_CONF_OK; From ru at nginx.com Wed Sep 24 05:57:45 2014 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 24 Sep 2014 09:57:45 +0400 Subject: [PATCH]Avoided to add duplicate hash key in ngx_http_types_slot(). In-Reply-To: References: Message-ID: <20140924055745.GO87738@lo0.su> On Wed, Sep 17, 2014 at 11:08:39PM +0800, flygoast wrote: > # HG changeset patch > # User Gu Feng > # Date 1410965522 -28800 > # Wed Sep 17 22:52:02 2014 +0800 > # Node ID 5af55dbe8c301357e021bfefb99f0c359cfde7fd > # Parent cda4fcb9294c8f5a0998e7c5d57c5143457db766 > Avoided to add duplicate hash key in ngx_http_types_slot(). > > > diff -r cda4fcb9294c -r 5af55dbe8c30 src/http/ngx_http.c > --- a/src/http/ngx_http.cTue Sep 16 21:12:51 2014 +0400 > +++ b/src/http/ngx_http.cWed Sep 17 22:52:02 2014 +0800 > @@ -2005,7 +2005,7 @@ ngx_http_types_slot(ngx_conf_t *cf, ngx_ > if (ngx_strcmp(value[i].data, type[n].key.data) == 0) { > ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > "duplicate MIME type \"%V\"", &value[i]); > - continue; > + goto next; > } > } > > @@ -2017,6 +2017,10 @@ ngx_http_types_slot(ngx_conf_t *cf, ngx_ > type->key = value[i]; > type->key_hash = hash; > type->value = (void *) 4; > + > + next: > + > + continue; > } > > return NGX_CONF_OK; > Committed, thanks! From vl at nginx.com Wed Sep 24 16:03:45 2014 From: vl at nginx.com (Homutov Vladimir) Date: Wed, 24 Sep 2014 16:03:45 +0000 Subject: [nginx] Syslog: enabled logging of send errors. Message-ID: details: http://hg.nginx.org/nginx/rev/2cb5275bf5e7 branches: changeset: 5857:2cb5275bf5e7 user: Vladimir Homutov date: Mon Sep 01 17:55:07 2014 +0400 description: Syslog: enabled logging of send errors. The ngx_cycle->log is used when sending the message. This allows to log syslog send errors in another log. Logging to syslog after its cleanup handler has been executed was prohibited. Previously, this was possible from ngx_destroy_pool(), which resulted in error messages caused by attempts to write into the closed socket. The "processing" flag is renamed to "busy" to better match its semantics. diffstat: src/core/ngx_syslog.c | 13 +++++++++---- src/core/ngx_syslog.h | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diffs (66 lines): diff -r 1b8459a53e4b -r 2cb5275bf5e7 src/core/ngx_syslog.c --- a/src/core/ngx_syslog.c Wed Sep 17 22:52:02 2014 +0800 +++ b/src/core/ngx_syslog.c Mon Sep 01 17:55:07 2014 +0400 @@ -234,11 +234,11 @@ ngx_syslog_writer(ngx_log_t *log, ngx_ui peer = log->wdata; - if (peer->processing) { + if (peer->busy) { return; } - peer->processing = 1; + peer->busy = 1; peer->severity = level - 1; p = ngx_syslog_add_header(peer, msg); @@ -254,7 +254,7 @@ ngx_syslog_writer(ngx_log_t *log, ngx_ui (void) ngx_syslog_send(peer, msg, p - msg); - peer->processing = 0; + peer->busy = 0; } @@ -267,6 +267,9 @@ ngx_syslog_send(ngx_syslog_peer_t *peer, } } + /* log syslog socket events with valid log */ + peer->conn.log = ngx_cycle->log; + if (ngx_send) { return ngx_send(&peer->conn, buf, len); @@ -285,7 +288,6 @@ ngx_syslog_init_peer(ngx_syslog_peer_t * peer->conn.read = &ngx_syslog_dummy_event; peer->conn.write = &ngx_syslog_dummy_event; - peer->conn.log = &ngx_syslog_dummy_log; ngx_syslog_dummy_event.log = &ngx_syslog_dummy_log; @@ -339,6 +341,9 @@ ngx_syslog_cleanup(void *data) { ngx_syslog_peer_t *peer = data; + /* prevents further use of this peer */ + peer->busy = 1; + if (ngx_close_socket(peer->conn.fd) == -1) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno, ngx_close_socket_n " failed"); diff -r 1b8459a53e4b -r 2cb5275bf5e7 src/core/ngx_syslog.h --- a/src/core/ngx_syslog.h Wed Sep 17 22:52:02 2014 +0800 +++ b/src/core/ngx_syslog.h Mon Sep 01 17:55:07 2014 +0400 @@ -16,7 +16,7 @@ typedef struct { ngx_addr_t server; ngx_connection_t conn; - ngx_uint_t processing; /* unsigned processing:1; */ + ngx_uint_t busy; /* unsigned busy:1; */ } ngx_syslog_peer_t; From vl at nginx.com Wed Sep 24 16:03:49 2014 From: vl at nginx.com (Homutov Vladimir) Date: Wed, 24 Sep 2014 16:03:49 +0000 Subject: [nginx] Syslog: improved error handling of unix domain sockets. Message-ID: details: http://hg.nginx.org/nginx/rev/02c2352d5b01 branches: changeset: 5858:02c2352d5b01 user: Vladimir Homutov date: Tue Aug 26 14:56:54 2014 +0400 description: Syslog: improved error handling of unix domain sockets. If a syslog daemon is restarted and the unix socket is used, further logging might stop to work. In case of send error, socket is closed, forcing a reconnection at the next logging attempt. diffstat: src/core/ngx_syslog.c | 26 ++++++++++++++++++++++++-- 1 files changed, 24 insertions(+), 2 deletions(-) diffs (54 lines): diff -r 2cb5275bf5e7 -r 02c2352d5b01 src/core/ngx_syslog.c --- a/src/core/ngx_syslog.c Mon Sep 01 17:55:07 2014 +0400 +++ b/src/core/ngx_syslog.c Tue Aug 26 14:56:54 2014 +0400 @@ -261,6 +261,8 @@ ngx_syslog_writer(ngx_log_t *log, ngx_ui ssize_t ngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len) { + ssize_t n; + if (peer->conn.fd == (ngx_socket_t) -1) { if (ngx_syslog_init_peer(peer) != NGX_OK) { return NGX_ERROR; @@ -271,12 +273,28 @@ ngx_syslog_send(ngx_syslog_peer_t *peer, peer->conn.log = ngx_cycle->log; if (ngx_send) { - return ngx_send(&peer->conn, buf, len); + n = ngx_send(&peer->conn, buf, len); } else { /* event module has not yet set ngx_io */ - return ngx_os_io.send(&peer->conn, buf, len); + n = ngx_os_io.send(&peer->conn, buf, len); } + +#if (NGX_HAVE_UNIX_DOMAIN) + + if (n == NGX_ERROR && peer->server.sockaddr->sa_family == AF_UNIX) { + + if (ngx_close_socket(peer->conn.fd) == -1) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno, + ngx_close_socket_n " failed"); + } + + peer->conn.fd = (ngx_socket_t) -1; + } + +#endif + + return n; } @@ -344,6 +362,10 @@ ngx_syslog_cleanup(void *data) /* prevents further use of this peer */ peer->busy = 1; + if (peer->conn.fd == (ngx_socket_t) -1) { + return; + } + if (ngx_close_socket(peer->conn.fd) == -1) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno, ngx_close_socket_n " failed"); From vbart at nginx.com Wed Sep 24 17:56:04 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 24 Sep 2014 17:56:04 +0000 Subject: [nginx] Limit conn: use complex value in limit_conn_zone (ticket... Message-ID: details: http://hg.nginx.org/nginx/rev/c9787372f16d branches: changeset: 5860:c9787372f16d user: Valentin Bartenev date: Wed Sep 24 21:55:19 2014 +0400 description: Limit conn: use complex value in limit_conn_zone (ticket #121). One intentional side effect of this change is that key is allowed only in the first position. Previously, it was possible to specify the key variable at any position, but that was never documented, and is contrary to nginx configuration practice for positional parameters. diffstat: src/http/modules/ngx_http_limit_conn_module.c | 123 +++++++++++-------------- 1 files changed, 55 insertions(+), 68 deletions(-) diffs (243 lines): diff -r ad9116427acf -r c9787372f16d src/http/modules/ngx_http_limit_conn_module.c --- a/src/http/modules/ngx_http_limit_conn_module.c Wed Sep 24 21:55:19 2014 +0400 +++ b/src/http/modules/ngx_http_limit_conn_module.c Wed Sep 24 21:55:19 2014 +0400 @@ -25,9 +25,8 @@ typedef struct { typedef struct { - ngx_rbtree_t *rbtree; - ngx_int_t index; - ngx_str_t var; + ngx_rbtree_t *rbtree; + ngx_http_complex_value_t key; } ngx_http_limit_conn_ctx_t; @@ -45,7 +44,7 @@ typedef struct { static ngx_rbtree_node_t *ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, - ngx_http_variable_value_t *vv, uint32_t hash); + ngx_str_t *key, uint32_t hash); static void ngx_http_limit_conn_cleanup(void *data); static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool); @@ -141,13 +140,13 @@ ngx_module_t ngx_http_limit_conn_module static ngx_int_t ngx_http_limit_conn_handler(ngx_http_request_t *r) { - size_t len, n; + size_t n; uint32_t hash; + ngx_str_t key; ngx_uint_t i; ngx_slab_pool_t *shpool; ngx_rbtree_node_t *node; ngx_pool_cleanup_t *cln; - ngx_http_variable_value_t *vv; ngx_http_limit_conn_ctx_t *ctx; ngx_http_limit_conn_node_t *lc; ngx_http_limit_conn_conf_t *lccf; @@ -164,41 +163,37 @@ ngx_http_limit_conn_handler(ngx_http_req for (i = 0; i < lccf->limits.nelts; i++) { ctx = limits[i].shm_zone->data; - vv = ngx_http_get_indexed_variable(r, ctx->index); + if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } - if (vv == NULL || vv->not_found) { + if (key.len == 0) { continue; } - len = vv->len; - - if (len == 0) { - continue; - } - - if (len > 255) { + if (key.len > 255) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "the value of the \"%V\" variable " - "is more than 255 bytes: \"%v\"", - &ctx->var, vv); + "the value of the \"%V\" key " + "is more than 255 bytes: \"%V\"", + &ctx->key.value, &key); continue; } r->main->limit_conn_set = 1; - hash = ngx_crc32_short(vv->data, len); + hash = ngx_crc32_short(key.data, key.len); shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); - node = ngx_http_limit_conn_lookup(ctx->rbtree, vv, hash); + node = ngx_http_limit_conn_lookup(ctx->rbtree, &key, hash); if (node == NULL) { n = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_limit_conn_node_t, data) - + len; + + key.len; node = ngx_slab_alloc_locked(shpool, n); @@ -211,9 +206,9 @@ ngx_http_limit_conn_handler(ngx_http_req lc = (ngx_http_limit_conn_node_t *) &node->color; node->key = hash; - lc->len = (u_char) len; + lc->len = (u_char) key.len; lc->conn = 1; - ngx_memcpy(lc->data, vv->data, len); + ngx_memcpy(lc->data, key.data, key.len); ngx_rbtree_insert(ctx->rbtree, node); @@ -300,8 +295,7 @@ ngx_http_limit_conn_rbtree_insert_value( static ngx_rbtree_node_t * -ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, ngx_http_variable_value_t *vv, - uint32_t hash) +ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, ngx_str_t *key, uint32_t hash) { ngx_int_t rc; ngx_rbtree_node_t *node, *sentinel; @@ -326,8 +320,8 @@ ngx_http_limit_conn_lookup(ngx_rbtree_t lcn = (ngx_http_limit_conn_node_t *) &node->color; - rc = ngx_memn2cmp(vv->data, lcn->data, - (size_t) vv->len, (size_t) lcn->len); + rc = ngx_memn2cmp(key->data, lcn->data, key->len, (size_t) lcn->len); + if (rc == 0) { return node; } @@ -399,11 +393,16 @@ ngx_http_limit_conn_init_zone(ngx_shm_zo ctx = shm_zone->data; if (octx) { - if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) { + if (ctx->key.value.len != octx->key.value.len + || ngx_strncmp(ctx->key.value.data, octx->key.value.data, + ctx->key.value.len) + != 0) + { ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, - "limit_conn_zone \"%V\" uses the \"%V\" variable " - "while previously it used the \"%V\" variable", - &shm_zone->shm.name, &ctx->var, &octx->var); + "limit_conn_zone \"%V\" uses the \"%V\" key " + "while previously it used the \"%V\" key", + &shm_zone->shm.name, &ctx->key.value, + &octx->key.value); return NGX_ERROR; } @@ -493,20 +492,35 @@ ngx_http_limit_conn_merge_conf(ngx_conf_ static char * ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - u_char *p; - ssize_t size; - ngx_str_t *value, name, s; - ngx_uint_t i; - ngx_shm_zone_t *shm_zone; - ngx_http_limit_conn_ctx_t *ctx; + u_char *p; + ssize_t size; + ngx_str_t *value, name, s; + ngx_uint_t i; + ngx_shm_zone_t *shm_zone; + ngx_http_limit_conn_ctx_t *ctx; + ngx_http_compile_complex_value_t ccv; value = cf->args->elts; - ctx = NULL; + ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_conn_ctx_t)); + if (ctx == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &ctx->key; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + size = 0; name.len = 0; - for (i = 1; i < cf->args->nelts; i++) { + for (i = 2; i < cf->args->nelts; i++) { if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { @@ -542,26 +556,6 @@ ngx_http_limit_conn_zone(ngx_conf_t *cf, continue; } - if (value[i].data[0] == '$') { - - value[i].len--; - value[i].data++; - - ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_conn_ctx_t)); - if (ctx == NULL) { - return NGX_CONF_ERROR; - } - - ctx->index = ngx_http_get_variable_index(cf, &value[i]); - if (ctx->index == NGX_ERROR) { - return NGX_CONF_ERROR; - } - - ctx->var = value[i]; - - continue; - } - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[i]); return NGX_CONF_ERROR; @@ -574,13 +568,6 @@ ngx_http_limit_conn_zone(ngx_conf_t *cf, return NGX_CONF_ERROR; } - if (ctx == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "no variable is defined for %V \"%V\"", - &cmd->name, &name); - return NGX_CONF_ERROR; - } - shm_zone = ngx_shared_memory_add(cf, &name, size, &ngx_http_limit_conn_module); if (shm_zone == NULL) { @@ -591,8 +578,8 @@ ngx_http_limit_conn_zone(ngx_conf_t *cf, ctx = shm_zone->data; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "%V \"%V\" is already bound to variable \"%V\"", - &cmd->name, &name, &ctx->var); + "%V \"%V\" is already bound to key \"%V\"", + &cmd->name, &name, &ctx->key.value); return NGX_CONF_ERROR; } From vbart at nginx.com Wed Sep 24 17:56:07 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 24 Sep 2014 17:56:07 +0000 Subject: [nginx] Limit conn: aligned field names in structures. Message-ID: details: http://hg.nginx.org/nginx/rev/1e6bf87a7289 branches: changeset: 5861:1e6bf87a7289 user: Valentin Bartenev date: Wed Sep 24 21:55:19 2014 +0400 description: Limit conn: aligned field names in structures. No functional changes. diffstat: src/http/modules/ngx_http_limit_conn_module.c | 22 +++++++++++----------- 1 files changed, 11 insertions(+), 11 deletions(-) diffs (47 lines): diff -r c9787372f16d -r 1e6bf87a7289 src/http/modules/ngx_http_limit_conn_module.c --- a/src/http/modules/ngx_http_limit_conn_module.c Wed Sep 24 21:55:19 2014 +0400 +++ b/src/http/modules/ngx_http_limit_conn_module.c Wed Sep 24 21:55:19 2014 +0400 @@ -11,16 +11,16 @@ typedef struct { - u_char color; - u_char len; - u_short conn; - u_char data[1]; + u_char color; + u_char len; + u_short conn; + u_char data[1]; } ngx_http_limit_conn_node_t; typedef struct { - ngx_shm_zone_t *shm_zone; - ngx_rbtree_node_t *node; + ngx_shm_zone_t *shm_zone; + ngx_rbtree_node_t *node; } ngx_http_limit_conn_cleanup_t; @@ -31,15 +31,15 @@ typedef struct { typedef struct { - ngx_shm_zone_t *shm_zone; - ngx_uint_t conn; + ngx_shm_zone_t *shm_zone; + ngx_uint_t conn; } ngx_http_limit_conn_limit_t; typedef struct { - ngx_array_t limits; - ngx_uint_t log_level; - ngx_uint_t status_code; + ngx_array_t limits; + ngx_uint_t log_level; + ngx_uint_t status_code; } ngx_http_limit_conn_conf_t; From vbart at nginx.com Wed Sep 24 17:56:10 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 24 Sep 2014 17:56:10 +0000 Subject: [nginx] Limit req: use complex value in limit_req_zone. Message-ID: details: http://hg.nginx.org/nginx/rev/ecbb99aa0e12 branches: changeset: 5862:ecbb99aa0e12 user: Valentin Bartenev date: Wed Sep 24 21:55:19 2014 +0400 description: Limit req: use complex value in limit_req_zone. One intentional side effect of this change is that key is allowed only in the first position. Previously, it was possible to specify the key variable at any position, but that was never documented, and is contrary with nginx configuration practice for positional parameters. diffstat: src/http/modules/ngx_http_limit_req_module.c | 111 +++++++++++--------------- 1 files changed, 49 insertions(+), 62 deletions(-) diffs (193 lines): diff -r 1e6bf87a7289 -r ecbb99aa0e12 src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c Wed Sep 24 21:55:19 2014 +0400 +++ b/src/http/modules/ngx_http_limit_req_module.c Wed Sep 24 21:55:19 2014 +0400 @@ -35,8 +35,7 @@ typedef struct { ngx_slab_pool_t *shpool; /* integer value, 1 corresponds to 0.001 r/s */ ngx_uint_t rate; - ngx_int_t index; - ngx_str_t var; + ngx_http_complex_value_t key; ngx_http_limit_req_node_t *node; } ngx_http_limit_req_ctx_t; @@ -158,12 +157,11 @@ ngx_module_t ngx_http_limit_req_module static ngx_int_t ngx_http_limit_req_handler(ngx_http_request_t *r) { - size_t len; uint32_t hash; + ngx_str_t key; ngx_int_t rc; ngx_uint_t n, excess; ngx_msec_t delay; - ngx_http_variable_value_t *vv; ngx_http_limit_req_ctx_t *ctx; ngx_http_limit_req_conf_t *lrcf; ngx_http_limit_req_limit_t *limit, *limits; @@ -189,31 +187,27 @@ ngx_http_limit_req_handler(ngx_http_requ ctx = limit->shm_zone->data; - vv = ngx_http_get_indexed_variable(r, ctx->index); + if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } - if (vv == NULL || vv->not_found) { + if (key.len == 0) { continue; } - len = vv->len; - - if (len == 0) { + if (key.len > 65535) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "the value of the \"%V\" key " + "is more than 65535 bytes: \"%V\"", + &ctx->key.value, &key); continue; } - if (len > 65535) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "the value of the \"%V\" variable " - "is more than 65535 bytes: \"%v\"", - &ctx->var, vv); - continue; - } - - hash = ngx_crc32_short(vv->data, len); + hash = ngx_crc32_short(key.data, key.len); ngx_shmtx_lock(&ctx->shpool->mutex); - rc = ngx_http_limit_req_lookup(limit, hash, vv->data, len, &excess, + rc = ngx_http_limit_req_lookup(limit, hash, key.data, key.len, &excess, (n == lrcf->limits.nelts - 1)); ngx_shmtx_unlock(&ctx->shpool->mutex); @@ -632,11 +626,16 @@ ngx_http_limit_req_init_zone(ngx_shm_zon ctx = shm_zone->data; if (octx) { - if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) { + if (ctx->key.value.len != octx->key.value.len + || ngx_strncmp(ctx->key.value.data, octx->key.value.data, + ctx->key.value.len) + != 0) + { ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, - "limit_req \"%V\" uses the \"%V\" variable " - "while previously it used the \"%V\" variable", - &shm_zone->shm.name, &ctx->var, &octx->var); + "limit_req \"%V\" uses the \"%V\" key " + "while previously it used the \"%V\" key", + &shm_zone->shm.name, &ctx->key.value, + &octx->key.value); return NGX_ERROR; } @@ -731,24 +730,39 @@ ngx_http_limit_req_merge_conf(ngx_conf_t static char * ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - u_char *p; - size_t len; - ssize_t size; - ngx_str_t *value, name, s; - ngx_int_t rate, scale; - ngx_uint_t i; - ngx_shm_zone_t *shm_zone; - ngx_http_limit_req_ctx_t *ctx; + u_char *p; + size_t len; + ssize_t size; + ngx_str_t *value, name, s; + ngx_int_t rate, scale; + ngx_uint_t i; + ngx_shm_zone_t *shm_zone; + ngx_http_limit_req_ctx_t *ctx; + ngx_http_compile_complex_value_t ccv; value = cf->args->elts; - ctx = NULL; + ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t)); + if (ctx == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &ctx->key; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + size = 0; rate = 1; scale = 1; name.len = 0; - for (i = 1; i < cf->args->nelts; i++) { + for (i = 2; i < cf->args->nelts; i++) { if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { @@ -808,26 +822,6 @@ ngx_http_limit_req_zone(ngx_conf_t *cf, continue; } - if (value[i].data[0] == '$') { - - value[i].len--; - value[i].data++; - - ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t)); - if (ctx == NULL) { - return NGX_CONF_ERROR; - } - - ctx->index = ngx_http_get_variable_index(cf, &value[i]); - if (ctx->index == NGX_ERROR) { - return NGX_CONF_ERROR; - } - - ctx->var = value[i]; - - continue; - } - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[i]); return NGX_CONF_ERROR; @@ -840,13 +834,6 @@ ngx_http_limit_req_zone(ngx_conf_t *cf, return NGX_CONF_ERROR; } - if (ctx == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "no variable is defined for %V \"%V\"", - &cmd->name, &name); - return NGX_CONF_ERROR; - } - ctx->rate = rate * 1000 / scale; shm_zone = ngx_shared_memory_add(cf, &name, size, @@ -859,8 +846,8 @@ ngx_http_limit_req_zone(ngx_conf_t *cf, ctx = shm_zone->data; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "%V \"%V\" is already bound to variable \"%V\"", - &cmd->name, &name, &ctx->var); + "%V \"%V\" is already bound to key \"%V\"", + &cmd->name, &name, &ctx->key.value); return NGX_CONF_ERROR; } From vbart at nginx.com Wed Sep 24 17:56:13 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 24 Sep 2014 17:56:13 +0000 Subject: [nginx] Limit req: reduced number of parameters in the lookup fu... Message-ID: details: http://hg.nginx.org/nginx/rev/102f85699420 branches: changeset: 5863:102f85699420 user: Valentin Bartenev date: Wed Sep 24 21:55:19 2014 +0400 description: Limit req: reduced number of parameters in the lookup function. No functional changes. diffstat: src/http/modules/ngx_http_limit_req_module.c | 15 +++++++-------- 1 files changed, 7 insertions(+), 8 deletions(-) diffs (62 lines): diff -r ecbb99aa0e12 -r 102f85699420 src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c Wed Sep 24 21:55:19 2014 +0400 +++ b/src/http/modules/ngx_http_limit_req_module.c Wed Sep 24 21:55:19 2014 +0400 @@ -58,8 +58,7 @@ typedef struct { static void ngx_http_limit_req_delay(ngx_http_request_t *r); static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, - ngx_uint_t hash, u_char *data, size_t len, ngx_uint_t *ep, - ngx_uint_t account); + ngx_uint_t hash, ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account); static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, ngx_uint_t n, ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit); static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, @@ -207,7 +206,7 @@ ngx_http_limit_req_handler(ngx_http_requ ngx_shmtx_lock(&ctx->shpool->mutex); - rc = ngx_http_limit_req_lookup(limit, hash, key.data, key.len, &excess, + rc = ngx_http_limit_req_lookup(limit, hash, &key, &excess, (n == lrcf->limits.nelts - 1)); ngx_shmtx_unlock(&ctx->shpool->mutex); @@ -359,7 +358,7 @@ ngx_http_limit_req_rbtree_insert_value(n static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash, - u_char *data, size_t len, ngx_uint_t *ep, ngx_uint_t account) + ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account) { size_t size; ngx_int_t rc, excess; @@ -394,7 +393,7 @@ ngx_http_limit_req_lookup(ngx_http_limit lr = (ngx_http_limit_req_node_t *) &node->color; - rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len); + rc = ngx_memn2cmp(key->data, lr->data, key->len, (size_t) lr->len); if (rc == 0) { ngx_queue_remove(&lr->queue); @@ -434,7 +433,7 @@ ngx_http_limit_req_lookup(ngx_http_limit size = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_limit_req_node_t, data) - + len; + + key->len; ngx_http_limit_req_expire(ctx, 1); @@ -455,10 +454,10 @@ ngx_http_limit_req_lookup(ngx_http_limit lr = (ngx_http_limit_req_node_t *) &node->color; - lr->len = (u_short) len; + lr->len = (u_short) key->len; lr->excess = 0; - ngx_memcpy(lr->data, data, len); + ngx_memcpy(lr->data, key->data, key->len); ngx_rbtree_insert(&ctx->sh->rbtree, node); From kpariani at zimbra.com Wed Sep 24 23:14:32 2014 From: kpariani at zimbra.com (Kunal Pariani) Date: Wed, 24 Sep 2014 18:14:32 -0500 (CDT) Subject: [PATCH] Update mail parsing to be per protocol (imap/pop/smtp) In-Reply-To: <722204518.3017626.1411600457312.JavaMail.zimbra@zimbra.com> References: <1273114156.2387485.1410986989995.JavaMail.zimbra@zimbra.com> <20140918110032.GO91749@mdounin.ru> <1644005643.2543169.1411061568638.JavaMail.zimbra@zimbra.com> Message-ID: <1349223799.3017631.1411600472282.JavaMail.zimbra@zimbra.com> Some comments received on the patch from Filipe I can add that I think your patch is valuable. But half of the changes are not related to the main patch goals: - expected args count check - additional error messages. Just a quick review of your patch: - it is too long to be easily reviewed. - please keep the blank lines from original code. ( lines with just a - remove them ). - moving and grouping of enum has no added value from my point of view. Because of the ngx_mail_set__parse_state_start() and ngx_mail_set_imap_parse_state_argument() methods, you need to push the enums declarations out of parse() methods. => use a macro to replace the ngx_mail_set__parse_state_start method. => not sure that a macro will be compliant with nginx standard. - ngx_mail_set_imap_parse_state_start() and co. has no value added, unless you want to put a breakpoint to catch these step. - same about ngx_mail_set_imap_parse_state_argument() and co. Can i know the possibility of this patch being considered if i make the above suggested changes or any others if there ? Thanks -Kunal ----- Original Message ----- From: "Kunal Pariani" To: "nginx-devel" Sent: Thursday, September 18, 2014 10:32:48 AM Subject: Re: [PATCH] Update mail parsing to be per protocol (imap/pop/smtp) The patch certainly adds more intelligence in the mail parser per protocol (adding more specific states & error codes) and seems valid even with the latest nginx mainline. Thanks -Kunal ----- Original Message ----- From: "Maxim Dounin" To: "nginx-devel" Sent: Thursday, September 18, 2014 4:00:32 AM Subject: Re: [PATCH] Update mail parsing to be per protocol (imap/pop/smtp) Hello! On Wed, Sep 17, 2014 at 03:49:50PM -0500, Kunal Pariani wrote: > Hello, > This patch adds separate mail parsing states per protocol > (imap/pop/smtp), specific error codes for parsing/auth/login > failures. Also includes some minor bug fixes in the mail parsing > code. Requesting to include this patch as Zimbra has been using > this since nginx 0.5.37, so it's quite heavily tested. Mail parsing code a bit changed since 0.5.37, so this is more like an argument against. In any case, it's not clear what the patch tries to achieve. It's highly unlikely that it will be considered, see http://nginx.org/en/docs/contributing_changes.html. -- Maxim Dounin http://nginx.org/ _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From s7v7nislands at gmail.com Fri Sep 26 09:21:25 2014 From: s7v7nislands at gmail.com (XiaoBing Jiang) Date: Fri, 26 Sep 2014 17:21:25 +0800 Subject: [PATCH] Fix typo In-Reply-To: <2742311.119GAPK7M2@vbart-laptop> References: <2742311.119GAPK7M2@vbart-laptop> Message-ID: what is the macro meaning? I can't find any symbol in configure script. On Tue, Sep 23, 2014 at 4:04 PM, Valentin V. Bartenev wrote: > On Tuesday 23 September 2014 10:00:06 XiaoBing Jiang wrote: >> # HG changeset patch >> # User s7v7nislands >> # Date 1411437071 -28800 >> # Tue Sep 23 09:51:11 2014 +0800 >> # Branch fix_typo >> # Node ID 34a7a94c3dab57fd302fe731b013d90be4354efe >> # Parent a0a14319968b2d978d306f5a91e81e9e4e3e7ce6 >> Fix typo >> >> diff -r a0a14319968b -r 34a7a94c3dab src/event/ngx_event_mutex.c >> --- a/src/event/ngx_event_mutex.c Mon Sep 22 19:48:23 2014 +0400 >> +++ b/src/event/ngx_event_mutex.c Tue Sep 23 09:51:11 2014 +0800 >> @@ -28,7 +28,7 @@ >> m->last = ev; >> ev->next = NULL; >> >> -#if (NGX_THREADS0) >> +#if (NGX_THREADS) >> ev->light = 1; >> #endif >> > > No, thanks, that's not a typo. > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From vbart at nginx.com Fri Sep 26 10:55:52 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Fri, 26 Sep 2014 14:55:52 +0400 Subject: [PATCH] Fix typo In-Reply-To: References: <2742311.119GAPK7M2@vbart-laptop> Message-ID: <2519375.PPZzKq0lsI@vbart-workstation> On Friday 26 September 2014 17:21:25 XiaoBing Jiang wrote: > what is the macro meaning? I can't find any symbol in configure script. > It's meaning: #if 0 ev->light = 1; #endif and the ngx_event_t structure has no the "light" member. wbr, Valentin V. Bartenev > On Tue, Sep 23, 2014 at 4:04 PM, Valentin V. Bartenev wrote: > > On Tuesday 23 September 2014 10:00:06 XiaoBing Jiang wrote: > >> # HG changeset patch > >> # User s7v7nislands > >> # Date 1411437071 -28800 > >> # Tue Sep 23 09:51:11 2014 +0800 > >> # Branch fix_typo > >> # Node ID 34a7a94c3dab57fd302fe731b013d90be4354efe > >> # Parent a0a14319968b2d978d306f5a91e81e9e4e3e7ce6 > >> Fix typo > >> > >> diff -r a0a14319968b -r 34a7a94c3dab src/event/ngx_event_mutex.c > >> --- a/src/event/ngx_event_mutex.c Mon Sep 22 19:48:23 2014 +0400 > >> +++ b/src/event/ngx_event_mutex.c Tue Sep 23 09:51:11 2014 +0800 > >> @@ -28,7 +28,7 @@ > >> m->last = ev; > >> ev->next = NULL; > >> > >> -#if (NGX_THREADS0) > >> +#if (NGX_THREADS) > >> ev->light = 1; > >> #endif > >> > > > > No, thanks, that's not a typo. > > > > wbr, Valentin V. Bartenev > > > > _______________________________________________ > > nginx-devel mailing list > > nginx-devel at nginx.org > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > From s7v7nislands at gmail.com Fri Sep 26 23:45:35 2014 From: s7v7nislands at gmail.com (XiaoBing Jiang) Date: Sat, 27 Sep 2014 07:45:35 +0800 Subject: [PATCH] Fix typo In-Reply-To: <2519375.PPZzKq0lsI@vbart-workstation> References: <2742311.119GAPK7M2@vbart-laptop> <2519375.PPZzKq0lsI@vbart-workstation> Message-ID: thanks! so can we just delete this code block? On Fri, Sep 26, 2014 at 6:55 PM, Valentin V. Bartenev wrote: > On Friday 26 September 2014 17:21:25 XiaoBing Jiang wrote: >> what is the macro meaning? I can't find any symbol in configure script. >> > > It's meaning: > > #if 0 > ev->light = 1; > #endif > > and the ngx_event_t structure has no the "light" member. > > wbr, Valentin V. Bartenev > > > >> On Tue, Sep 23, 2014 at 4:04 PM, Valentin V. Bartenev wrote: >> > On Tuesday 23 September 2014 10:00:06 XiaoBing Jiang wrote: >> >> # HG changeset patch >> >> # User s7v7nislands >> >> # Date 1411437071 -28800 >> >> # Tue Sep 23 09:51:11 2014 +0800 >> >> # Branch fix_typo >> >> # Node ID 34a7a94c3dab57fd302fe731b013d90be4354efe >> >> # Parent a0a14319968b2d978d306f5a91e81e9e4e3e7ce6 >> >> Fix typo >> >> >> >> diff -r a0a14319968b -r 34a7a94c3dab src/event/ngx_event_mutex.c >> >> --- a/src/event/ngx_event_mutex.c Mon Sep 22 19:48:23 2014 +0400 >> >> +++ b/src/event/ngx_event_mutex.c Tue Sep 23 09:51:11 2014 +0800 >> >> @@ -28,7 +28,7 @@ >> >> m->last = ev; >> >> ev->next = NULL; >> >> >> >> -#if (NGX_THREADS0) >> >> +#if (NGX_THREADS) >> >> ev->light = 1; >> >> #endif >> >> >> > >> > No, thanks, that's not a typo. >> > >> > wbr, Valentin V. Bartenev >> > >> > _______________________________________________ >> > nginx-devel mailing list >> > nginx-devel at nginx.org >> > http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From vbart at nginx.com Sat Sep 27 04:13:16 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Sat, 27 Sep 2014 08:13:16 +0400 Subject: [PATCH] Fix typo In-Reply-To: References: <2519375.PPZzKq0lsI@vbart-workstation> Message-ID: <5333662.qEBhE02kjk@vbart-laptop> On Saturday 27 September 2014 07:45:35 XiaoBing Jiang wrote: > thanks! so can we just delete this code block? > It's not that simple. This code block is a part of worker thread support that is unfinished and a long time broken. So you should either fix it or have a good reason to delete it all. wbr, Valentin V. Bartenev > On Fri, Sep 26, 2014 at 6:55 PM, Valentin V. Bartenev wrote: > > On Friday 26 September 2014 17:21:25 XiaoBing Jiang wrote: > >> what is the macro meaning? I can't find any symbol in configure script. > >> > > > > It's meaning: > > > > #if 0 > > ev->light = 1; > > #endif > > > > and the ngx_event_t structure has no the "light" member. > > > > wbr, Valentin V. Bartenev > > > > > > > >> On Tue, Sep 23, 2014 at 4:04 PM, Valentin V. Bartenev wrote: > >> > On Tuesday 23 September 2014 10:00:06 XiaoBing Jiang wrote: > >> >> # HG changeset patch > >> >> # User s7v7nislands > >> >> # Date 1411437071 -28800 > >> >> # Tue Sep 23 09:51:11 2014 +0800 > >> >> # Branch fix_typo > >> >> # Node ID 34a7a94c3dab57fd302fe731b013d90be4354efe > >> >> # Parent a0a14319968b2d978d306f5a91e81e9e4e3e7ce6 > >> >> Fix typo > >> >> > >> >> diff -r a0a14319968b -r 34a7a94c3dab src/event/ngx_event_mutex.c > >> >> --- a/src/event/ngx_event_mutex.c Mon Sep 22 19:48:23 2014 +0400 > >> >> +++ b/src/event/ngx_event_mutex.c Tue Sep 23 09:51:11 2014 +0800 > >> >> @@ -28,7 +28,7 @@ > >> >> m->last = ev; > >> >> ev->next = NULL; > >> >> > >> >> -#if (NGX_THREADS0) > >> >> +#if (NGX_THREADS) > >> >> ev->light = 1; > >> >> #endif > >> >> > >> > > >> > No, thanks, that's not a typo. > >> > > >> > wbr, Valentin V. Bartenev > >> > > >> > _______________________________________________ > >> > nginx-devel mailing list > >> > nginx-devel at nginx.org > >> > http://mailman.nginx.org/mailman/listinfo/nginx-devel > >> > >> _______________________________________________ > >> nginx-devel mailing list > >> nginx-devel at nginx.org > >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >> > > > > _______________________________________________ > > nginx-devel mailing list > > nginx-devel at nginx.org > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > From s7v7nislands at gmail.com Sun Sep 28 04:00:45 2014 From: s7v7nislands at gmail.com (XiaoBing Jiang) Date: Sun, 28 Sep 2014 12:00:45 +0800 Subject: [PATCH] Fix typo In-Reply-To: <5333662.qEBhE02kjk@vbart-laptop> References: <2519375.PPZzKq0lsI@vbart-workstation> <5333662.qEBhE02kjk@vbart-laptop> Message-ID: I grep the '#if 0', find many in code. why this don't using '#if 0'? I feel using '#if (NGX_THREADS0)' is more confused. On Sat, Sep 27, 2014 at 12:13 PM, Valentin V. Bartenev wrote: > On Saturday 27 September 2014 07:45:35 XiaoBing Jiang wrote: >> thanks! so can we just delete this code block? >> > > It's not that simple. This code block is a part > of worker thread support that is unfinished and > a long time broken. So you should either fix it > or have a good reason to delete it all. > > wbr, Valentin V. Bartenev > > >> On Fri, Sep 26, 2014 at 6:55 PM, Valentin V. Bartenev wrote: >> > On Friday 26 September 2014 17:21:25 XiaoBing Jiang wrote: >> >> what is the macro meaning? I can't find any symbol in configure script. >> >> >> > >> > It's meaning: >> > >> > #if 0 >> > ev->light = 1; >> > #endif >> > >> > and the ngx_event_t structure has no the "light" member. >> > >> > wbr, Valentin V. Bartenev >> > >> > >> > >> >> On Tue, Sep 23, 2014 at 4:04 PM, Valentin V. Bartenev wrote: >> >> > On Tuesday 23 September 2014 10:00:06 XiaoBing Jiang wrote: >> >> >> # HG changeset patch >> >> >> # User s7v7nislands >> >> >> # Date 1411437071 -28800 >> >> >> # Tue Sep 23 09:51:11 2014 +0800 >> >> >> # Branch fix_typo >> >> >> # Node ID 34a7a94c3dab57fd302fe731b013d90be4354efe >> >> >> # Parent a0a14319968b2d978d306f5a91e81e9e4e3e7ce6 >> >> >> Fix typo >> >> >> >> >> >> diff -r a0a14319968b -r 34a7a94c3dab src/event/ngx_event_mutex.c >> >> >> --- a/src/event/ngx_event_mutex.c Mon Sep 22 19:48:23 2014 +0400 >> >> >> +++ b/src/event/ngx_event_mutex.c Tue Sep 23 09:51:11 2014 +0800 >> >> >> @@ -28,7 +28,7 @@ >> >> >> m->last = ev; >> >> >> ev->next = NULL; >> >> >> >> >> >> -#if (NGX_THREADS0) >> >> >> +#if (NGX_THREADS) >> >> >> ev->light = 1; >> >> >> #endif >> >> >> >> >> > >> >> > No, thanks, that's not a typo. >> >> > >> >> > wbr, Valentin V. Bartenev >> >> > >> >> > _______________________________________________ >> >> > nginx-devel mailing list >> >> > nginx-devel at nginx.org >> >> > http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> >> >> _______________________________________________ >> >> nginx-devel mailing list >> >> nginx-devel at nginx.org >> >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> >> > >> > _______________________________________________ >> > nginx-devel mailing list >> > nginx-devel at nginx.org >> > http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From vbart at nginx.com Sun Sep 28 23:03:23 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Mon, 29 Sep 2014 03:03:23 +0400 Subject: [PATCH] Fix typo In-Reply-To: References: <5333662.qEBhE02kjk@vbart-laptop> Message-ID: <5336261.NeyGX4maaZ@vbart-laptop> On Sunday 28 September 2014 12:00:45 XiaoBing Jiang wrote: > I grep the '#if 0', find many in code. > > why this don't using '#if 0'? I feel using '#if (NGX_THREADS0)' is > more confused. This one is about threads, so it combines #if (NGX_THREADS) and #if 0, or just a shorter way to write #if (NGX_THREADS && 0). For example, you can also find "#if (NGX_DEBUG0)". Why actually do you care? That's a dead code anyway. wbr, Valentin V. Bartenev From s7v7nislands at gmail.com Mon Sep 29 01:38:23 2014 From: s7v7nislands at gmail.com (XiaoBing Jiang) Date: Mon, 29 Sep 2014 09:38:23 +0800 Subject: [PATCH] Fix typo In-Reply-To: <5336261.NeyGX4maaZ@vbart-laptop> References: <5333662.qEBhE02kjk@vbart-laptop> <5336261.NeyGX4maaZ@vbart-laptop> Message-ID: I'm a newbie for c programming. I want to know the usage of macro in nginx. thanks for explain this to me! On Mon, Sep 29, 2014 at 7:03 AM, Valentin V. Bartenev wrote: > On Sunday 28 September 2014 12:00:45 XiaoBing Jiang wrote: >> I grep the '#if 0', find many in code. >> >> why this don't using '#if 0'? I feel using '#if (NGX_THREADS0)' is >> more confused. > > This one is about threads, so it combines #if (NGX_THREADS) and #if 0, > or just a shorter way to write #if (NGX_THREADS && 0). > > For example, you can also find "#if (NGX_DEBUG0)". > > Why actually do you care? That's a dead code anyway. > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From faskiri.devel at gmail.com Mon Sep 29 08:33:08 2014 From: faskiri.devel at gmail.com (Fasih) Date: Mon, 29 Sep 2014 14:03:08 +0530 Subject: SSL memory bug? Message-ID: Hi I was looking at ngx_event_openssl.c, when I saw this. if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_set_ex_data() failed"); X509_free(x509); BIO_free(bio); return NGX_ERROR; } X509_free(x509); We just free the memory that is then used in ngx_ssl_session_id_context (introduced in 1.6.2). I havent tried to repro the error, but looks like a bug to me. PFA a suggested patch. -------------- next part -------------- A non-text attachment was scrubbed... Name: patch Type: application/octet-stream Size: 586 bytes Desc: not available URL: From mdounin at mdounin.ru Mon Sep 29 12:17:50 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 29 Sep 2014 16:17:50 +0400 Subject: SSL memory bug? In-Reply-To: References: Message-ID: <20140929121750.GN10052@mdounin.ru> Hello! On Mon, Sep 29, 2014 at 02:03:08PM +0530, Fasih wrote: > Hi > > I was looking at ngx_event_openssl.c, when I saw this. > > if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) > == 0) > { > ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, > "SSL_CTX_set_ex_data() failed"); > X509_free(x509); > BIO_free(bio); > return NGX_ERROR; > } > > X509_free(x509); > > > We just free the memory that is then used in > > ngx_ssl_session_id_context (introduced in 1.6.2). I havent tried to > repro the error, but looks like a bug to me. PFA a suggested patch. The SSL_CTX_use_certificate() call will grab a reference to the certificate, so X509_free() here will not really free the memory. -- Maxim Dounin http://nginx.org/ From fasihullah.askiri at gmail.com Mon Sep 29 14:23:15 2014 From: fasihullah.askiri at gmail.com (Fasihullah Askiri) Date: Mon, 29 Sep 2014 19:53:15 +0530 Subject: SSL memory bug? In-Reply-To: <20140929121750.GN10052@mdounin.ru> References: <20140929121750.GN10052@mdounin.ru> Message-ID: Thanks Maxim Yeah, I had earlier tried to run this with valgrind and saw that valgrind wasnt reporting an issue, also saw from the openssl code it seems to be dereferencing. But the man page doesnt mention dereferencing anywhere. For my information, can you please point me to some documentation in openssl that says so. I use X509_free elsewhere and I have used it as free (and not as a deref). Should I open a doc ticket (if there is any) in openssl? On Mon, Sep 29, 2014 at 5:47 PM, Maxim Dounin wrote: > Hello! > > On Mon, Sep 29, 2014 at 02:03:08PM +0530, Fasih wrote: > >> Hi >> >> I was looking at ngx_event_openssl.c, when I saw this. >> >> if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) >> == 0) >> { >> ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, >> "SSL_CTX_set_ex_data() failed"); >> X509_free(x509); >> BIO_free(bio); >> return NGX_ERROR; >> } >> >> X509_free(x509); >> >> >> We just free the memory that is then used in >> >> ngx_ssl_session_id_context (introduced in 1.6.2). I havent tried to >> repro the error, but looks like a bug to me. PFA a suggested patch. > > The SSL_CTX_use_certificate() call will grab a reference to the > certificate, so X509_free() here will not really free the memory. > > -- > Maxim Dounin > http://nginx.org/ > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- +Fasih Life is 10% what happens to you and 90% how you react to it From mdounin at mdounin.ru Mon Sep 29 15:58:15 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 29 Sep 2014 19:58:15 +0400 Subject: SSL memory bug? In-Reply-To: References: <20140929121750.GN10052@mdounin.ru> Message-ID: <20140929155815.GW10052@mdounin.ru> Hello! On Mon, Sep 29, 2014 at 07:53:15PM +0530, Fasihullah Askiri wrote: > Thanks Maxim > > Yeah, I had earlier tried to run this with valgrind and saw that > valgrind wasnt reporting an issue, also saw from the openssl code it > seems to be dereferencing. But the man page doesnt mention > dereferencing anywhere. For my information, can you please point me to > some documentation in openssl that says so. I use X509_free elsewhere > and I have used it as free (and not as a deref). Should I open a doc > ticket (if there is any) in openssl? I suspect this is undocumented. -- Maxim Dounin http://nginx.org/ From yingqi.lu at intel.com Mon Sep 29 19:43:59 2014 From: yingqi.lu at intel.com (Lu, Yingqi) Date: Mon, 29 Sep 2014 19:43:59 +0000 Subject: [Patch] SO_REUSEPORT support from master process In-Reply-To: <9ACD5B67AAC5594CB6268234CF29CF9AA37BD365@ORSMSX113.amr.corp.intel.com> References: <9ACD5B67AAC5594CB6268234CF29CF9AA37A52F5@ORSMSX113.amr.corp.intel.com> <1984759.coG7FlzylE@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BAF5D@ORSMSX113.amr.corp.intel.com> <27675150.0d46n4LCFt@vbart-laptop> <9ACD5B67AAC5594CB6268234CF29CF9AA37BB059@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BBD5D@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BBF2E@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BD313@ORSMSX113.amr.corp.intel.com> <9ACD5B67AAC5594CB6268234CF29CF9AA37BD365@ORSMSX113.amr.corp.intel.com> Message-ID: <9ACD5B67AAC5594CB6268234CF29CF9AA37CAF8C@ORSMSX113.amr.corp.intel.com> Hi All, I just want to check if there are any more feedback on the patch? Is there anything additional we need to provide to help the review process? Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Tuesday, September 23, 2014 8:47 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Forgot to ask in my last email: can anyone please help to move the patch from http://forum.nginx.org/read.php?29,253446 to this main thread? Thanks very much for your help! Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Tuesday, September 23, 2014 8:36 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process I am wondering if there are any more feedback/comments/concerns? Also, does the format look OK to all of you? Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Saturday, September 20, 2014 4:45 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, I just sent the new patch directly from ToriseHg. Thanks again very much to Valentin Bartenev for his valuable feedback! The 2 changes from last version are: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. However, it is automatically named as "[PATCH] SO_REUSEPORT support from master process" instead of "[Patch] SO_REUSEPORT support from master process". Therefore, it does not show in this thread. The patch is available at a separate thread at http://forum.nginx.org/read.php?29,253446. Can anyone help to move the patch to the main thread and delete the duplicated copies? By the way, if you use outlook and you see a small message on the top saying "We removed extra line breaks from this message", please click on it to "Restore line breaks". Otherwise, the code shown there is not complete. The patch is tested locally, but I am concerned about the format changes during the email delivery. Please let me know if you see wrong format or cannot apply the patch. Thank you very much for your help! Yingqi -----Original Message----- From: Lu, Yingqi Sent: Saturday, September 20, 2014 4:00 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, After I sent out the patch, I noticed that the patch inserted in the email is actually with different format than the original one generated by TortoiseHg. What I did is just copying it and pasting in the email. Did I missed anything? I guess this is not the correct way to send the patch. I will try to find a way to send directly from ToriseHg. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Saturday, September 20, 2014 3:23 PM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Dear All, Here is another updated version of the patch. Thanks very much to Valentin Bartenev for his valuable feedback! Here are the changes in this version: 1. We use "total CPU threads" instead of "active CPU threads" to calculate the number of duplicated listeners. 2. We modify some of the code to meet the style requirements listed at http://nginx.org/en/docs/contributing_changes.html. The way we created the patch below is: we clone the code from http://hg.nginx.org/nginx, modified 4 files and then committed the changes. After that, we export the patch and attached here. Please let me know if there is anything missing here. This is the first time we prototype the patch for Nginx. Your comments and feedback are highly appreciated. Thanks, Yingqi # HG changeset patch # User Yingqi Lu # Date 1411248953 25200 # Sat Sep 20 14:35:53 2014 -0700 # Node ID 04abfbb10a7f5e4efd5187d1382a880483a79294 # Parent 43512a33e8f232fb6f256b90e76ac4f1472a0c1f Added SO_REUSEPORT support. It duplicates and configures certain number of listen sockets in the master process with SO_REUSEPORT enabled. All the worker processes can inherit them. The number of the listen sockets to be duplicated is calculated based on the number of total CPU threads. With big system that has more CPU threads, more duplicated listen sockets created to improve the throughput and scalability. With system that has only 8 or less CPU threads, there will be only 1 listen socket. Duplicated listen sockets are only being created when necessary. In case that SO_REUSEPORT is not supported by the OS, it falls back default behavior. diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_connection.c --- a/src/core/ngx_connection.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_connection.c Sat Sep 20 14:35:53 2014 -0700 @@ -304,7 +304,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - int reuseaddr; + int reuseaddr, reuseport; ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; @@ -312,6 +312,7 @@ ngx_listening_t *ls; reuseaddr = 1; + reuseport = 1; #if (NGX_SUPPRESS_WARN) failed = 0; #endif @@ -370,6 +371,24 @@ return NGX_ERROR; } + if (ngx_so_reuseport_enabled) + { + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed", + &ls[i].addr_text); + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.c Sat Sep 20 14:35:53 2014 -0700 @@ -26,6 +26,9 @@ ngx_uint_t ngx_test_config; ngx_uint_t ngx_quiet_mode; +ngx_uint_t ngx_so_reuseport_enabled; +ngx_uint_t ngx_num_dup_sockets; + #if (NGX_THREADS) ngx_tls_key_t ngx_core_tls_key; #endif @@ -54,7 +57,39 @@ ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; + ngx_uint_t num_cores, taken; + ngx_socket_t temp_s; + int one = 1; + /* check if SO_REUSEPORT feature is enabled */ + temp_s = ngx_socket(AF_INET, SOCK_STREAM, 0); + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + if (setsockopt(temp_s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &one, sizeof(int)) == 0) { + ngx_so_reuseport_enabled = 1; + } else { + ngx_so_reuseport_enabled = 0; + } + ngx_close_socket(temp_s); + + if (ngx_so_reuseport_enabled) { +#ifdef _SC_NPROCESSORS_ONLN + num_cores = sysconf(_SC_NPROCESSORS_CONF); #else + num_cores = 1; +#endif + if (num_cores > 8) { + ngx_num_dup_sockets = num_cores/8; + } else { + ngx_num_dup_sockets = 1; + } + } else { + ngx_num_dup_sockets = 1; + } + ngx_timezone_update(); /* force localtime update with a new timezone */ @@ -114,7 +149,8 @@ } - n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; + n = old_cycle->paths.nelts ? old_cycle->paths.nelts : + 10 * ngx_num_dup_sockets; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { @@ -164,7 +200,8 @@ return NULL; } - n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; + n = old_cycle->listening.nelts ? old_cycle->listening.nelts : + 10 * ngx_num_dup_sockets; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { @@ -231,7 +268,8 @@ ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ - conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); + conf.args = ngx_array_create(pool, + 10 * ngx_num_dup_sockets, + sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; @@ -486,6 +524,7 @@ } nls = cycle->listening.elts; + taken = 0; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { @@ -493,9 +532,9 @@ continue; } - if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, + if ((ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) - == NGX_OK) + == NGX_OK) && i >= taken) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; @@ -540,6 +579,7 @@ nls[n].add_deferred = 1; } #endif + taken = i + 1; break; } } @@ -747,7 +787,7 @@ exit(1); } - n = 10; + n = 10 * ngx_num_dup_sockets; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { diff -r 43512a33e8f2 -r 04abfbb10a7f src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Wed Aug 13 15:11:45 2014 +0400 +++ b/src/core/ngx_cycle.h Sat Sep 20 14:35:53 2014 -0700 @@ -136,6 +136,8 @@ extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; extern ngx_uint_t ngx_quiet_mode; +extern ngx_uint_t ngx_so_reuseport_enabled; +extern ngx_uint_t ngx_num_dup_sockets; #if (NGX_THREADS) extern ngx_tls_key_t ngx_core_tls_key; #endif diff -r 43512a33e8f2 -r 04abfbb10a7f src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Aug 13 15:11:45 2014 +0400 +++ b/src/http/ngx_http.c Sat Sep 20 14:35:53 2014 -0700 @@ -1671,7 +1671,7 @@ static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { - ngx_uint_t i, last, bind_wildcard; + ngx_uint_t i, j, last, bind_wildcard; ngx_listening_t *ls; ngx_http_port_t *hport; ngx_http_conf_addr_t *addr; @@ -1703,40 +1703,42 @@ continue; } - ls = ngx_http_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); - if (hport == NULL) { - return NGX_ERROR; - } - - ls->servers = hport; - - if (i == last - 1) { - hport->naddrs = last; - - } else { - hport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + for(j = 0; j < ngx_num_dup_sockets; j++) { + ls = ngx_http_add_listening(cf, &addr[i]); + if (ls == NULL) { return NGX_ERROR; } - break; -#endif - default: /* AF_INET */ - if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + + hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); + if (hport == NULL) { return NGX_ERROR; } - break; + + ls->servers = hport; + + if (i == last - 1) { + hport->naddrs = last; + + } else { + hport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { + return NGX_ERROR; + } + break; + } } addr++; -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Lu, Yingqi Sent: Friday, September 19, 2014 10:34 AM To: nginx-devel at nginx.org Subject: RE: [Patch] SO_REUSEPORT support from master process Hi Valentin, I just tested the exact case you mentioned and you are right! There is a connection drop, but it got recovered really quickly. The new connections will only go to the remaining listen sockets on a round robin fashion after the reload. I will change the check of "active cpu" to "all cpu". This will make the number of listen sockets a constant as long as the system remain active. Thank you very much for your hint! I will also check the coding style again and resend the patch. Thanks, Yingqi -----Original Message----- From: nginx-devel-bounces at nginx.org [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Valentin V. Bartenev Sent: Friday, September 19, 2014 9:48 AM To: nginx-devel at nginx.org Subject: Re: [Patch] SO_REUSEPORT support from master process On Friday 19 September 2014 15:52:35 Lu, Yingqi wrote: > Hi Valentin, > > Thanks very much for your email. > > Regarding to your first question, I did following test: > 1. Start Nginx > 2. Offline half of the CPU threads by "echo 0 > > /sys/devices/system/cpu/"cpu#"/online > 3. Reload Nginx and check the worker process, the number of listen > sockets is actually reduced to half. > 4. Then, I put back the offlined CPU threads back online, and reload the Nginx again. > 5. The new worker process now has 2X listen sockets as the CPU threads > doubled since the previous reload. > > Every time Nginx reloads, my understanding is it will run Ngx_init_cycle. CPU_num_check is > there. Is above testing the correct way to check if reload works? Please let me know if I > missed anything. [..] What happens if you shutdown half of your cpus again, and try to reload nginx under high load? As I understand right, with your patch it will close half of listen sockets, and all the connections that have been waiting to be accepted on these sockets will be lost. wbr, Valentin V. Bartenev _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From s.martin49 at gmail.com Mon Sep 29 20:55:37 2014 From: s.martin49 at gmail.com (Samuel Martin) Date: Mon, 29 Sep 2014 22:55:37 +0200 Subject: [PATCH 0 of 4 v3] Build-system: Cross-compilation support improvement In-Reply-To: References: Message-ID: Hi all, On Tue, Aug 26, 2014 at 9:40 AM, Samuel Martin wrote: > Is this a "444 No Response" answer? > > On Tue, Aug 12, 2014 at 4:03 PM, Samuel Martin wrote: >> ping? >> >> On Sat, Aug 2, 2014 at 1:14 AM, Samuel Martin wrote: >>> Hi all, >>> >>> >>> Here is the 3rd round of this short series improving nginx build-system >>> support for cross-compilation. >>> >>> This series fixes a couple of issues found in the previous submission. >>> It still tries to be as less intrusive as possible, and intends to make >>> easier integration in cross-compilataion frameworks such as Buildroot [1]. >>> >>> These patches include most of the changes needed for porperly supporting >>> the cross-compilation, except the sys_nerr guessing part [2], which cannot >>> merged in nginx because it is too unix-oriented and based on fragile >>> assumptions So, really, the nginx community is not interested in improving the cross-compilation support? If so, just take some time to answer but don't leave people in the dark, please. Note that this series addresses the comments done on the first post [3-6]. BTW, it's not something I want to push blindly, because: - in the Buildroot project [1], we try to send patches to the upstream project as much as possible patches (as long as the patches are clean enough to get accepted); - once integrated in Buildroot [1], automatic jobs [7] will run build-tests, so if further fixes are needed, we will do them; so we won't let this cross-compilation support unmaintained. >>> >>> [1] http://buildroot.net/ >>> [2] https://github.com/tSed/buildroot/blob/nginx-integration/package/nginx/nginx-0005-auto-unix-make-sys_nerr-guessing-cross-friendly.patch [3] http://mailman.nginx.org/pipermail/nginx-devel/2014-May/005292.html [4] http://mailman.nginx.org/pipermail/nginx-devel/2014-May/005290.html [5] http://mailman.nginx.org/pipermail/nginx-devel/2014-May/005291.html [6] http://mailman.nginx.org/pipermail/nginx-devel/2014-May/005293.html [7] http://autobuild.buildroot.org/ Yours, -- Samuel From mertsas at cisco.com Tue Sep 30 06:23:00 2014 From: mertsas at cisco.com (Martin =?utf-8?Q?Erts=C3=A5s?=) Date: Tue, 30 Sep 2014 08:23:00 +0200 Subject: [PATCH 0 of 4 v3] Build-system: Cross-compilation support improvement In-Reply-To: References: Message-ID: <20140930062259.GF8093@cisco.com> On Mon, Sep 29, 2014 at 10:55:37PM +0200, Samuel Martin wrote: > Hi all, > > On Tue, Aug 26, 2014 at 9:40 AM, Samuel Martin wrote: > > Is this a "444 No Response" answer? > > > > On Tue, Aug 12, 2014 at 4:03 PM, Samuel Martin wrote: > >> ping? > >> > >> On Sat, Aug 2, 2014 at 1:14 AM, Samuel Martin wrote: > >>> Hi all, > >>> > >>> > >>> Here is the 3rd round of this short series improving nginx build-system > >>> support for cross-compilation. > >>> > >>> This series fixes a couple of issues found in the previous submission. > >>> It still tries to be as less intrusive as possible, and intends to make > >>> easier integration in cross-compilataion frameworks such as Buildroot [1]. > >>> > >>> These patches include most of the changes needed for porperly supporting > >>> the cross-compilation, except the sys_nerr guessing part [2], which cannot > >>> merged in nginx because it is too unix-oriented and based on fragile > >>> assumptions > > So, really, the nginx community is not interested in improving the > cross-compilation support? > If so, just take some time to answer but don't leave people in the dark, please. > > Note that this series addresses the comments done on the first post [3-6]. > > BTW, it's not something I want to push blindly, because: > - in the Buildroot project [1], we try to send patches to the upstream > project as much as possible patches (as long as the patches are clean > enough to get accepted); > - once integrated in Buildroot [1], automatic jobs [7] will run > build-tests, so if further fixes are needed, we will do them; so we > won't let this cross-compilation support unmaintained. > Also, this is something we want here as well, as we are currently cross compiling nginx. - Martin > > >>> > >>> [1] http://buildroot.net/ > >>> [2] https://github.com/tSed/buildroot/blob/nginx-integration/package/nginx/nginx-0005-auto-unix-make-sys_nerr-guessing-cross-friendly.patch > > [3] http://mailman.nginx.org/pipermail/nginx-devel/2014-May/005292.html > [4] http://mailman.nginx.org/pipermail/nginx-devel/2014-May/005290.html > [5] http://mailman.nginx.org/pipermail/nginx-devel/2014-May/005291.html > [6] http://mailman.nginx.org/pipermail/nginx-devel/2014-May/005293.html > [7] http://autobuild.buildroot.org/ > > Yours, > > -- > Samuel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From thierry.magnien at sfr.com Tue Sep 30 09:41:40 2014 From: thierry.magnien at sfr.com (MAGNIEN, Thierry) Date: Tue, 30 Sep 2014 09:41:40 +0000 Subject: Variable visibility between 3rd party modules Message-ID: <5D103CE839D50E4CBC62C9FD7B83287CC9C492D8@EXCN015.encara.local.ads> Hi, In my own module, do I have a simple way to retrieve a variable which has been set by another module ? For example, GeoIP module sets the geoip_org variable. Is there a set of C functions that allow my module to retrieve this value ? Thanks a lot, Thierry From mdounin at mdounin.ru Tue Sep 30 11:18:40 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 30 Sep 2014 11:18:40 +0000 Subject: [nginx] Upstream keepalive: reset c->sent on cached connections. Message-ID: details: http://hg.nginx.org/nginx/rev/39befd3c0d84 branches: changeset: 5864:39befd3c0d84 user: Maxim Dounin date: Mon Sep 29 22:27:45 2014 +0400 description: Upstream keepalive: reset c->sent on cached connections. The c->sent is reset to 0 on each request by server-side http code, so do the same on client side. This allows to count number of bytes sent in a particular request. diffstat: src/http/modules/ngx_http_upstream_keepalive_module.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c --- a/src/http/modules/ngx_http_upstream_keepalive_module.c +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c @@ -248,6 +248,7 @@ ngx_http_upstream_get_keepalive_peer(ngx "get keepalive peer: using connection %p", c); c->idle = 0; + c->sent = 0; c->log = pc->log; c->read->log = pc->log; c->write->log = pc->log; From mdounin at mdounin.ru Tue Sep 30 13:27:46 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 30 Sep 2014 13:27:46 +0000 Subject: [nginx] nginx-1.7.6-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/a8d111bb6884 branches: changeset: 5865:a8d111bb6884 user: Maxim Dounin date: Tue Sep 30 17:20:32 2014 +0400 description: nginx-1.7.6-RELEASE diffstat: docs/xml/nginx/changes.xml | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 45 insertions(+), 0 deletions(-) diffs (55 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,51 @@ + + + + +?????????? ????????? limit_zone ?????? ?? ??????????????. + + +the deprecated "limit_zone" directive is not supported anymore. + + + + + +? ?????????? limit_conn_zone ? limit_req_zone ?????? ????? ???????????? +?????????? ?????????? ??????????. + + +the "limit_conn_zone" and "limit_req_zone" directives now can be used +with combinations of multiple variables. + + + + + +??? ????????? ???????? FastCGI-??????? ?? ?????? +???? ??????? ????? ???????????? ???????????. + + +request body might be transmitted incorrectly +when retrying a FastCGI request to the next upstream server. + + + + + +? ???????????? ? syslog. + + +in logging to syslog. + + + + + + From mdounin at mdounin.ru Tue Sep 30 13:27:53 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 30 Sep 2014 13:27:53 +0000 Subject: [nginx] release-1.7.6 tag Message-ID: details: http://hg.nginx.org/nginx/rev/a215d9021f13 branches: changeset: 5866:a215d9021f13 user: Maxim Dounin date: Tue Sep 30 17:20:33 2014 +0400 description: release-1.7.6 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -375,3 +375,4 @@ 0bd223a546192fdf2e862f33938f4ec2a3b5b283 fe7cd01828d5ca7491059f0690bb4453645eb28b release-1.7.3 cbb146b120296852e781079d5138b04495bab6df release-1.7.4 fe129aa02db9001d220f1db7c3c056f79482c111 release-1.7.5 +a8d111bb68847f61d682a3c8792fecb2e52efa2c release-1.7.6 From mdounin at mdounin.ru Tue Sep 30 15:34:43 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 30 Sep 2014 19:34:43 +0400 Subject: [PATCH 0 of 4 v3] Build-system: Cross-compilation support improvement In-Reply-To: References: Message-ID: <20140930153443.GO69200@mdounin.ru> Hello! On Mon, Sep 29, 2014 at 10:55:37PM +0200, Samuel Martin wrote: > Hi all, > > On Tue, Aug 26, 2014 at 9:40 AM, Samuel Martin wrote: > > Is this a "444 No Response" answer? > > > > On Tue, Aug 12, 2014 at 4:03 PM, Samuel Martin wrote: > >> ping? > >> > >> On Sat, Aug 2, 2014 at 1:14 AM, Samuel Martin wrote: > >>> Hi all, > >>> > >>> > >>> Here is the 3rd round of this short series improving nginx build-system > >>> support for cross-compilation. > >>> > >>> This series fixes a couple of issues found in the previous submission. > >>> It still tries to be as less intrusive as possible, and intends to make > >>> easier integration in cross-compilataion frameworks such as Buildroot [1]. > >>> > >>> These patches include most of the changes needed for porperly supporting > >>> the cross-compilation, except the sys_nerr guessing part [2], which cannot > >>> merged in nginx because it is too unix-oriented and based on fragile > >>> assumptions > > So, really, the nginx community is not interested in improving the > cross-compilation support? > If so, just take some time to answer but don't leave people in the dark, please. As previously said[1], while cross-compilation is something good to have, we don't consider it to be a "must-have" feature. Unfortunately, I currently have no time to work on this even as a reviewer, and the patches provided doesn't look good enough for me as is. [1] http://mailman.nginx.org/pipermail/nginx-devel/2014-May/005318.html -- Maxim Dounin http://nginx.org/ From bsfranks at gmail.com Tue Sep 30 15:47:52 2014 From: bsfranks at gmail.com (bsfranks at gmail.com) Date: Tue, 30 Sep 2014 08:47:52 -0700 Subject: Variable visibility between 3rd party modules In-Reply-To: <5D103CE839D50E4CBC62C9FD7B83287CC9C492D8@EXCN015.encara.local.ads> References: <5D103CE839D50E4CBC62C9FD7B83287CC9C492D8@EXCN015.encara.local.ads> Message-ID: Hi Thierry, On Tue, Sep 30, 2014 at 2:41 AM, MAGNIEN, Thierry wrote: > Hi, > > In my own module, do I have a simple way to retrieve a variable which has > been set by another module ? > > For example, GeoIP module sets the geoip_org variable. Is there a set of C > functions that allow my module to retrieve this value ? > > Thanks a lot, > Thierry > Check out the ngx_http_get_variable() function. Hope this helps! Ben -------------- next part -------------- An HTML attachment was scrubbed... URL: From agentzh at gmail.com Tue Sep 30 22:10:42 2014 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Tue, 30 Sep 2014 15:10:42 -0700 Subject: [BUG] New memory invalid read regression in resolver since nginx 1.7.5 Message-ID: Hello! I've noticed that the code re-factoring in the resolver in nginx 1.7.5 introduces a new regression that can cause memory invalid reads when --with-debug is used to build the nginx. The issue still exists in nginx 1.7.6. The following standalone and minimal example can trigger this: location = /main { return 200 "foo"; addition_types text/plain; add_after_body /sub; } location = /sub { resolver 8.8.8.8; set $myurl "http://not-exist.agentzh.org"; proxy_pass $myurl; } Accessing /main with valgrind yields the following error: ==16903== Invalid read of size 4 ==16903== at 0x41FDE6: ngx_event_del_timer (ngx_event_timer.h:38) ==16903== by 0x420A86: ngx_resolve_name_done (ngx_resolver.c:415) ==16903== by 0x46B90A: ngx_http_upstream_finalize_request (ngx_http_upstream.c:3586) ==16903== by 0x466090: ngx_http_upstream_resolve_handler (ngx_http_upstream.c:941) ==16903== by 0x422D0B: ngx_resolver_process_a (ngx_resolver.c:1580) ==16903== by 0x422715: ngx_resolver_process_response (ngx_resolver.c:1369) ==16903== by 0x42221A: ngx_resolver_read_response (ngx_resolver.c:1239) ==16903== by 0x438C9A: ngx_epoll_process_events (ngx_epoll_module.c:685) ==16903== by 0x4296CC: ngx_process_events_and_timers (ngx_event.c:248) ==16903== by 0x4356CB: ngx_single_process_cycle (ngx_process_cycle.c:319) ==16903== by 0x403700: main (nginx.c:404) ==16903== Address 0x4e7e448 is 24 bytes inside a block of size 128 free'd ==16903== at 0x4A07577: free (vg_replace_malloc.c:468) ==16903== by 0x424CF8: ngx_resolver_free_locked (ngx_resolver.c:2888) ==16903== by 0x424C42: ngx_resolver_free_node (ngx_resolver.c:2838) ==16903== by 0x422CD6: ngx_resolver_process_a (ngx_resolver.c:1571) ==16903== by 0x422715: ngx_resolver_process_response (ngx_resolver.c:1369) ==16903== by 0x42221A: ngx_resolver_read_response (ngx_resolver.c:1239) ==16903== by 0x438C9A: ngx_epoll_process_events (ngx_epoll_module.c:685) ==16903== by 0x4296CC: ngx_process_events_and_timers (ngx_event.c:248) ==16903== by 0x4356CB: ngx_single_process_cycle (ngx_process_cycle.c:319) ==16903== by 0x403700: main (nginx.c:404) ==16903== The offending line is ngx_event_timer.h:38: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "event timer del: %d: %M", ngx_event_ident(ev->data), ev->timer.key); while ev->data here is the resolver node that has already been freed up earlier in ngx_resolver_free_node. nginx -V output: $ /opt/nginx/sbin/nginx -V nginx version: nginx/1.7.5 built by gcc 4.8.3 20140911 (Red Hat 4.8.3-7) (GCC) configure arguments: --with-cc-opt=-O0 --prefix=/opt/nginx --with-debug --with-http_addition_module Regards, -agentzh From agentzh at gmail.com Tue Sep 30 22:51:40 2014 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Tue, 30 Sep 2014 15:51:40 -0700 Subject: [BUG] New memory invalid read regression in resolver since nginx 1.7.5 In-Reply-To: References: Message-ID: Hello! On Tue, Sep 30, 2014 at 3:10 PM, Yichun Zhang (agentzh) wrote: > ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, > "event timer del: %d: %M", > ngx_event_ident(ev->data), ev->timer.key); > There is another issue here: it seems that ngx_event_ident() assumes ev->data is an ngx_connection_t pointer: #define ngx_event_ident(p) ((ngx_connection_t *) (p))->fd But in fact, ev->data can point to any thing. Maybe it makes more sense to just output the pointer value of ev->data here? How about the following patch? # HG changeset patch # User Yichun Zhang # Date 1412117428 25200 # Tue Sep 30 15:50:28 2014 -0700 # Node ID 1ff0f68d9376e3d184d65814a6372856bf65cfcd # Parent a215d9021f137b9e2d4f69c37c7f992a2bef12c6 Event: ngx_event_ident should not assume ev->data to be an ngx_connection_t. This change also fixes an invalid memory read in the resolver since 1.7.5 when --with-debug is used in the build. diff -r a215d9021f13 -r 1ff0f68d9376 src/event/ngx_event.h --- a/src/event/ngx_event.h Tue Sep 30 17:20:33 2014 +0400 +++ b/src/event/ngx_event.h Tue Sep 30 15:50:28 2014 -0700 @@ -526,7 +526,7 @@ ngx_int_t ngx_send_lowat(ngx_connection_ /* used in ngx_log_debugX() */ -#define ngx_event_ident(p) ((ngx_connection_t *) (p))->fd +#define ngx_event_ident(p) (p) #include diff -r a215d9021f13 -r 1ff0f68d9376 src/event/ngx_event_timer.c --- a/src/event/ngx_event_timer.c Tue Sep 30 17:20:33 2014 +0400 +++ b/src/event/ngx_event_timer.c Tue Sep 30 15:50:28 2014 -0700 @@ -99,7 +99,7 @@ ngx_event_expire_timers(void) ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer)); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "event timer del: %d: %M", + "event timer del: %p: %M", ngx_event_ident(ev->data), ev->timer.key); ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer); diff -r a215d9021f13 -r 1ff0f68d9376 src/event/ngx_event_timer.h --- a/src/event/ngx_event_timer.h Tue Sep 30 17:20:33 2014 +0400 +++ b/src/event/ngx_event_timer.h Tue Sep 30 15:50:28 2014 -0700 @@ -36,7 +36,7 @@ static ngx_inline void ngx_event_del_timer(ngx_event_t *ev) { ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "event timer del: %d: %M", + "event timer del: %p: %M", ngx_event_ident(ev->data), ev->timer.key); ngx_mutex_lock(ngx_event_timer_mutex); @@ -75,7 +75,7 @@ ngx_event_add_timer(ngx_event_t *ev, ngx if (ngx_abs(diff) < NGX_TIMER_LAZY_DELAY) { ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "event timer: %d, old: %M, new: %M", + "event timer: %p, old: %M, new: %M", ngx_event_ident(ev->data), ev->timer.key, key); return; } @@ -86,7 +86,7 @@ ngx_event_add_timer(ngx_event_t *ev, ngx ev->timer.key = key; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "event timer add: %d: %M:%M", + "event timer add: %p: %M:%M", ngx_event_ident(ev->data), timer, ev->timer.key); ngx_mutex_lock(ngx_event_timer_mutex); -------------- next part -------------- A non-text attachment was scrubbed... Name: event-ident.patch Type: text/x-patch Size: 2764 bytes Desc: not available URL: