Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2017-03-02 19:38:34 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Thu Mar 2 19:38:34 2017 rev:47 rq:460861 version:1.7.3 Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2017-02-03 17:42:18.141625423 +0100 +++ /work/SRC/openSUSE:Factory/.haproxy.new/haproxy.changes 2017-03-02 19:38:35.568961394 +0100 @@ -1,0 +2,20 @@ +Tue Feb 28 11:31:02 UTC 2017 - kgronl...@suse.com + +- Update to version 1.7.3: + * BUG/MINOR: stream: Fix how backend-specific analyzers are set on a stream + * BUG/MEDIUM: tcp: don't poll for write when connect() succeeds + * BUG/MINOR: unix: fix connect's polling in case no data are scheduled + * BUG/MINOR: lua: Map.end are not reliable because "end" is a reserved keyword + * MINOR: dns: give ability to dns_init_resolvers() to close a socket when requested + * BUG/MAJOR: dns: restart sockets after fork() + * MINOR: chunks: implement a simple dynamic allocator for trash buffers + * BUG/MEDIUM: http: prevent redirect from overwriting a buffer + * BUG/MEDIUM: filters: Do not truncate HTTP response when body length is undefined + * BUG/MEDIUM: http: Prevent replace-header from overwriting a buffer + * BUG/MINOR: http: Return an error when a replace-header rule failed on the response + * BUG/MINOR: sendmail: The return of vsnprintf is not cleanly tested + * BUG/MAJOR: lua segmentation fault when the request is like 'GET ?arg=val HTTP/1.1' + * BUG/MEDIUM: config: reject anything but "if" or "unless" after a use-backend rule + * MINOR: http: don't close when redirect location doesn't start with "/" + +------------------------------------------------------------------- Old: ---- haproxy-1.7.2.tar.gz New: ---- haproxy-1.7.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.QrU3j0/_old 2017-03-02 19:38:36.372847639 +0100 +++ /var/tmp/diff_new_pack.QrU3j0/_new 2017-03-02 19:38:36.372847639 +0100 @@ -41,7 +41,7 @@ %bcond_without apparmor Name: haproxy -Version: 1.7.2 +Version: 1.7.3 Release: 0 # # ++++++ _service ++++++ --- /var/tmp/diff_new_pack.QrU3j0/_old 2017-03-02 19:38:36.404843111 +0100 +++ /var/tmp/diff_new_pack.QrU3j0/_new 2017-03-02 19:38:36.408842545 +0100 @@ -3,8 +3,8 @@ <param name="url">http://git.haproxy.org/git/haproxy-1.7.git</param> <param name="scm">git</param> <param name="filename">haproxy</param> - <param name="versionformat">1.7.2</param> - <param name="revision">v1.7.2</param> + <param name="versionformat">1.7.3</param> + <param name="revision">v1.7.3</param> <param name="changesgenerate">enable</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.QrU3j0/_old 2017-03-02 19:38:36.424840281 +0100 +++ /var/tmp/diff_new_pack.QrU3j0/_new 2017-03-02 19:38:36.428839716 +0100 @@ -3,4 +3,4 @@ <param name="url">http://git.haproxy.org/git/haproxy-1.6.git</param> <param name="changesrevision">864bf78c3b6898eb12ece5f0a44032090f26f57f</param></service><service name="tar_scm"> <param name="url">http://git.haproxy.org/git/haproxy-1.7.git</param> - <param name="changesrevision">ddb646ee9182df570017ddf280873a1360a28898</param></service></servicedata> \ No newline at end of file + <param name="changesrevision">9cb532a34ae190b350cdeb8bbbae25d524b10949</param></service></servicedata> \ No newline at end of file ++++++ haproxy-1.7.2.tar.gz -> haproxy-1.7.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/CHANGELOG new/haproxy-1.7.3/CHANGELOG --- old/haproxy-1.7.2/CHANGELOG 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/CHANGELOG 2017-02-28 09:59:23.000000000 +0100 @@ -1,6 +1,27 @@ ChangeLog : =========== +2017/02/28 : 1.7.3 + - BUG/MINOR: stream: Fix how backend-specific analyzers are set on a stream + - BUILD: ssl: fix build on OpenSSL 1.0.0 + - BUILD: ssl: silence a warning reported for ERR_remove_state() + - BUILD: ssl: eliminate warning with OpenSSL 1.1.0 regarding RAND_pseudo_bytes() + - BUG/MEDIUM: tcp: don't poll for write when connect() succeeds + - BUG/MINOR: unix: fix connect's polling in case no data are scheduled + - DOC: lua: improve links + - BUG/MINOR: lua: Map.end are not reliable because "end" is a reserved keyword + - MINOR: dns: give ability to dns_init_resolvers() to close a socket when requested + - BUG/MAJOR: dns: restart sockets after fork() + - MINOR: chunks: implement a simple dynamic allocator for trash buffers + - BUG/MEDIUM: http: prevent redirect from overwriting a buffer + - BUG/MEDIUM: filters: Do not truncate HTTP response when body length is undefined + - BUG/MEDIUM: http: Prevent replace-header from overwriting a buffer + - BUG/MINOR: http: Return an error when a replace-header rule failed on the response + - BUG/MINOR: sendmail: The return of vsnprintf is not cleanly tested + - BUG/MAJOR: lua segmentation fault when the request is like 'GET ?arg=val HTTP/1.1' + - BUG/MEDIUM: config: reject anything but "if" or "unless" after a use-backend rule + - MINOR: http: don't close when redirect location doesn't start with "/" + 2017/01/13 : 1.7.2 - BUG/MEDIUM: lua: In some case, the return of sample-fetches is ignored (2) - SCRIPTS: git-show-backports: fix a harmless typo diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/README new/haproxy-1.7.3/README --- old/haproxy-1.7.2/README 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/README 2017-02-28 09:59:23.000000000 +0100 @@ -3,7 +3,7 @@ ---------------------- version 1.7 willy tarreau - 2017/01/13 + 2017/02/28 1) How to build it diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/VERDATE new/haproxy-1.7.3/VERDATE --- old/haproxy-1.7.2/VERDATE 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/VERDATE 2017-02-28 09:59:23.000000000 +0100 @@ -1,2 +1,2 @@ $Format:%ci$ -2017/01/13 +2017/02/28 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/VERSION new/haproxy-1.7.3/VERSION --- old/haproxy-1.7.2/VERSION 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/VERSION 2017-02-28 09:59:23.000000000 +0100 @@ -1 +1 @@ -1.7.2 +1.7.3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/doc/configuration.txt new/haproxy-1.7.3/doc/configuration.txt --- old/haproxy-1.7.2/doc/configuration.txt 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/doc/configuration.txt 2017-02-28 09:59:23.000000000 +0100 @@ -4,7 +4,7 @@ ---------------------- version 1.7 willy tarreau - 2017/01/13 + 2017/02/28 This document covers the configuration language as implemented in the version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/doc/lua-api/index.rst new/haproxy-1.7.3/doc/lua-api/index.rst --- old/haproxy-1.7.2/doc/lua-api/index.rst 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/doc/lua-api/index.rst 2017-02-28 09:59:23.000000000 +0100 @@ -165,6 +165,14 @@ This attribute is an integer, it contains the value of the loglevel "debug" (7). +.. js:attribute:: core.proxies + + **context**: task, action, sample-fetch, converter + + This attribute is an array of declared proxies (frontend and backends). Each + proxy give an access to his list of listeners and servers. Each entry is of + type :ref:`proxy_class` + .. js:function:: core.log(loglevel, msg) **context**: body, init, task, action, sample-fetch, converter @@ -176,19 +184,20 @@ :param integer loglevel: Is the log level asociated with the message. It is a number between 0 and 7. :param string msg: The log content. - :see: core.emerg, core.alert, core.crit, core.err, core.warning, core.notice, - core.info, core.debug (log level definitions) - :see: code.Debug - :see: core.Info - :see: core.Warning - :see: core.Alert + :see: :js:attr:`core.emerg`, :js:attr:`core.alert`, :js:attr:`core.crit`, + :js:attr:`core.err`, :js:attr:`core.warning`, :js:attr:`core.notice`, + :js:attr:`core.info`, :js:attr:`core.debug` (log level definitions) + :see: :js:func:`core.Debug` + :see: :js:func:`core.Info` + :see: :js:func:`core.Warning` + :see: :js:func:`core.Alert` .. js:function:: core.Debug(msg) **context**: body, init, task, action, sample-fetch, converter :param string msg: The log content. - :see: log + :see: :js:func:`core.log` Does the same job than: @@ -204,7 +213,7 @@ **context**: body, init, task, action, sample-fetch, converter :param string msg: The log content. - :see: log + :see: :js:func:`core.log` .. code-block:: lua @@ -218,7 +227,7 @@ **context**: body, init, task, action, sample-fetch, converter :param string msg: The log content. - :see: log + :see: :js:func:`core.log` .. code-block:: lua @@ -232,7 +241,7 @@ **context**: body, init, task, action, sample-fetch, converter :param string msg: The log content. - :see: log + :see: :js:func:`core.log` .. code-block:: lua @@ -1097,8 +1106,8 @@ **warning** some sample fetches are not available in some context. These limitations are specified in this documentation when theire useful. - :see: TXN.f - :see: TXN.sf + :see: :js:attr:`TXN.f` + :see: :js:attr:`TXN.sf` Fetches are useful for: @@ -1131,8 +1140,8 @@ HAProxy documentation "configuration.txt" for more information about her usage. Its the chapter 7.3.1. - :see: TXN.c - :see: TXN.sc + :see: :js:attr:`TXN.c` + :see: :js:attr:`TXN.sc` Converters provides statefull transformation. They are useful for: @@ -1275,7 +1284,7 @@ :param class_http http: The related http object. :returns: array of headers. - :see: HTTP.res_get_headers() + :see: :js:func:`HTTP.res_get_headers` This is the form of the returned array: @@ -1296,7 +1305,7 @@ :param class_http http: The related http object. :returns: array of headers. - :see: HTTP.req_get_headers() + :see: :js:func:`HTTP.req_get_headers` This is the form of the returned array: @@ -1319,7 +1328,7 @@ :param class_http http: The related http object. :param string name: The header name. :param string value: The header value. - :see: HTTP.res_add_header() + :see: :js:func:`HTTP.res_add_header` .. js:function:: HTTP.res_add_header(http, name, value) @@ -1329,7 +1338,7 @@ :param class_http http: The related http object. :param string name: The header name. :param string value: The header value. - :see: HTTP.req_add_header() + :see: :js:func:`HTTP.req_add_header` .. js:function:: HTTP.req_del_header(http, name) @@ -1338,7 +1347,7 @@ :param class_http http: The related http object. :param string name: The header name. - :see: HTTP.res_del_header() + :see: :js:func:`HTTP.res_del_header` .. js:function:: HTTP.res_del_header(http, name) @@ -1347,7 +1356,7 @@ :param class_http http: The related http object. :param string name: The header name. - :see: HTTP.req_del_header() + :see: :js:func:`HTTP.req_del_header` .. js:function:: HTTP.req_set_header(http, name, value) @@ -1357,7 +1366,7 @@ :param class_http http: The related http object. :param string name: The header name. :param string value: The header value. - :see: HTTP.res_set_header() + :see: :js:func:`HTTP.res_set_header` This function does the same work as the folowwing code: @@ -1377,7 +1386,7 @@ :param class_http http: The related http object. :param string name: The header name. :param string value: The header value. - :see: HTTP.req_rep_header() + :see: :js:func:`HTTP.req_rep_header()` .. js:function:: HTTP.req_rep_header(http, name, regex, replace) @@ -1390,7 +1399,7 @@ :param string name: The header name. :param string regex: The match regular expression. :param string replace: The replacement value. - :see: HTTP.res_rep_header() + :see: :js:func:`HTTP.res_rep_header()` .. js:function:: HTTP.res_rep_header(http, name, regex, string) @@ -1403,7 +1412,7 @@ :param string name: The header name. :param string regex: The match regular expression. :param string replace: The replacement value. - :see: HTTP.req_replace_header() + :see: :js:func:`HTTP.req_rep_header()` .. js:function:: HTTP.req_set_method(http, method) @@ -1516,13 +1525,14 @@ :param integer loglevel: Is the log level asociated with the message. It is a number between 0 and 7. :param string msg: The log content. - :see: core.emerg, core.alert, core.crit, core.err, core.warning, core.notice, - core.info, core.debug (log level definitions) - :see: TXN.deflog - :see: TXN.Debug - :see: TXN.Info - :see: TXN.Warning - :see: TXN.Alert + :see: :js:attr:`core.emerg`, :js:attr:`core.alert`, :js:attr:`core.crit`, + :js:attr:`core.err`, :js:attr:`core.warning`, :js:attr:`core.notice`, + :js:attr:`core.info`, :js:attr:`core.debug` (log level definitions) + :see: :js:func:`TXN.deflog` + :see: :js:func:`TXN.Debug` + :see: :js:func:`TXN.Info` + :see: :js:func:`TXN.Warning` + :see: :js:func:`TXN.Alert` .. js:function:: TXN.deflog(TXN, msg) @@ -1531,13 +1541,13 @@ :param class_txn txn: The class txn object containing the data. :param string msg: The log content. - :see: TXN.log + :see: :js:func:`TXN.log .. js:function:: TXN.Debug(txn, msg) :param class_txn txn: The class txn object containing the data. :param string msg: The log content. - :see: TXN.log + :see: :js:func:`TXN.log` Does the same job than: @@ -1552,7 +1562,7 @@ :param class_txn txn: The class txn object containing the data. :param string msg: The log content. - :see: TXN.log + :see: :js:func:`TXN.log` .. code-block:: lua @@ -1565,7 +1575,7 @@ :param class_txn txn: The class txn object containing the data. :param string msg: The log content. - :see: TXN.log + :see: :js:func:`TXN.log` .. code-block:: lua @@ -1578,7 +1588,7 @@ :param class_txn txn: The class txn object containing the data. :param string msg: The log content. - :see: TXN.log + :see: :js:func:`TXN.log` .. code-block:: lua @@ -1647,7 +1657,9 @@ :param class_txn txn: The class txn object containing the data. :param integer loglevel: The required log level. This variable can be one of - :see: core.<loglevel> + :see: :js:attr:`core.emerg`, :js:attr:`core.alert`, :js:attr:`core.crit`, + :js:attr:`core.err`, :js:attr:`core.warning`, :js:attr:`core.notice`, + :js:attr:`core.info`, :js:attr:`core.debug` (log level definitions) .. js:function:: TXN.set_tos(txn, tos) @@ -1851,7 +1863,7 @@ default = "usa" -- Create and load map - geo = Map.new("geo.map", Map.ip); + geo = Map.new("geo.map", Map._ip); -- Create new fetch that returns the user country core.register_fetches("country", function(txn) @@ -1876,60 +1888,76 @@ return loc; end); -.. js:attribute:: Map.int +.. js:attribute:: Map._int See the HAProxy configuration.txt file, chapter "Using ACLs and fetching samples" ans subchapter "ACL basics" to understand this pattern matching method. -.. js:attribute:: Map.ip + Note that :js:attr:`Map.int` is also available for compatibility. + +.. js:attribute:: Map._ip See the HAProxy configuration.txt file, chapter "Using ACLs and fetching samples" ans subchapter "ACL basics" to understand this pattern matching method. -.. js:attribute:: Map.str + Note that :js:attr:`Map.ip` is also available for compatibility. + +.. js:attribute:: Map._str See the HAProxy configuration.txt file, chapter "Using ACLs and fetching samples" ans subchapter "ACL basics" to understand this pattern matching method. -.. js:attribute:: Map.beg + Note that :js:attr:`Map.str` is also available for compatibility. + +.. js:attribute:: Map._beg See the HAProxy configuration.txt file, chapter "Using ACLs and fetching samples" ans subchapter "ACL basics" to understand this pattern matching method. -.. js:attribute:: Map.sub + Note that :js:attr:`Map.beg` is also available for compatibility. + +.. js:attribute:: Map._sub See the HAProxy configuration.txt file, chapter "Using ACLs and fetching samples" ans subchapter "ACL basics" to understand this pattern matching method. -.. js:attribute:: Map.dir + Note that :js:attr:`Map.sub` is also available for compatibility. + +.. js:attribute:: Map._dir See the HAProxy configuration.txt file, chapter "Using ACLs and fetching samples" ans subchapter "ACL basics" to understand this pattern matching method. -.. js:attribute:: Map.dom + Note that :js:attr:`Map.dir` is also available for compatibility. + +.. js:attribute:: Map._dom See the HAProxy configuration.txt file, chapter "Using ACLs and fetching samples" ans subchapter "ACL basics" to understand this pattern matching method. -.. js:attribute:: Map.end + Note that :js:attr:`Map.dom` is also available for compatibility. + +.. js:attribute:: Map._end See the HAProxy configuration.txt file, chapter "Using ACLs and fetching samples" ans subchapter "ACL basics" to understand this pattern matching method. -.. js:attribute:: Map.reg +.. js:attribute:: Map._reg See the HAProxy configuration.txt file, chapter "Using ACLs and fetching samples" ans subchapter "ACL basics" to understand this pattern matching method. + Note that :js:attr:`Map.reg` is also available for compatibility. + .. js:function:: Map.new(file, method) @@ -1939,7 +1967,10 @@ :param integer method: Is the map pattern matching method. See the attributes of the Map class. :returns: a class Map object. - :see: The Map attributes. + :see: The Map attributes: :js:attr:`Map._int`, :js:attr:`Map._ip`, + :js:attr:`Map._str`, :js:attr:`Map._beg`, :js:attr:`Map._sub`, + :js:attr:`Map._dir`, :js:attr:`Map._dom`, :js:attr:`Map._end` and + :js:attr:`Map._reg`. .. js:function:: Map.lookup(map, str) @@ -2126,13 +2157,13 @@ .. js:function:: AppletHTTP.get_priv(applet) - Return Lua data stored in the current transaction (with the - `AppletHTTP.set_priv()`) function. If no data are stored, it returns a nil - value. + Return Lua data stored in the current transaction. If no data are stored, + it returns a nil value. :param class_AppletHTTP applet: An :ref:`applethttp_class` :returns: the opaque data previsously stored, or nil if nothing is avalaible. + :see: :js:func:`AppletHTTP.set_priv` .. js:function:: AppletHTTP.set_priv(applet, data) @@ -2141,6 +2172,7 @@ :param class_AppletHTTP applet: An :ref:`applethttp_class` :param opaque data: The data which is stored in the transaction. + :see: :js:func:`AppletHTTP.get_priv` .. _applettcp_class: @@ -2207,13 +2239,13 @@ .. js:function:: AppletTCP.get_priv(applet) - Return Lua data stored in the current transaction (with the - `AppletTCP.set_priv()`) function. If no data are stored, it returns a nil - value. + Return Lua data stored in the current transaction. If no data are stored, + it returns a nil value. :param class_AppletTCP applet: An :ref:`applettcp_class` :returns: the opaque data previsously stored, or nil if nothing is avalaible. + :see: :js:func:`AppletTCP.set_priv` .. js:function:: AppletTCP.set_priv(applet, data) @@ -2222,6 +2254,7 @@ :param class_AppletTCP applet: An :ref:`applettcp_class` :param opaque data: The data which is stored in the transaction. + :see: :js:func:`AppletTCP.get_priv` External Lua libraries ====================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/examples/haproxy.spec new/haproxy-1.7.3/examples/haproxy.spec --- old/haproxy-1.7.2/examples/haproxy.spec 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/examples/haproxy.spec 2017-02-28 09:59:23.000000000 +0100 @@ -1,6 +1,6 @@ Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments Name: haproxy -Version: 1.7.2 +Version: 1.7.3 Release: 1 License: GPL Group: System Environment/Daemons @@ -74,6 +74,9 @@ %attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name} %changelog +* Tue Feb 28 2017 Willy Tarreau <w...@1wt.eu> +- updated to 1.7.3 + * Fri Jan 13 2017 Willy Tarreau <w...@1wt.eu> - updated to 1.7.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/include/common/chunk.h new/haproxy-1.7.3/include/common/chunk.h --- old/haproxy-1.7.2/include/common/chunk.h 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/include/common/chunk.h 2017-02-28 09:59:23.000000000 +0100 @@ -26,6 +26,7 @@ #include <string.h> #include <common/config.h> +#include <common/memory.h> /* describes a chunk of string */ @@ -35,6 +36,8 @@ int len; /* current size of the string from first to last char. <0 = uninit. */ }; +struct pool_head *pool2_trash; + /* function prototypes */ int chunk_printf(struct chunk *chk, const char *fmt, ...) @@ -50,6 +53,16 @@ int alloc_trash_buffers(int bufsize); void free_trash_buffers(void); struct chunk *get_trash_chunk(void); +struct chunk *alloc_trash_chunk(void); + +/* + * free a trash chunk allocated by alloc_trash_chunk(). NOP on NULL. + */ +static inline void free_trash_chunk(struct chunk *chunk) +{ + pool_free2(pool2_trash, chunk); +} + static inline void chunk_reset(struct chunk *chk) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/include/proto/dns.h new/haproxy-1.7.3/include/proto/dns.h --- old/haproxy-1.7.2/include/proto/dns.h 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/include/proto/dns.h 2017-02-28 09:59:23.000000000 +0100 @@ -30,7 +30,7 @@ int dns_hostname_validation(const char *string, char **err); int dns_build_query(int query_id, int query_type, char *hostname_dn, int hostname_dn_len, char *buf, int bufsize); struct task *dns_process_resolve(struct task *t); -int dns_init_resolvers(void); +int dns_init_resolvers(int close_socket); uint16_t dns_rnd16(void); int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct dns_response_packet *dns_p); int dns_get_ip_from_response(struct dns_response_packet *dns_p, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/include/proto/openssl-compat.h new/haproxy-1.7.3/include/proto/openssl-compat.h --- old/haproxy-1.7.2/include/proto/openssl-compat.h 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/include/proto/openssl-compat.h 2017-02-28 09:59:23.000000000 +0100 @@ -56,16 +56,7 @@ #if (OPENSSL_VERSION_NUMBER < 0x1000000fL) -/* - * Functions introduced in OpenSSL 1.0.1 - */ -static inline int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len) -{ - s->sid_ctx_length = sid_ctx_len; - memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); - return 1; -} - +/* Functions introduced in OpenSSL 1.0.0 */ static inline int EVP_PKEY_base_id(const EVP_PKEY *pkey) { return EVP_PKEY_type(pkey->type); @@ -86,6 +77,18 @@ #endif +#if (OPENSSL_VERSION_NUMBER < 0x1000100fL) +/* + * Functions introduced in OpenSSL 1.0.1 + */ +static inline int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len) +{ + s->sid_ctx_length = sid_ctx_len; + memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); + return 1; +} +#endif + #if (OPENSSL_VERSION_NUMBER < 0x1010000fL) || defined(LIBRESSL_VERSION_NUMBER) /* * Functions introduced in OpenSSL 1.1.0 and not yet present in LibreSSL @@ -147,4 +150,25 @@ #define __OPENSSL_110_CONST__ #endif +/* ERR_remove_state() was deprecated in 1.0.0 in favor of + * ERR_remove_thread_state(), which was in turn deprecated in + * 1.1.0 and does nothing anymore. Let's simply silently kill + * it. + */ +#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) +#undef ERR_remove_state +#define ERR_remove_state(x) +#endif + + +/* RAND_pseudo_bytes() is deprecated in 1.1.0 in favor of RAND_bytes(). Note + * that the return codes differ, but it happens that the only use case (ticket + * key update) was already wrong, considering a non-cryptographic random as a + * failure. + */ +#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) +#undef RAND_pseudo_bytes +#define RAND_pseudo_bytes(x,y) RAND_bytes(x,y) +#endif + #endif /* _PROTO_OPENSSL_COMPAT_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/cfgparse.c new/haproxy-1.7.3/src/cfgparse.c --- old/haproxy-1.7.2/src/cfgparse.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/cfgparse.c 2017-02-28 09:59:23.000000000 +0100 @@ -3984,6 +3984,12 @@ err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum); } + else if (*args[2]) { + Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n", + file, linenum, args[2]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } rule = calloc(1, sizeof(*rule)); if (!rule) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/checks.c new/haproxy-1.7.3/src/checks.c --- old/haproxy-1.7.2/src/checks.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/checks.c 2017-02-28 09:59:23.000000000 +0100 @@ -3407,7 +3407,7 @@ len = vsnprintf(buf, sizeof(buf), format, argp); va_end(argp); - if (len < 0) { + if (len < 0 || len >= sizeof(buf)) { Alert("Email alert [%s] could not format message\n", p->id); return; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/chunk.c new/haproxy-1.7.3/src/chunk.c --- old/haproxy-1.7.2/src/chunk.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/chunk.c 2017-02-28 09:59:23.000000000 +0100 @@ -29,6 +29,9 @@ static char *trash_buf1; static char *trash_buf2; +/* the trash pool for reentrant allocations */ +struct pool_head *pool2_trash = NULL; + /* * Returns a pre-allocated and initialized trash chunk that can be used for any * type of conversion. Two chunks and their respective buffers are alternatively @@ -63,7 +66,8 @@ trash_size = bufsize; trash_buf1 = (char *)my_realloc2(trash_buf1, bufsize); trash_buf2 = (char *)my_realloc2(trash_buf2, bufsize); - return trash_buf1 && trash_buf2; + pool2_trash = create_pool("trash", sizeof(struct chunk) + bufsize, MEM_F_EXACT); + return trash_buf1 && trash_buf2 && pool2_trash; } /* @@ -78,6 +82,25 @@ } /* + * Allocate a trash chunk from the reentrant pool. The buffer starts at the + * end of the chunk. This chunk must be freed using free_trash_chunk(). This + * call may fail and the caller is responsible for checking that the returned + * pointer is not NULL. + */ +struct chunk *alloc_trash_chunk(void) +{ + struct chunk *chunk; + + chunk = pool_alloc2(pool2_trash); + if (chunk) { + char *buf = (char *)chunk + sizeof(struct chunk); + *buf = 0; + chunk_init(chunk, buf, pool2_trash->size - sizeof(struct chunk)); + } + return chunk; +} + +/* * Does an snprintf() at the beginning of chunk <chk>, respecting the limit of * at most chk->size chars. If the chk->len is over, nothing is added. Returns * the new chunk size, or < 0 in case of failure. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/dns.c new/haproxy-1.7.3/src/dns.c --- old/haproxy-1.7.2/src/dns.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/dns.c 2017-02-28 09:59:23.000000000 +0100 @@ -919,11 +919,13 @@ * parses resolvers sections and initializes: * - task (time events) for each resolvers section * - the datagram layer (network IO events) for each nameserver + * It takes one argument: + * - close_first takes 2 values: 0 or 1. If 1, the connection is closed first. * returns: * 0 in case of error * 1 when no error */ -int dns_init_resolvers(void) +int dns_init_resolvers(int close_socket) { struct dns_resolvers *curr_resolvers; struct dns_nameserver *curnameserver; @@ -961,7 +963,19 @@ curr_resolvers->t = t; list_for_each_entry(curnameserver, &curr_resolvers->nameserver_list, list) { - if ((dgram = calloc(1, sizeof(*dgram))) == NULL) { + dgram = NULL; + + if (close_socket == 1) { + if (curnameserver->dgram) { + close(curnameserver->dgram->t.sock.fd); + memset(curnameserver->dgram, '\0', sizeof(*dgram)); + dgram = curnameserver->dgram; + } + } + + /* allocate memory only if it has not already been allocated + * by a previous call to this function */ + if (!dgram && (dgram = calloc(1, sizeof(*dgram))) == NULL) { Alert("Starting [%s/%s] nameserver: out of memory.\n", curr_resolvers->id, curnameserver->id); return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/haproxy.c new/haproxy-1.7.3/src/haproxy.c --- old/haproxy-1.7.2/src/haproxy.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/haproxy.c 2017-02-28 09:59:23.000000000 +0100 @@ -1309,7 +1309,7 @@ exit(1); /* initialize structures for name resolution */ - if (!dns_init_resolvers()) + if (!dns_init_resolvers(0)) exit(1); free(err_msg); @@ -1685,6 +1685,7 @@ pool_destroy2(pool2_stream); pool_destroy2(pool2_session); pool_destroy2(pool2_connection); + pool_destroy2(pool2_trash); pool_destroy2(pool2_buffer); pool_destroy2(pool2_requri); pool_destroy2(pool2_task); @@ -2090,6 +2091,10 @@ fork_poller(); } + /* initialize structures for name resolution */ + if (!dns_init_resolvers(1)) + exit(1); + protocol_enable_all(); /* * That's it : the central polling loop. Run until we stop. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/hlua.c new/haproxy-1.7.3/src/hlua.c --- old/haproxy-1.7.2/src/hlua.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/hlua.c 2017-02-28 09:59:23.000000000 +0100 @@ -3551,22 +3551,24 @@ /* Get path and qs */ path = http_get_path(txn); - end = txn->req.chn->buf->p + txn->req.sl.rq.u + txn->req.sl.rq.u_l; - p = path; - while (p < end && *p != '?') - p++; - - /* Stores the request path. */ - lua_pushstring(L, "path"); - lua_pushlstring(L, path, p - path); - lua_settable(L, -3); + if (path) { + end = txn->req.chn->buf->p + txn->req.sl.rq.u + txn->req.sl.rq.u_l; + p = path; + while (p < end && *p != '?') + p++; - /* Stores the query string. */ - lua_pushstring(L, "qs"); - if (*p == '?') - p++; - lua_pushlstring(L, p, end - p); - lua_settable(L, -3); + /* Stores the request path. */ + lua_pushstring(L, "path"); + lua_pushlstring(L, path, p - path); + lua_settable(L, -3); + + /* Stores the query string. */ + lua_pushstring(L, "qs"); + if (*p == '?') + p++; + lua_pushlstring(L, p, end - p); + lua_settable(L, -3); + } /* Stores the request path. */ lua_pushstring(L, "length"); @@ -7008,6 +7010,10 @@ /* register pattern types. */ for (i=0; i<PAT_MATCH_NUM; i++) hlua_class_const_int(gL.T, pat_match_names[i], i); + for (i=0; i<PAT_MATCH_NUM; i++) { + snprintf(trash.str, trash.size, "_%s", pat_match_names[i]); + hlua_class_const_int(gL.T, trash.str, i); + } /* register constructor. */ hlua_class_function(gL.T, "new", hlua_map_new); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/proto_http.c new/haproxy-1.7.3/src/proto_http.c --- old/haproxy-1.7.2/src/proto_http.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/proto_http.c 2017-02-28 09:59:23.000000000 +0100 @@ -3419,13 +3419,22 @@ struct list *fmt, struct my_regex *re, int action) { - struct chunk *replace = get_trash_chunk(); + struct chunk *replace; + int ret = -1; + + replace = alloc_trash_chunk(); + if (!replace) + goto leave; replace->len = build_logline(s, replace->str, replace->size, fmt); if (replace->len >= replace->size - 1) - return -1; + goto leave; + + ret = http_transform_header_str(s, msg, name, name_len, replace->str, re, action); - return http_transform_header_str(s, msg, name, name_len, replace->str, re, action); + leave: + free_trash_chunk(replace); + return ret; } /* Executes the http-request rules <rules> for stream <s>, proxy <px> and @@ -3814,7 +3823,7 @@ rule->arg.hdr_add.name_len, &rule->arg.hdr_add.fmt, &rule->arg.hdr_add.re, rule->action)) - return HTTP_RULE_RES_STOP; /* note: we should report an error here */ + return HTTP_RULE_RES_BADREQ; break; case ACT_HTTP_DEL_HDR: @@ -4023,7 +4032,12 @@ struct http_msg *req = &txn->req; struct http_msg *res = &txn->rsp; const char *msg_fmt; - const char *location; + struct chunk *chunk; + int ret = 0; + + chunk = alloc_trash_chunk(); + if (!chunk) + goto leave; /* build redirect message */ switch(rule->code) { @@ -4045,10 +4059,8 @@ break; } - if (unlikely(!chunk_strcpy(&trash, msg_fmt))) - return 0; - - location = trash.str + trash.len; + if (unlikely(!chunk_strcpy(chunk, msg_fmt))) + goto leave; switch(rule->type) { case REDIRECT_TYPE_SCHEME: { @@ -4087,40 +4099,40 @@ if (rule->rdr_str) { /* this is an old "redirect" rule */ /* check if we can add scheme + "://" + host + path */ - if (trash.len + rule->rdr_len + 3 + hostlen + pathlen > trash.size - 4) - return 0; + if (chunk->len + rule->rdr_len + 3 + hostlen + pathlen > chunk->size - 4) + goto leave; /* add scheme */ - memcpy(trash.str + trash.len, rule->rdr_str, rule->rdr_len); - trash.len += rule->rdr_len; + memcpy(chunk->str + chunk->len, rule->rdr_str, rule->rdr_len); + chunk->len += rule->rdr_len; } else { /* add scheme with executing log format */ - trash.len += build_logline(s, trash.str + trash.len, trash.size - trash.len, &rule->rdr_fmt); + chunk->len += build_logline(s, chunk->str + chunk->len, chunk->size - chunk->len, &rule->rdr_fmt); /* check if we can add scheme + "://" + host + path */ - if (trash.len + 3 + hostlen + pathlen > trash.size - 4) - return 0; + if (chunk->len + 3 + hostlen + pathlen > chunk->size - 4) + goto leave; } /* add "://" */ - memcpy(trash.str + trash.len, "://", 3); - trash.len += 3; + memcpy(chunk->str + chunk->len, "://", 3); + chunk->len += 3; /* add host */ - memcpy(trash.str + trash.len, host, hostlen); - trash.len += hostlen; + memcpy(chunk->str + chunk->len, host, hostlen); + chunk->len += hostlen; /* add path */ - memcpy(trash.str + trash.len, path, pathlen); - trash.len += pathlen; + memcpy(chunk->str + chunk->len, path, pathlen); + chunk->len += pathlen; /* append a slash at the end of the location if needed and missing */ - if (trash.len && trash.str[trash.len - 1] != '/' && + if (chunk->len && chunk->str[chunk->len - 1] != '/' && (rule->flags & REDIRECT_FLAG_APPEND_SLASH)) { - if (trash.len > trash.size - 5) - return 0; - trash.str[trash.len] = '/'; - trash.len++; + if (chunk->len > chunk->size - 5) + goto leave; + chunk->str[chunk->len] = '/'; + chunk->len++; } break; @@ -4149,38 +4161,38 @@ } if (rule->rdr_str) { /* this is an old "redirect" rule */ - if (trash.len + rule->rdr_len + pathlen > trash.size - 4) - return 0; + if (chunk->len + rule->rdr_len + pathlen > chunk->size - 4) + goto leave; /* add prefix. Note that if prefix == "/", we don't want to * add anything, otherwise it makes it hard for the user to * configure a self-redirection. */ if (rule->rdr_len != 1 || *rule->rdr_str != '/') { - memcpy(trash.str + trash.len, rule->rdr_str, rule->rdr_len); - trash.len += rule->rdr_len; + memcpy(chunk->str + chunk->len, rule->rdr_str, rule->rdr_len); + chunk->len += rule->rdr_len; } } else { /* add prefix with executing log format */ - trash.len += build_logline(s, trash.str + trash.len, trash.size - trash.len, &rule->rdr_fmt); + chunk->len += build_logline(s, chunk->str + chunk->len, chunk->size - chunk->len, &rule->rdr_fmt); /* Check length */ - if (trash.len + pathlen > trash.size - 4) - return 0; + if (chunk->len + pathlen > chunk->size - 4) + goto leave; } /* add path */ - memcpy(trash.str + trash.len, path, pathlen); - trash.len += pathlen; + memcpy(chunk->str + chunk->len, path, pathlen); + chunk->len += pathlen; /* append a slash at the end of the location if needed and missing */ - if (trash.len && trash.str[trash.len - 1] != '/' && + if (chunk->len && chunk->str[chunk->len - 1] != '/' && (rule->flags & REDIRECT_FLAG_APPEND_SLASH)) { - if (trash.len > trash.size - 5) - return 0; - trash.str[trash.len] = '/'; - trash.len++; + if (chunk->len > chunk->size - 5) + goto leave; + chunk->str[chunk->len] = '/'; + chunk->len++; } break; @@ -4188,59 +4200,54 @@ case REDIRECT_TYPE_LOCATION: default: if (rule->rdr_str) { /* this is an old "redirect" rule */ - if (trash.len + rule->rdr_len > trash.size - 4) - return 0; + if (chunk->len + rule->rdr_len > chunk->size - 4) + goto leave; /* add location */ - memcpy(trash.str + trash.len, rule->rdr_str, rule->rdr_len); - trash.len += rule->rdr_len; + memcpy(chunk->str + chunk->len, rule->rdr_str, rule->rdr_len); + chunk->len += rule->rdr_len; } else { /* add location with executing log format */ - trash.len += build_logline(s, trash.str + trash.len, trash.size - trash.len, &rule->rdr_fmt); + chunk->len += build_logline(s, chunk->str + chunk->len, chunk->size - chunk->len, &rule->rdr_fmt); /* Check left length */ - if (trash.len > trash.size - 4) - return 0; + if (chunk->len > chunk->size - 4) + goto leave; } break; } if (rule->cookie_len) { - memcpy(trash.str + trash.len, "\r\nSet-Cookie: ", 14); - trash.len += 14; - memcpy(trash.str + trash.len, rule->cookie_str, rule->cookie_len); - trash.len += rule->cookie_len; + memcpy(chunk->str + chunk->len, "\r\nSet-Cookie: ", 14); + chunk->len += 14; + memcpy(chunk->str + chunk->len, rule->cookie_str, rule->cookie_len); + chunk->len += rule->cookie_len; } - /* add end of headers and the keep-alive/close status. - * We may choose to set keep-alive if the Location begins - * with a slash, because the client will come back to the - * same server. - */ + /* add end of headers and the keep-alive/close status. */ txn->status = rule->code; /* let's log the request time */ s->logs.tv_request = now; - if (*location == '/' && - (req->flags & HTTP_MSGF_XFER_LEN) && + if ((req->flags & HTTP_MSGF_XFER_LEN) && ((!(req->flags & HTTP_MSGF_TE_CHNK) && !req->body_len) || (req->msg_state == HTTP_MSG_DONE)) && ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL || (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL)) { /* keep-alive possible */ if (!(req->flags & HTTP_MSGF_VER_11)) { if (unlikely(txn->flags & TX_USE_PX_CONN)) { - memcpy(trash.str + trash.len, "\r\nProxy-Connection: keep-alive", 30); - trash.len += 30; + memcpy(chunk->str + chunk->len, "\r\nProxy-Connection: keep-alive", 30); + chunk->len += 30; } else { - memcpy(trash.str + trash.len, "\r\nConnection: keep-alive", 24); - trash.len += 24; + memcpy(chunk->str + chunk->len, "\r\nConnection: keep-alive", 24); + chunk->len += 24; } } - memcpy(trash.str + trash.len, "\r\n\r\n", 4); - trash.len += 4; - FLT_STRM_CB(s, flt_http_reply(s, txn->status, &trash)); - bo_inject(res->chn, trash.str, trash.len); + memcpy(chunk->str + chunk->len, "\r\n\r\n", 4); + chunk->len += 4; + FLT_STRM_CB(s, flt_http_reply(s, txn->status, chunk)); + bo_inject(res->chn, chunk->str, chunk->len); /* "eat" the request */ bi_fast_delete(req->chn->buf, req->sov); req->next -= req->sov; @@ -4255,13 +4262,13 @@ } else { /* keep-alive not possible */ if (unlikely(txn->flags & TX_USE_PX_CONN)) { - memcpy(trash.str + trash.len, "\r\nProxy-Connection: close\r\n\r\n", 29); - trash.len += 29; + memcpy(chunk->str + chunk->len, "\r\nProxy-Connection: close\r\n\r\n", 29); + chunk->len += 29; } else { - memcpy(trash.str + trash.len, "\r\nConnection: close\r\n\r\n", 23); - trash.len += 23; + memcpy(chunk->str + chunk->len, "\r\nConnection: close\r\n\r\n", 23); + chunk->len += 23; } - http_reply_and_close(s, txn->status, &trash); + http_reply_and_close(s, txn->status, chunk); req->chn->analysers &= AN_REQ_FLT_END; } @@ -4270,7 +4277,10 @@ if (!(s->flags & SF_FINST_MASK)) s->flags |= SF_FINST_R; - return 1; + ret = 1; + leave: + free_trash_chunk(chunk); + return ret; } /* This stream analyser runs all HTTP request processing which is common to @@ -6820,7 +6830,7 @@ } skip_header_mangling: - if ((msg->flags & HTTP_MSGF_XFER_LEN) || HAS_FILTERS(s) || + if ((msg->flags & HTTP_MSGF_XFER_LEN) || HAS_DATA_FILTERS(s, rep) || (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_TUN) { rep->analysers &= ~AN_RES_FLT_XFER_DATA; rep->analysers |= AN_RES_HTTP_XFER_BODY; @@ -6971,8 +6981,8 @@ * keep-alive is set on the client side or if there are filters * registered on the stream, we don't want to forward a close */ - if ((msg->flags & HTTP_MSGF_TE_CHNK) || !msg->body_len || - HAS_FILTERS(s) || + if ((msg->flags & HTTP_MSGF_TE_CHNK) || !(msg->flags & HTTP_MSGF_XFER_LEN) || + HAS_DATA_FILTERS(s, res) || (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL || (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) channel_dont_close(res); @@ -7064,11 +7074,10 @@ goto missing_data_or_waiting; } - if (!(msg->flags & HTTP_MSGF_XFER_LEN) && !(chn->flags & CF_SHUTR) && - HAS_DATA_FILTERS(s, chn)) { - /* The server still sending data that should be filtered */ + /* The server still sending data that should be filtered */ + if (!(msg->flags & HTTP_MSGF_XFER_LEN) && !(chn->flags & CF_SHUTR)) goto missing_data_or_waiting; - } + msg->msg_state = HTTP_MSG_ENDING; ending: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/proto_tcp.c new/haproxy-1.7.3/src/proto_tcp.c --- old/haproxy-1.7.2/src/proto_tcp.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/proto_tcp.c 2017-02-28 09:59:23.000000000 +0100 @@ -474,10 +474,16 @@ if (global.tune.server_rcvbuf) setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &global.tune.server_rcvbuf, sizeof(global.tune.server_rcvbuf)); - if ((connect(fd, (struct sockaddr *)&conn->addr.to, get_addr_len(&conn->addr.to)) == -1) && - (errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) { - - if (errno == EAGAIN || errno == EADDRINUSE || errno == EADDRNOTAVAIL) { + if (connect(fd, (struct sockaddr *)&conn->addr.to, get_addr_len(&conn->addr.to)) == -1) { + if (errno == EINPROGRESS || errno == EALREADY) { + /* common case, let's wait for connect status */ + conn->flags |= CO_FL_WAIT_L4_CONN; + } + else if (errno == EISCONN) { + /* should normally not happen but if so, indicates that it's OK */ + conn->flags &= ~CO_FL_WAIT_L4_CONN; + } + else if (errno == EAGAIN || errno == EADDRINUSE || errno == EADDRNOTAVAIL) { char *msg; if (errno == EAGAIN || errno == EADDRNOTAVAIL) { msg = "no free ports"; @@ -514,6 +520,10 @@ return SF_ERR_SRVCL; } } + else { + /* connect() == 0, this is great! */ + conn->flags &= ~CO_FL_WAIT_L4_CONN; + } conn->flags |= CO_FL_ADDR_TO_SET; @@ -523,7 +533,6 @@ conn_ctrl_init(conn); /* registers the FD */ fdtab[fd].linger_risk = 1; /* close hard if needed */ - conn_sock_want_send(conn); /* for connect status */ if (conn_xprt_init(conn) < 0) { conn_force_close(conn); @@ -531,6 +540,17 @@ return SF_ERR_RESOURCE; } + if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_WAIT_L4_CONN)) { + conn_sock_want_send(conn); /* for connect status, proxy protocol or SSL */ + } + else { + /* If there's no more handshake, we need to notify the data + * layer when the connection is already OK otherwise we'll have + * no other opportunity to do it later (eg: health checks). + */ + data = 1; + } + if (data) conn_data_want_send(conn); /* prepare to send data if any */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/proto_uxst.c new/haproxy-1.7.3/src/proto_uxst.c --- old/haproxy-1.7.2/src/proto_uxst.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/proto_uxst.c 2017-02-28 09:59:23.000000000 +0100 @@ -495,12 +495,12 @@ setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &global.tune.server_rcvbuf, sizeof(global.tune.server_rcvbuf)); if (connect(fd, (struct sockaddr *)&conn->addr.to, get_addr_len(&conn->addr.to)) == -1) { - if (errno == EALREADY || errno == EISCONN) { - conn->flags &= ~CO_FL_WAIT_L4_CONN; - } - else if (errno == EINPROGRESS) { + if (errno == EINPROGRESS || errno == EALREADY) { conn->flags |= CO_FL_WAIT_L4_CONN; } + else if (errno == EISCONN) { + conn->flags &= ~CO_FL_WAIT_L4_CONN; + } else if (errno == EAGAIN || errno == EADDRINUSE || errno == EADDRNOTAVAIL) { char *msg; if (errno == EAGAIN || errno == EADDRNOTAVAIL) { @@ -533,13 +533,9 @@ } else { /* connect() already succeeded, which is quite usual for unix - * sockets. Let's avoid a second connect() probe to complete it, - * but we need to ensure we'll wake up if there's no more handshake - * pending (eg: for health checks). + * sockets. Let's avoid a second connect() probe to complete it. */ conn->flags &= ~CO_FL_WAIT_L4_CONN; - if (!(conn->flags & CO_FL_HANDSHAKE)) - data = 1; } conn->flags |= CO_FL_ADDR_TO_SET; @@ -550,8 +546,6 @@ conn_ctrl_init(conn); /* registers the FD */ fdtab[fd].linger_risk = 0; /* no need to disable lingering */ - if (conn->flags & CO_FL_HANDSHAKE) - conn_sock_want_send(conn); /* for connect status or proxy protocol */ if (conn_xprt_init(conn) < 0) { conn_force_close(conn); @@ -559,6 +553,17 @@ return SF_ERR_RESOURCE; } + if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_WAIT_L4_CONN)) { + conn_sock_want_send(conn); /* for connect status, proxy protocol or SSL */ + } + else { + /* If there's no more handshake, we need to notify the data + * layer when the connection is already OK otherwise we'll have + * no other opportunity to do it later (eg: health checks). + */ + data = 1; + } + if (data) conn_data_want_send(conn); /* prepare to send data if any */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.2/src/proxy.c new/haproxy-1.7.3/src/proxy.c --- old/haproxy-1.7.2/src/proxy.c 2017-01-13 10:03:00.000000000 +0100 +++ new/haproxy-1.7.3/src/proxy.c 2017-02-28 09:59:23.000000000 +0100 @@ -1156,7 +1156,7 @@ * be more reliable to store the list of analysers that have been run, * but what we do here is OK for now. */ - s->req.analysers |= be->be_req_ana & (strm_li(s) ? ~strm_li(s)->analysers : 0); + s->req.analysers |= be->be_req_ana & ~(strm_li(s) ? strm_li(s)->analysers : 0); /* If the target backend requires HTTP processing, we have to allocate * the HTTP transaction and hdr_idx if we did not have one.