Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2014-10-08 22:14:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2014-10-07 16:01:19.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.haproxy.new/haproxy.changes 2014-10-08 22:14:31.000000000 +0200 @@ -1,0 +2,30 @@ +Wed Oct 8 12:53:41 UTC 2014 - [email protected] + +- update to 1.5.5 + - DOC: indicate that weight zero is reported as DRAIN + - DOC: Address issue where documentation is excluded due to a gitignore rule + - This update includes all previous patches since 1.5.4 + +- Removed patches: + - 0001-DOC-clearly-state-that-the-show-sess-output-format-i.patch + - 0002-MINOR-stats-fix-minor-typo-fix-in-stats_dump_errors_.patch + - 0003-MEDIUM-Improve-signal-handling-in-systemd-wrapper.patch + - 0004-MINOR-Also-accept-SIGHUP-SIGTERM-in-systemd-wrapper.patch + - 0005-DOC-indicate-in-the-doc-that-track-sc-can-wait-if-da.patch + - 0006-MEDIUM-http-enable-header-manipulation-for-101-respo.patch + - 0007-BUG-MEDIUM-config-propagate-frontend-to-backend-proc.patch + - 0008-MEDIUM-config-properly-propagate-process-binding-bet.patch + - 0009-MEDIUM-config-make-the-frontends-automatically-bind-.patch + - 0010-MEDIUM-config-compute-the-exact-bind-process-before-.patch + - 0011-MEDIUM-config-only-warn-if-stats-are-attached-to-mul.patch + - 0012-MEDIUM-config-report-it-when-tcp-request-rules-are-m.patch + - 0013-MINOR-config-detect-the-case-where-a-tcp-request-con.patch + - 0014-MEDIUM-systemd-wrapper-support-multiple-executable-v.patch + - 0015-BUG-MEDIUM-remove-debugging-code-from-systemd-wrappe.patch + - 0016-BUG-MEDIUM-http-adjust-close-mode-when-switching-to-.patch + - 0017-BUG-MINOR-config-don-t-propagate-process-binding-on-.patch + - 0018-BUG-MEDIUM-check-rule-less-tcp-check-must-detect-con.patch + - 0019-BUG-MINOR-tcp-check-report-the-correct-failed-step-i.patch + - 0020-BUG-MINOR-config-don-t-propagate-process-binding-for.patch + +------------------------------------------------------------------- Old: ---- 0001-DOC-clearly-state-that-the-show-sess-output-format-i.patch 0002-MINOR-stats-fix-minor-typo-fix-in-stats_dump_errors_.patch 0003-MEDIUM-Improve-signal-handling-in-systemd-wrapper.patch 0004-MINOR-Also-accept-SIGHUP-SIGTERM-in-systemd-wrapper.patch 0005-DOC-indicate-in-the-doc-that-track-sc-can-wait-if-da.patch 0006-MEDIUM-http-enable-header-manipulation-for-101-respo.patch 0007-BUG-MEDIUM-config-propagate-frontend-to-backend-proc.patch 0008-MEDIUM-config-properly-propagate-process-binding-bet.patch 0009-MEDIUM-config-make-the-frontends-automatically-bind-.patch 0010-MEDIUM-config-compute-the-exact-bind-process-before-.patch 0011-MEDIUM-config-only-warn-if-stats-are-attached-to-mul.patch 0012-MEDIUM-config-report-it-when-tcp-request-rules-are-m.patch 0013-MINOR-config-detect-the-case-where-a-tcp-request-con.patch 0014-MEDIUM-systemd-wrapper-support-multiple-executable-v.patch 0015-BUG-MEDIUM-remove-debugging-code-from-systemd-wrappe.patch 0016-BUG-MEDIUM-http-adjust-close-mode-when-switching-to-.patch 0017-BUG-MINOR-config-don-t-propagate-process-binding-on-.patch 0018-BUG-MEDIUM-check-rule-less-tcp-check-must-detect-con.patch 0019-BUG-MINOR-tcp-check-report-the-correct-failed-step-i.patch 0020-BUG-MINOR-config-don-t-propagate-process-binding-for.patch haproxy-1.5.4.tar.gz New: ---- haproxy-1.5.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.W0GvxX/_old 2014-10-08 22:14:32.000000000 +0200 +++ /var/tmp/diff_new_pack.W0GvxX/_new 2014-10-08 22:14:32.000000000 +0200 @@ -33,7 +33,7 @@ %bcond_without apparmor Name: haproxy -Version: 1.5.4 +Version: 1.5.5 Release: 0 # # @@ -61,46 +61,6 @@ Patch2: haproxy-makefile_lib.patch Patch3: sec-options.patch Patch4: haproxy-1.5_check_config_before_start.patch -# PATCH-FIX-UPSTREAM: DOC: clearly state that the "show sess" output format is not fixed -Patch5: 0001-DOC-clearly-state-that-the-show-sess-output-format-i.patch -# PATCH-FIX-UPSTREAM: MINOR: stats: fix minor typo fix in stats_dump_errors_to_buffer() -Patch6: 0002-MINOR-stats-fix-minor-typo-fix-in-stats_dump_errors_.patch -# PATCH-FIX-UPSTREAM: MEDIUM: Improve signal handling in systemd wrapper. -Patch7: 0003-MEDIUM-Improve-signal-handling-in-systemd-wrapper.patch -# PATCH-FIX-UPSTREAM: MINOR: Also accept SIGHUP/SIGTERM in systemd-wrapper -Patch8: 0004-MINOR-Also-accept-SIGHUP-SIGTERM-in-systemd-wrapper.patch -# PATCH-FIX-UPSTREAM: DOC: indicate in the doc that track-sc* can wait if data are missing -Patch9: 0005-DOC-indicate-in-the-doc-that-track-sc-can-wait-if-da.patch -# PATCH-FIX-UPSTREAM: MEDIUM: http: enable header manipulation for 101 responses -Patch10: 0006-MEDIUM-http-enable-header-manipulation-for-101-respo.patch -# PATCH-FIX-UPSTREAM: BUG/MEDIUM: config: propagate frontend to backend process binding again. -Patch11: 0007-BUG-MEDIUM-config-propagate-frontend-to-backend-proc.patch -# PATCH-FIX-UPSTREAM: MEDIUM: config: properly propagate process binding between proxies -Patch12: 0008-MEDIUM-config-properly-propagate-process-binding-bet.patch -# PATCH-FIX-UPSTREAM: MEDIUM: config: make the frontends automatically bind to the listeners' processes -Patch13: 0009-MEDIUM-config-make-the-frontends-automatically-bind-.patch -# PATCH-FIX-UPSTREAM: MEDIUM: config: compute the exact bind-process before listener's maxaccept -Patch14: 0010-MEDIUM-config-compute-the-exact-bind-process-before-.patch -# PATCH-FIX-UPSTREAM: MEDIUM: config: only warn if stats are attached to multi-process bind directives -Patch15: 0011-MEDIUM-config-only-warn-if-stats-are-attached-to-mul.patch -# PATCH-FIX-UPSTREAM: MEDIUM: config: report it when tcp-request rules are misplaced -Patch16: 0012-MEDIUM-config-report-it-when-tcp-request-rules-are-m.patch -# PATCH-FIX-UPSTREAM: MINOR: config: detect the case where a tcp-request content rule has no inspect-delay -Patch17: 0013-MINOR-config-detect-the-case-where-a-tcp-request-con.patch -# PATCH-FIX-UPSTREAM: MEDIUM: systemd-wrapper: support multiple executable versions and names -Patch18: 0014-MEDIUM-systemd-wrapper-support-multiple-executable-v.patch -# PATCH-FIX-UPSTREAM: BUG/MEDIUM: remove debugging code from systemd-wrapper -Patch19: 0015-BUG-MEDIUM-remove-debugging-code-from-systemd-wrappe.patch -# PATCH-FIX-UPSTREAM: BUG/MEDIUM: http: adjust close mode when switching to backend -Patch20: 0016-BUG-MEDIUM-http-adjust-close-mode-when-switching-to-.patch -# PATCH-FIX-UPSTREAM: BUG/MINOR: config: don't propagate process binding on fatal errors. -Patch21: 0017-BUG-MINOR-config-don-t-propagate-process-binding-on-.patch -# PATCH-FIX-UPSTREAM: BUG/MEDIUM: check: rule-less tcp-check must detect connect failures -Patch22: 0018-BUG-MEDIUM-check-rule-less-tcp-check-must-detect-con.patch -# PATCH-FIX-UPSTREAM: BUG/MINOR: tcp-check: report the correct failed step in the status -Patch23: 0019-BUG-MINOR-tcp-check-report-the-correct-failed-step-i.patch -# PATCH-FIX-UPSTREAM: BUG/MINOR: config: don't propagate process binding for dynamic use_backend -Patch24: 0020-BUG-MINOR-config-don-t-propagate-process-binding-for.patch Source99: haproxy-rpmlintrc # @@ -135,26 +95,6 @@ %patch2 %patch3 %patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 -%patch16 -p1 -%patch17 -p1 -%patch18 -p1 -%patch19 -p1 -%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -%patch24 -p1 %build %{__make} \ ++++++ haproxy-1.5.4.tar.gz -> haproxy-1.5.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/.gitignore new/haproxy-1.5.5/.gitignore --- old/haproxy-1.5.4/.gitignore 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/.gitignore 2014-10-08 10:07:23.000000000 +0200 @@ -12,6 +12,7 @@ *.log* *.trace* haproxy-* +!doc/haproxy-*.txt !src/*.c make-* dlmalloc.c diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/CHANGELOG new/haproxy-1.5.5/CHANGELOG --- old/haproxy-1.5.4/CHANGELOG 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/CHANGELOG 2014-10-08 10:07:23.000000000 +0200 @@ -1,6 +1,30 @@ ChangeLog : =========== +2014/10/08 : 1.5.5 + - DOC: Address issue where documentation is excluded due to a gitignore rule. + - MEDIUM: Improve signal handling in systemd wrapper. + - BUG/MINOR: config: don't propagate process binding for dynamic use_backend + - MINOR: Also accept SIGHUP/SIGTERM in systemd-wrapper + - DOC: clearly state that the "show sess" output format is not fixed + - MINOR: stats: fix minor typo fix in stats_dump_errors_to_buffer() + - DOC: indicate in the doc that track-sc* can wait if data are missing + - MEDIUM: http: enable header manipulation for 101 responses + - BUG/MEDIUM: config: propagate frontend to backend process binding again. + - MEDIUM: config: properly propagate process binding between proxies + - MEDIUM: config: make the frontends automatically bind to the listeners' processes + - MEDIUM: config: compute the exact bind-process before listener's maxaccept + - MEDIUM: config: only warn if stats are attached to multi-process bind directives + - MEDIUM: config: report it when tcp-request rules are misplaced + - MINOR: config: detect the case where a tcp-request content rule has no inspect-delay + - MEDIUM: systemd-wrapper: support multiple executable versions and names + - BUG/MEDIUM: remove debugging code from systemd-wrapper + - BUG/MEDIUM: http: adjust close mode when switching to backend + - BUG/MINOR: config: don't propagate process binding on fatal errors. + - BUG/MEDIUM: check: rule-less tcp-check must detect connect failures + - BUG/MINOR: tcp-check: report the correct failed step in the status + - DOC: indicate that weight zero is reported as DRAIN + 2014/09/02 : 1.5.4 - BUG: config: error in http-response replace-header number of arguments - BUG/MINOR: Fix search for -p argument in systemd wrapper. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/VERDATE new/haproxy-1.5.5/VERDATE --- old/haproxy-1.5.4/VERDATE 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/VERDATE 2014-10-08 10:07:23.000000000 +0200 @@ -1,2 +1,2 @@ $Format:%ci$ -2014/09/02 +2014/10/07 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/VERSION new/haproxy-1.5.5/VERSION --- old/haproxy-1.5.4/VERSION 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/VERSION 2014-10-08 10:07:23.000000000 +0200 @@ -1 +1 @@ -1.5.4 +1.5.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/doc/configuration.txt new/haproxy-1.5.5/doc/configuration.txt --- old/haproxy-1.5.4/doc/configuration.txt 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/doc/configuration.txt 2014-10-08 10:07:23.000000000 +0200 @@ -1905,6 +1905,10 @@ Each "bind" line may further be limited to a subset of the proxy's processes, please consult the "process" bind keyword in section 5.1. + When a frontend has no explicit "bind-process" line, it tries to bind to all + the processes referenced by its "bind" lines. That means that frontends can + easily adapt to their listeners' processes. + If some backends are referenced by frontends bound to other processes, the backend automatically inherits the frontend's processes. @@ -7470,9 +7474,9 @@ contents will always be immediately present when the rule is evaluated first. Tracking layer7 information is also possible provided that the information - are present when the rule is processed. The current solution for making the - rule engine wait for such information is to set an inspect delay and to - condition its execution with an ACL relying on such information. + are present when the rule is processed. The rule processing engine is able to + wait until the inspect delay expires when the data to be tracked is not yet + available. Example: # Accept HTTP requests containing a Host header saying "example.com" @@ -7497,12 +7501,12 @@ Example: # Track the last IP from X-Forwarded-For tcp-request inspect-delay 10s - tcp-request content track-sc0 hdr(x-forwarded-for,-1) if HTTP + tcp-request content track-sc0 hdr(x-forwarded-for,-1) Example: # track request counts per "base" (concatenation of Host+URL) tcp-request inspect-delay 10s - tcp-request content track-sc0 base table req-rate if HTTP + tcp-request content track-sc0 base table req-rate Example: track per-frontend and per-backend counters, block abusers at the frontend when the backend detects abuse. @@ -8645,7 +8649,9 @@ - An ASCII representation of a positive integer percentage, e.g. "75%". Values in this format will set the weight proportional to the initial - weight of a server as configured when haproxy starts. + weight of a server as configured when haproxy starts. Note that a zero + weight is reported on the stats page as "DRAIN" since it has the same + effect on the server (it's removed from the LB farm). - The word "ready". This will turn the server's administrative state to the READY mode, thus cancelling any DRAIN or MAINT state @@ -13734,9 +13740,11 @@ of "show sess" (it corresponds to the session pointer). Those information are useless to most users but may be used by haproxy developers to troubleshoot a complex bug. The output format is intentionally not documented so that it can - freely evolve depending on demands. The special id "all" dumps the states of - all sessions, which can be avoided as much as possible as it is highly CPU - intensive and can take a lot of time. + freely evolve depending on demands. You may find a description of all fields + returned in src/dumpstats.c + + The special id "all" dumps the states of all sessions, which must be avoided + as much as possible as it is highly CPU intensive and can take a lot of time. show stat [<iid> <type> <sid>] Dump statistics in the CSV format. By passing <id>, <type> and <sid>, it is diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/examples/haproxy.spec new/haproxy-1.5.5/examples/haproxy.spec --- old/haproxy-1.5.4/examples/haproxy.spec 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/examples/haproxy.spec 2014-10-08 10:07:23.000000000 +0200 @@ -1,6 +1,6 @@ Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments Name: haproxy -Version: 1.5.4 +Version: 1.5.5 Release: 1 License: GPL Group: System Environment/Daemons @@ -76,6 +76,9 @@ %attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name} %changelog +* Wed Oct 8 2014 Willy Tarreau <[email protected]> +- updated to 1.5.5 + * Tue Sep 2 2014 Willy Tarreau <[email protected]> - updated to 1.5.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/include/common/cfgparse.h new/haproxy-1.5.5/include/common/cfgparse.h --- old/haproxy-1.5.4/include/common/cfgparse.h 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/include/common/cfgparse.h 2014-10-08 10:07:23.000000000 +0200 @@ -73,6 +73,8 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err); int cfg_register_section(char *section_name, int (*section_parser)(const char *, int, char **, int)); +int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg); +int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg); /* * Sends a warning if proxy <proxy> does not have at least one of the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/include/proto/proto_http.h new/haproxy-1.5.5/include/proto/proto_http.h --- old/haproxy-1.5.4/include/proto/proto_http.h 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/include/proto/proto_http.h 2014-10-08 10:07:23.000000000 +0200 @@ -112,6 +112,7 @@ void http_init_txn(struct session *s); void http_end_txn(struct session *s); void http_reset_txn(struct session *s); +void http_adjust_conn_mode(struct session *s, struct http_txn *txn, struct http_msg *msg); struct http_req_rule *parse_http_req_cond(const char **args, const char *file, int linenum, struct proxy *proxy); struct http_res_rule *parse_http_res_cond(const char **args, const char *file, int linenum, struct proxy *proxy); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/src/cfgparse.c new/haproxy-1.5.5/src/cfgparse.c --- old/haproxy-1.5.4/src/cfgparse.c 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/src/cfgparse.c 2014-10-08 10:07:23.000000000 +0200 @@ -317,6 +317,19 @@ return 0; } +/* Report a warning if a rule is placed after a 'tcp-request content' rule. + * Return 1 if the warning has been emitted, otherwise 0. + */ +int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg) +{ + if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) { + Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n", + file, line, arg); + return 1; + } + return 0; +} + /* Report a warning if a rule is placed after a 'block' rule. * Return 1 if the warning has been emitted, otherwise 0. */ @@ -408,6 +421,31 @@ return 0; } +/* report a warning if a "tcp request connection" rule is dangerously placed */ +int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg) +{ + return warnif_rule_after_tcp_cont(proxy, file, line, arg) || + warnif_rule_after_block(proxy, file, line, arg) || + warnif_rule_after_http_req(proxy, file, line, arg) || + warnif_rule_after_reqxxx(proxy, file, line, arg) || + warnif_rule_after_reqadd(proxy, file, line, arg) || + warnif_rule_after_redirect(proxy, file, line, arg) || + warnif_rule_after_use_backend(proxy, file, line, arg) || + warnif_rule_after_use_server(proxy, file, line, arg); +} + +/* report a warning if a "tcp request content" rule is dangerously placed */ +int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg) +{ + return warnif_rule_after_block(proxy, file, line, arg) || + warnif_rule_after_http_req(proxy, file, line, arg) || + warnif_rule_after_reqxxx(proxy, file, line, arg) || + warnif_rule_after_reqadd(proxy, file, line, arg) || + warnif_rule_after_redirect(proxy, file, line, arg) || + warnif_rule_after_use_backend(proxy, file, line, arg) || + warnif_rule_after_use_server(proxy, file, line, arg); +} + /* report a warning if a block rule is dangerously placed */ int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg) { @@ -5932,6 +5970,66 @@ return err_code; } +/* This function propagates processes from frontend <from> to backend <to> so + * that it is always guaranteed that a backend pointed to by a frontend is + * bound to all of its processes. After that, if the target is a "listen" + * instance, the function recursively descends the target's own targets along + * default_backend, use_backend rules, and reqsetbe rules. Since the bits are + * checked first to ensure that <to> is already bound to all processes of + * <from>, there is no risk of looping and we ensure to follow the shortest + * path to the destination. + * + * It is possible to set <to> to NULL for the first call so that the function + * takes care of visiting the initial frontend in <from>. + * + * It is important to note that the function relies on the fact that all names + * have already been resolved. + */ +void propagate_processes(struct proxy *from, struct proxy *to) +{ + struct switching_rule *rule; + struct hdr_exp *exp; + + if (to) { + /* check whether we need to go down */ + if (from->bind_proc && + (from->bind_proc & to->bind_proc) == from->bind_proc) + return; + + if (!from->bind_proc && !to->bind_proc) + return; + + to->bind_proc = from->bind_proc ? + (to->bind_proc | from->bind_proc) : 0; + + /* now propagate down */ + from = to; + } + + if (!from->cap & PR_CAP_FE) + return; + + /* default_backend */ + if (from->defbe.be) + propagate_processes(from, from->defbe.be); + + /* use_backend */ + list_for_each_entry(rule, &from->switching_rules, list) { + if (rule->dynamic) + continue; + to = rule->be.backend; + propagate_processes(from, to); + } + + /* reqsetbe */ + for (exp = from->req_exp; exp != NULL; exp = exp->next) { + if (exp->action != ACT_SETBE) + continue; + to = (struct proxy *)exp->replace; + propagate_processes(from, to); + } +} + /* * Returns the error code, 0 if OK, or any combination of : * - ERR_ABORT: must abort ASAP @@ -5984,12 +6082,11 @@ proxy = next; } - while (curproxy != NULL) { + for (curproxy = proxy; curproxy; curproxy = curproxy->next) { struct switching_rule *rule; struct server_rule *srule; struct sticking_rule *mrule; struct tcp_rule *trule; - struct listener *listener; unsigned int next_id; int nbproc; @@ -6057,14 +6154,6 @@ } } - /* here, if bind_proc is null, it means no limit, otherwise it's explicit. - * We now check how many processes the proxy will effectively run on. - */ - - nbproc = global.nbproc; - if (curproxy->bind_proc) - nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc)); - if (global.nbproc > 1 && curproxy->table.peers.name) { Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n", curproxy->id); @@ -6162,12 +6251,6 @@ } else { free(curproxy->defbe.name); curproxy->defbe.be = target; - /* we force the backend to be present on at least all of - * the frontend's processes. - */ - if (target->bind_proc) - target->bind_proc = curproxy->bind_proc ? - (target->bind_proc | curproxy->bind_proc) : 0; /* Emit a warning if this proxy also has some servers */ if (curproxy->srv) { @@ -6200,12 +6283,6 @@ } else { free((void *)exp->replace); exp->replace = (const char *)target; - /* we force the backend to be present on at least all of - * the frontend's processes. - */ - if (target->bind_proc) - target->bind_proc = curproxy->bind_proc ? - (target->bind_proc | curproxy->bind_proc) : 0; } } } @@ -6254,16 +6331,10 @@ } else { free((void *)rule->be.name); rule->be.backend = target; - /* we force the backend to be present on at least all of - * the frontend's processes. - */ - if (target->bind_proc) - target->bind_proc = curproxy->bind_proc ? - (target->bind_proc | curproxy->bind_proc) : 0; } } - /* find the target proxy for 'use_backend' rules */ + /* find the target server for 'use_server' rules */ list_for_each_entry(srule, &curproxy->server_rules, list) { struct server *target = findserver(curproxy, srule->srv.name); @@ -6929,6 +7000,29 @@ newsrv = newsrv->next; } + /* check if we have a frontend with "tcp-request content" looking at L7 + * with no inspect-delay + */ + if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) { + list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) { + if (trule->action == TCP_ACT_CAPTURE && + !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC)) + break; + if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) && + !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC)) + break; + } + + if (&trule->list != &curproxy->tcp_req.inspect_rules) { + Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request" + " contents were found in a frontend without any 'tcp-request inspect-delay' setting." + " This means that these rules will randomly find their contents. This can be fixed by" + " setting the tcp-request inspect-delay.\n", + proxy_type_str(curproxy), curproxy->id); + err_code |= ERR_WARN; + } + } + if (curproxy->cap & PR_CAP_FE) { if (!curproxy->accept) curproxy->accept = frontend_accept; @@ -6965,6 +7059,90 @@ if (curproxy->options2 & PR_O2_RDPC_PRST) curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE; } + } + + /***********************************************************/ + /* At this point, target names have already been resolved. */ + /***********************************************************/ + + /* Check multi-process mode compatibility */ + + if (global.nbproc > 1 && global.stats_fe) { + list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) { + unsigned long mask; + + mask = nbits(global.nbproc); + if (global.stats_fe->bind_proc) + mask &= global.stats_fe->bind_proc; + + if (bind_conf->bind_proc) + mask &= bind_conf->bind_proc; + + /* stop here if more than one process is used */ + if (popcount(mask) > 1) + break; + } + if (&bind_conf->by_fe != &global.stats_fe->conf.bind) { + Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n"); + } + } + + /* Make each frontend inherit bind-process from its listeners when not specified. */ + for (curproxy = proxy; curproxy; curproxy = curproxy->next) { + if (curproxy->bind_proc) + continue; + + list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) { + unsigned long mask; + + mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL; + curproxy->bind_proc |= mask; + } + + if (!curproxy->bind_proc) + curproxy->bind_proc = ~0UL; + } + + if (global.stats_fe) { + list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) { + unsigned long mask; + + mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL; + global.stats_fe->bind_proc |= mask; + } + if (!global.stats_fe->bind_proc) + global.stats_fe->bind_proc = ~0UL; + } + + /* propagate bindings from frontends to backends. Don't do it if there + * are any fatal errors as we must not call it with unresolved proxies. + */ + if (!cfgerr) { + for (curproxy = proxy; curproxy; curproxy = curproxy->next) { + if (curproxy->cap & PR_CAP_FE) + propagate_processes(curproxy, NULL); + } + } + + /* Bind each unbound backend to all processes when not specified. */ + for (curproxy = proxy; curproxy; curproxy = curproxy->next) { + if (curproxy->bind_proc) + continue; + curproxy->bind_proc = ~0UL; + } + + /*******************************************************/ + /* At this step, all proxies have a non-null bind_proc */ + /*******************************************************/ + + /* perform the final checks before creating tasks */ + + for (curproxy = proxy; curproxy; curproxy = curproxy->next) { + struct listener *listener; + unsigned int next_id; + int nbproc; + + nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc)); #ifdef USE_OPENSSL /* Configure SSL for each bind line. @@ -7078,8 +7256,19 @@ if (nbproc > 1) { if (curproxy->uri_auth) { - Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n", - curproxy->id); + int count, maxproc = 0; + + list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) { + count = popcount(bind_conf->bind_proc); + if (count > maxproc) + maxproc = count; + } + /* backends have 0, frontends have 1 or more */ + if (maxproc != 1) + Warning("Proxy '%s': in multi-process mode, stats will be" + " limited to process assigned to the current request.\n", + curproxy->id); + if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) { Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n", curproxy->id); @@ -7109,29 +7298,6 @@ curproxy->id); cfgerr++; } - - curproxy = curproxy->next; - } - - /* Check multi-process mode compatibility */ - if (global.nbproc > 1 && global.stats_fe) { - list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) { - unsigned long mask; - - mask = nbits(global.nbproc); - if (global.stats_fe->bind_proc) - mask &= global.stats_fe->bind_proc; - - if (bind_conf->bind_proc) - mask &= bind_conf->bind_proc; - - /* stop here if more than one process is used */ - if (popcount(mask) > 1) - break; - } - if (&bind_conf->by_fe != &global.stats_fe->conf.bind) { - Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n"); - } } /* automatically compute fullconn if not set. We must not do it in the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/src/checks.c new/haproxy-1.5.5/src/checks.c --- old/haproxy-1.5.4/src/checks.c 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/src/checks.c 2014-10-08 10:07:23.000000000 +0200 @@ -580,6 +580,7 @@ struct check *check = conn->owner; const char *err_msg; struct chunk *chk; + int step; if (check->result != CHK_RES_UNKNOWN) return; @@ -599,19 +600,27 @@ chk = get_trash_chunk(); if (check->type == PR_O2_TCPCHK_CHK) { - chunk_printf(chk, " at step %d of tcp-check", tcpcheck_get_step_id(check->server)); - /* we were looking for a string */ - if (check->current_step && check->current_step->action == TCPCHK_ACT_CONNECT) { - chunk_appendf(chk, " (connect)"); - } - else if (check->current_step && check->current_step->action == TCPCHK_ACT_EXPECT) { - if (check->current_step->string) - chunk_appendf(chk, " (string '%s')", check->current_step->string); - else if (check->current_step->expect_regex) - chunk_appendf(chk, " (expect regex)"); - } - else if (check->current_step && check->current_step->action == TCPCHK_ACT_SEND) { - chunk_appendf(chk, " (send)"); + step = tcpcheck_get_step_id(check->server); + if (!step) + chunk_printf(chk, " at initial connection step of tcp-check"); + else { + chunk_printf(chk, " at step %d of tcp-check", step); + /* we were looking for a string */ + if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_CONNECT) { + if (check->last_started_step->port) + chunk_appendf(chk, " (connect port %d)" ,check->last_started_step->port); + else + chunk_appendf(chk, " (connect)"); + } + else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_EXPECT) { + if (check->last_started_step->string) + chunk_appendf(chk, " (string '%s')", check->last_started_step->string); + else if (check->last_started_step->expect_regex) + chunk_appendf(chk, " (expect regex)"); + } + else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_SEND) { + chunk_appendf(chk, " (send)"); + } } } @@ -1818,6 +1827,10 @@ struct tcpcheck_rule *cur = NULL, *next = NULL; int i = 0; + /* not even started anything yet => step 0 = initial connect */ + if (!s->check.current_step) + return 0; + cur = s->check.last_started_step; /* no step => first step */ @@ -1837,20 +1850,34 @@ static void tcpcheck_main(struct connection *conn) { char *contentptr; - struct list *head = NULL; struct tcpcheck_rule *cur = NULL; int done = 0, ret = 0; - struct check *check = conn->owner; struct server *s = check->server; struct task *t = check->task; + struct list *head = &s->proxy->tcpcheck_rules; - /* - * don't do anything until the connection is established but if we're running - * first step which must be a connect + /* here, we know that the check is complete or that it failed */ + if (check->result != CHK_RES_UNKNOWN) + goto out_end_tcpcheck; + + /* We have 4 possibilities here : + * 1. we've not yet attempted step 1, and step 1 is a connect, so no + * connection attempt was made yet ; + * 2. we've not yet attempted step 1, and step 1 is a not connect or + * does not exist (no rule), so a connection attempt was made + * before coming here. + * 3. we're coming back after having started with step 1, so we may + * be waiting for a connection attempt to complete. + * 4. the connection + handshake are complete + * + * #2 and #3 are quite similar, we want both the connection and the + * handshake to complete before going any further. Thus we must always + * wait for a connection to complete unless we're before and existing + * step 1. */ - if (check->current_step && (!(conn->flags & CO_FL_CONNECTED))) { - /* update expire time, should be done by process_chk */ + if ((!(conn->flags & CO_FL_CONNECTED) || (conn->flags & CO_FL_HANDSHAKE)) && + (check->current_step || LIST_ISEMPTY(head))) { /* we allow up to min(inter, timeout.connect) for a connection * to establish but only when timeout.check is set * as it may be to short for a full check otherwise @@ -1867,16 +1894,15 @@ return; } - /* here, we know that the connection is established */ - if (check->result != CHK_RES_UNKNOWN) + /* special case: option tcp-check with no rule, a connect is enough */ + if (LIST_ISEMPTY(head)) { + set_server_check_status(check, HCHK_STATUS_L4OK, NULL); goto out_end_tcpcheck; + } - /* head is be the first element of the double chained list */ - head = &s->proxy->tcpcheck_rules; - - /* no step means first step - * initialisation */ + /* no step means first step initialisation */ if (check->current_step == NULL) { + check->last_started_step = NULL; check->bo->p = check->bo->data; check->bo->o = 0; check->bi->p = check->bi->data; @@ -1891,9 +1917,6 @@ cur = check->current_step; } - if (conn->flags & CO_FL_HANDSHAKE) - return; - /* It's only the rules which will enable send/recv */ __conn_data_stop_both(conn); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/src/dumpstats.c new/haproxy-1.5.5/src/dumpstats.c --- old/haproxy-1.5.4/src/dumpstats.c 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/src/dumpstats.c 2014-10-08 10:07:23.000000000 +0200 @@ -6045,7 +6045,7 @@ break; case 1: chunk_appendf(&trash, - " backend %s (#%d) : invalid response\n" + " backend %s (#%d): invalid response\n" " frontend %s (#%d)", appctx->ctx.errors.px->id, appctx->ctx.errors.px->uuid, es->oe->id, es->oe->uuid); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/src/haproxy-systemd-wrapper.c new/haproxy-1.5.5/src/haproxy-systemd-wrapper.c --- old/haproxy-1.5.4/src/haproxy-systemd-wrapper.c 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/src/haproxy-systemd-wrapper.c 2014-10-08 10:07:23.000000000 +0200 @@ -22,24 +22,42 @@ #define SD_DEBUG "<7>" #define SD_NOTICE "<5>" +static volatile sig_atomic_t caught_signal; + static char *pid_file = "/run/haproxy.pid"; static int wrapper_argc; static char **wrapper_argv; +/* returns the path to the haproxy binary into <buffer>, whose size indicated + * in <buffer_size> must be at least 1 byte long. + */ static void locate_haproxy(char *buffer, size_t buffer_size) { char *end = NULL; + int len; - if (readlink("/proc/self/exe", buffer, buffer_size) > 0) - end = strrchr(buffer, '/'); + len = readlink("/proc/self/exe", buffer, buffer_size - 1); + if (len == -1) + goto fail; + + buffer[len] = 0; + end = strrchr(buffer, '/'); + if (end == NULL) + goto fail; - if (end == NULL) { - strncpy(buffer, "/usr/sbin/haproxy", buffer_size); + if (strcmp(end + strlen(end) - 16, "-systemd-wrapper") == 0) { + end[strlen(end) - 16] = '\0'; return; } + end[1] = '\0'; strncpy(end + 1, "haproxy", buffer + buffer_size - (end + 1)); buffer[buffer_size - 1] = '\0'; + return; + fail: + strncpy(buffer, "/usr/sbin/haproxy", buffer_size); + buffer[buffer_size - 1] = '\0'; + return; } static void spawn_haproxy(char **pid_strv, int nb_pid) @@ -103,7 +121,12 @@ return read; } -static void sigusr2_handler(int signum __attribute__((unused))) +static void signal_handler(int signum) +{ + caught_signal = signum; +} + +static void do_restart(void) { setenv(REEXEC_FLAG, "1", 1); fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: re-executing\n"); @@ -111,7 +134,7 @@ execv(wrapper_argv[0], wrapper_argv); } -static void sigint_handler(int signum __attribute__((unused))) +static void do_shutdown(void) { int i, pid; char **pid_strv = NULL; @@ -147,25 +170,23 @@ --argc; ++argv; init(argc, argv); - signal(SIGINT, &sigint_handler); - signal(SIGUSR2, &sigusr2_handler); + struct sigaction sa; + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = &signal_handler; + sigaction(SIGUSR2, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); if (getenv(REEXEC_FLAG) != NULL) { /* We are being re-executed: restart HAProxy gracefully */ int i; char **pid_strv = NULL; int nb_pid = read_pids(&pid_strv); - sigset_t sigs; unsetenv(REEXEC_FLAG); spawn_haproxy(pid_strv, nb_pid); - /* Unblock SIGUSR2 which was blocked by the signal handler - * before re-exec */ - sigprocmask(SIG_BLOCK, NULL, &sigs); - sigdelset(&sigs, SIGUSR2); - sigprocmask(SIG_SETMASK, &sigs, NULL); - for (i = 0; i < nb_pid; ++i) free(pid_strv[i]); free(pid_strv); @@ -176,8 +197,16 @@ } status = -1; - while (-1 != wait(&status) || errno == EINTR) - ; + while (-1 != wait(&status) || errno == EINTR) { + if (caught_signal == SIGUSR2 || caught_signal == SIGHUP) { + caught_signal = 0; + do_restart(); + } + else if (caught_signal == SIGINT || caught_signal == SIGTERM) { + caught_signal = 0; + do_shutdown(); + } + } fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: exit, haproxy RC=%d\n", status); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/src/proto_http.c new/haproxy-1.5.5/src/proto_http.c --- old/haproxy-1.5.4/src/proto_http.c 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/src/proto_http.c 2014-10-08 10:07:23.000000000 +0200 @@ -2393,6 +2393,59 @@ return 0; } +void http_adjust_conn_mode(struct session *s, struct http_txn *txn, struct http_msg *msg) +{ + int tmp = TX_CON_WANT_KAL; + + if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) { + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN || + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN) + tmp = TX_CON_WANT_TUN; + + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL) + tmp = TX_CON_WANT_TUN; + } + + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL || + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) { + /* option httpclose + server_close => forceclose */ + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL) + tmp = TX_CON_WANT_CLO; + else + tmp = TX_CON_WANT_SCL; + } + + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL || + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL) + tmp = TX_CON_WANT_CLO; + + if ((txn->flags & TX_CON_WANT_MSK) < tmp) + txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp; + + if (!(txn->flags & TX_HDR_CONN_PRS) && + (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) { + /* parse the Connection header and possibly clean it */ + int to_del = 0; + if ((msg->flags & HTTP_MSGF_VER_11) || + ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL && + !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA))) + to_del |= 2; /* remove "keep-alive" */ + if (!(msg->flags & HTTP_MSGF_VER_11)) + to_del |= 1; /* remove "close" */ + http_parse_connection_header(txn, msg, to_del); + } + + /* check if client or config asks for explicit close in KAL/SCL */ + if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL || + (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) && + ((txn->flags & TX_HDR_CONN_CLO) || /* "connection: close" */ + (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */ + !(msg->flags & HTTP_MSGF_XFER_LEN) || /* no length known => close */ + s->fe->state == PR_STSTOPPED)) /* frontend is stopping */ + txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO; +} /* This stream analyser waits for a complete HTTP request. It returns 1 if the * processing can continue on next analysers, or zero if it either needs more @@ -2929,58 +2982,8 @@ * time. */ if (!(txn->flags & TX_HDR_CONN_PRS) || - ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE))) { - int tmp = TX_CON_WANT_KAL; - - if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) { - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN || - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN) - tmp = TX_CON_WANT_TUN; - - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL) - tmp = TX_CON_WANT_TUN; - } - - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL || - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) { - /* option httpclose + server_close => forceclose */ - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL) - tmp = TX_CON_WANT_CLO; - else - tmp = TX_CON_WANT_SCL; - } - - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL || - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL) - tmp = TX_CON_WANT_CLO; - - if ((txn->flags & TX_CON_WANT_MSK) < tmp) - txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp; - - if (!(txn->flags & TX_HDR_CONN_PRS) && - (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) { - /* parse the Connection header and possibly clean it */ - int to_del = 0; - if ((msg->flags & HTTP_MSGF_VER_11) || - ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL && - !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA))) - to_del |= 2; /* remove "keep-alive" */ - if (!(msg->flags & HTTP_MSGF_VER_11)) - to_del |= 1; /* remove "close" */ - http_parse_connection_header(txn, msg, to_del); - } - - /* check if client or config asks for explicit close in KAL/SCL */ - if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL || - (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) && - ((txn->flags & TX_HDR_CONN_CLO) || /* "connection: close" */ - (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */ - !(msg->flags & HTTP_MSGF_XFER_LEN) || /* no length known => close */ - s->fe->state == PR_STSTOPPED)) /* frontend is stopping */ - txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO; - } + ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE))) + http_adjust_conn_mode(s, txn, msg); /* end of job, return OK */ req->analysers &= ~an_bit; @@ -6249,7 +6252,7 @@ /* add response headers from the rule sets in the same order */ list_for_each_entry(wl, &rule_set->rsp_add, list) { - if (txn->status < 200) + if (txn->status < 200 && txn->status != 101) break; if (wl->cond) { int ret = acl_exec_cond(wl->cond, px, s, txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL); @@ -6270,7 +6273,7 @@ } /* OK that's all we can do for 1xx responses */ - if (unlikely(txn->status < 200)) + if (unlikely(txn->status < 200 && txn->status != 101)) goto skip_header_mangling; /* @@ -6283,7 +6286,7 @@ /* * Check for cache-control or pragma headers if required. */ - if ((s->be->options & PR_O_CHK_CACHE) || (s->be->ck_opts & PR_CK_NOC)) + if (((s->be->options & PR_O_CHK_CACHE) || (s->be->ck_opts & PR_CK_NOC)) && txn->status != 101) check_response_for_cacheability(s, rep); /* @@ -6399,9 +6402,11 @@ * Adjust "Connection: close" or "Connection: keep-alive" if needed. * If an "Upgrade" token is found, the header is left untouched in order * not to have to deal with some client bugs : some of them fail an upgrade - * if anything but "Upgrade" is present in the Connection header. + * if anything but "Upgrade" is present in the Connection header. We don't + * want to touch any 101 response either since it's switching to another + * protocol. */ - if (!(txn->flags & TX_HDR_CONN_UPG) && + if ((txn->status != 101) && !(txn->flags & TX_HDR_CONN_UPG) && (((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) || ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL))) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/src/proto_tcp.c new/haproxy-1.5.5/src/proto_tcp.c --- old/haproxy-1.5.4/src/proto_tcp.c 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/src/proto_tcp.c 2014-10-08 10:07:23.000000000 +0200 @@ -1711,6 +1711,8 @@ warn++; } + /* the following function directly emits the warning */ + warnif_misplaced_tcp_cont(curpx, file, line, args[0]); LIST_ADDQ(&curpx->tcp_req.inspect_rules, &rule->list); } else if (strcmp(args[1], "connection") == 0) { @@ -1754,6 +1756,8 @@ warn++; } + /* the following function directly emits the warning */ + warnif_misplaced_tcp_conn(curpx, file, line, args[0]); LIST_ADDQ(&curpx->tcp_req.l4_rules, &rule->list); } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.5.4/src/proxy.c new/haproxy-1.5.5/src/proxy.c --- old/haproxy-1.5.4/src/proxy.c 2014-09-02 13:54:16.000000000 +0200 +++ new/haproxy-1.5.5/src/proxy.c 2014-10-08 10:07:23.000000000 +0200 @@ -955,6 +955,14 @@ http_init_txn(s); } + /* If we chain to an HTTP backend running a different HTTP mode, we + * have to re-adjust the desired keep-alive/close mode to accommodate + * both the frontend's and the backend's modes. + */ + if (s->fe->mode == PR_MODE_HTTP && be->mode == PR_MODE_HTTP && + ((s->fe->options & PR_O_HTTP_MODE) != (be->options & PR_O_HTTP_MODE))) + http_adjust_conn_mode(s, &s->txn, &s->txn.req); + /* If an LB algorithm needs to access some pre-parsed body contents, * we must not start to forward anything until the connection is * confirmed otherwise we'll lose the pointer to these data and -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
