Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2021-07-12 01:24:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new.2625 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Mon Jul 12 01:24:40 2021 rev:105 rq:904653 version:2.4.2+git0.553dee326 Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2021-06-24 18:22:01.524879691 +0200 +++ /work/SRC/openSUSE:Factory/.haproxy.new.2625/haproxy.changes 2021-07-12 01:24:44.757365380 +0200 @@ -1,0 +2,41 @@ +Wed Jul 07 23:30:56 UTC 2021 - mrueck...@suse.de + +- Update to version 2.4.2+git0.553dee326: + * [RELEASE] Released version 2.4.2 + * REGTESTS: add http scheme-based normalization test + * MEDIUM: h2: apply scheme-based normalization on h2 requests + * MEDIUM: h1-htx: apply scheme-based normalization on h1 requests + * MEDIUM: http: implement scheme-based normalization + * MINOR: http: implement http_get_scheme + * Revert "MINOR: tcp-act: Add set-src/set-src-port for "tcp-request content" rules" + * BUG/MINOR: cli: fix server name output in "show fd" + * BUG/MEDIUM: sock: make sure to never miss early connection failures + * DOC: stick-table: add missing documentation about gpt0 stored type + * BUG/MINOR: peers: fix data_type bit computation more than 32 data_types + * BUG/MINOR: stick-table: fix several printf sign errors dumping tables + * DOC: config: use CREATE USER for mysql-check + * BUG/MEDIUM: resolvers: Make 1st server of a template take part to SRV resolution + * BUG/MINOR: mqtt: Support empty client ID in CONNECT message + * BUG/MINOR: mqtt: Fix parser for string with more than 127 characters + * BUG/MINOR: tcpcheck: Fix numbering of implicit HTTP send/expect rules + * BUILD: Makefile: fix linkage for Haiku. + * BUG/MINOR: checks: return correct error code for srv_parse_agent_check + * MINOR: resolvers: Reset server IP on error in resolv_get_ip_from_response() + * BUG/MINOR: resolvers: Reset server IP when no ip is found in the response + * BUG/MINOR: resolvers: Always attach server on matching record on resolution + * CLEANUP: dns: Remove a forgotten debug message + * DOC: config: Add missing actions in "tcp-request session" documentation + * MINOR: tcp-act: Add set-src/set-src-port for "tcp-request content" rules + * REGTESTS: fix maxconn update with agent-check + * BUG/MAJOR: server: fix deadlock when changing maxconn via agent-check + * BUG/MINOR: cache: Correctly handle existing-but-empty 'accept-encoding' header + * BUG/MINOR: server/cli: Fix locking in function processing "set server" command + * BUG/MINOR: resolvers: Use resolver's lock in resolv_srvrq_expire_task() + * BUG/MEDIUM: resolvers: Add a task on servers to check SRV resolution status + * MINOR: resolvers: Remove server from named_servers tree when removing a SRV item + * MINOR: resolvers: Clean server in a dedicated function when removing a SRV item + * BUG/MEDIUM: server/cli: Fix ABBA deadlock when fqdn is set from the CLI + * BUG/MINOR: server: Forbid to set fqdn on the CLI if SRV resolution is enabled + * BUG/MINOR: server-state: load SRV resolution only if params match the config + +------------------------------------------------------------------- Old: ---- haproxy-2.4.1+git0.1ce7d4925.tar.gz New: ---- haproxy-2.4.2+git0.553dee326.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.Q43BK3/_old 2021-07-12 01:24:45.357360767 +0200 +++ /var/tmp/diff_new_pack.Q43BK3/_new 2021-07-12 01:24:45.357360767 +0200 @@ -53,7 +53,7 @@ %endif Name: haproxy -Version: 2.4.1+git0.1ce7d4925 +Version: 2.4.2+git0.553dee326 Release: 0 # # ++++++ _service ++++++ --- /var/tmp/diff_new_pack.Q43BK3/_old 2021-07-12 01:24:45.385360551 +0200 +++ /var/tmp/diff_new_pack.Q43BK3/_new 2021-07-12 01:24:45.385360551 +0200 @@ -6,7 +6,7 @@ <param name="versionformat">@PARENT_TAG@+git@TAG_OFFSET@.%h</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="versionrewrite-replacement">\1</param> - <param name="revision">v2.4.1</param> + <param name="revision">v2.4.2</param> <param name="changesgenerate">enable</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.Q43BK3/_old 2021-07-12 01:24:45.401360428 +0200 +++ /var/tmp/diff_new_pack.Q43BK3/_new 2021-07-12 01:24:45.401360428 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">http://git.haproxy.org/git/haproxy-2.4.git</param> - <param name="changesrevision">1ce7d49252b1b9c767ab676bd178cccc35929d28</param> + <param name="changesrevision">553dee32630347e78cc3a33001c40d26d4245d23</param> </service> </servicedata> \ No newline at end of file ++++++ haproxy-2.4.1+git0.1ce7d4925.tar.gz -> haproxy-2.4.2+git0.553dee326.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/.gitignore new/haproxy-2.4.2+git0.553dee326/.gitignore --- old/haproxy-2.4.1+git0.1ce7d4925/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/haproxy-2.4.2+git0.553dee326/.gitignore 2021-07-07 16:46:09.000000000 +0200 @@ -0,0 +1,53 @@ +# Below we forbid everything and only allow what we know, that's much easier +# than blocking about 500 different test files and bug report outputs. +/.* +/* +!/.cirrus.yml +!/.gitattributes +!/.github +!/.gitignore +!/.travis.yml +!/CHANGELOG +!/LICENSE +!/BRANCHES +!/Makefile +!/README +!/INSTALL +!/CONTRIBUTING +!/MAINTAINERS +!/ROADMAP +!/SUBVERS +!/VERDATE +!/VERSION +!/addons +!/admin +!/dev +!/doc +!/ebtree +!/examples +!/include +!/src +!/tests +!/debian +!/scripts +!/reg-tests +# Reject some generic files +*.o +*.a +*~ +*.rej +*.orig +*.bak +# And reject some specific files +/admin/halog/halog +/admin/iprange/ip6range +/admin/iprange/iprange +/admin/systemd/haproxy.service +dev/base64/base64rev-gen +dev/flags/flags +dev/poll/poll +dev/tcploop/tcploop +dev/hpack/decode +dev/hpack/gen-rht +/src/dlmalloc.c +/tests/test_hashes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/CHANGELOG new/haproxy-2.4.2+git0.553dee326/CHANGELOG --- old/haproxy-2.4.1+git0.1ce7d4925/CHANGELOG 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/CHANGELOG 2021-07-07 16:46:09.000000000 +0200 @@ -1,6 +1,43 @@ ChangeLog : =========== +2021/07/07 : 2.4.2 + - BUG/MINOR: server-state: load SRV resolution only if params match the config + - BUG/MINOR: server: Forbid to set fqdn on the CLI if SRV resolution is enabled + - BUG/MEDIUM: server/cli: Fix ABBA deadlock when fqdn is set from the CLI + - MINOR: resolvers: Clean server in a dedicated function when removing a SRV item + - MINOR: resolvers: Remove server from named_servers tree when removing a SRV item + - BUG/MEDIUM: resolvers: Add a task on servers to check SRV resolution status + - BUG/MINOR: resolvers: Use resolver's lock in resolv_srvrq_expire_task() + - BUG/MINOR: server/cli: Fix locking in function processing "set server" command + - BUG/MINOR: cache: Correctly handle existing-but-empty 'accept-encoding' header + - BUG/MAJOR: server: fix deadlock when changing maxconn via agent-check + - REGTESTS: fix maxconn update with agent-check + - MINOR: tcp-act: Add set-src/set-src-port for "tcp-request content" rules + - DOC: config: Add missing actions in "tcp-request session" documentation + - CLEANUP: dns: Remove a forgotten debug message + - BUG/MINOR: resolvers: Always attach server on matching record on resolution + - BUG/MINOR: resolvers: Reset server IP when no ip is found in the response + - MINOR: resolvers: Reset server IP on error in resolv_get_ip_from_response() + - BUG/MINOR: checks: return correct error code for srv_parse_agent_check + - BUILD: Makefile: fix linkage for Haiku. + - BUG/MINOR: tcpcheck: Fix numbering of implicit HTTP send/expect rules + - BUG/MINOR: mqtt: Fix parser for string with more than 127 characters + - BUG/MINOR: mqtt: Support empty client ID in CONNECT message + - BUG/MEDIUM: resolvers: Make 1st server of a template take part to SRV resolution + - DOC: config: use CREATE USER for mysql-check + - BUG/MINOR: stick-table: fix several printf sign errors dumping tables + - BUG/MINOR: peers: fix data_type bit computation more than 32 data_types + - DOC: stick-table: add missing documentation about gpt0 stored type + - BUG/MEDIUM: sock: make sure to never miss early connection failures + - BUG/MINOR: cli: fix server name output in "show fd" + - Revert "MINOR: tcp-act: Add set-src/set-src-port for "tcp-request content" rules" + - MINOR: http: implement http_get_scheme + - MEDIUM: http: implement scheme-based normalization + - MEDIUM: h1-htx: apply scheme-based normalization on h1 requests + - MEDIUM: h2: apply scheme-based normalization on h2 requests + - REGTESTS: add http scheme-based normalization test + 2021/06/17 : 2.4.1 - BUG/MEDIUM: ebtree: Invalid read when looking for dup entry - BUG/MAJOR: server: prevent deadlock when using 'set maxconn server' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/Makefile new/haproxy-2.4.2+git0.553dee326/Makefile --- old/haproxy-2.4.1+git0.1ce7d4925/Makefile 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/Makefile 2021-07-07 16:46:09.000000000 +0200 @@ -346,7 +346,7 @@ # Haiku ifeq ($(TARGET),haiku) TARGET_LDFLAGS = -lnetwork - set_target_defaults = $(call default_opts,USE_POLL USE_TPROXY) + set_target_defaults = $(call default_opts,USE_POLL USE_TPROXY USE_OBSOLETE_LINKER) endif # For linux >= 2.6.28 and glibc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/VERDATE new/haproxy-2.4.2+git0.553dee326/VERDATE --- old/haproxy-2.4.1+git0.1ce7d4925/VERDATE 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/VERDATE 2021-07-07 16:46:09.000000000 +0200 @@ -1,2 +1,2 @@ $Format:%ci$ -2021/06/17 +2021/07/07 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/VERSION new/haproxy-2.4.2+git0.553dee326/VERSION --- old/haproxy-2.4.1+git0.1ce7d4925/VERSION 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/VERSION 2021-07-07 16:46:09.000000000 +0200 @@ -1 +1 @@ -2.4.1 +2.4.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/doc/configuration.txt new/haproxy-2.4.2+git0.553dee326/doc/configuration.txt --- old/haproxy-2.4.1+git0.1ce7d4925/doc/configuration.txt 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/doc/configuration.txt 2021-07-07 16:46:09.000000000 +0200 @@ -4,7 +4,7 @@ ---------------------- version 2.4 willy tarreau - 2021/06/17 + 2021/07/07 This document covers the configuration language as implemented in the version @@ -9093,12 +9093,13 @@ one Client Authentication packet, and one QUIT packet, to correctly close MySQL session. We then parse the MySQL Handshake Initialization packet and/or Error packet. It is a basic but useful test which does not produce error nor - aborted connect on the server. However, it requires adding an authorization - in the MySQL table, like this : - - USE mysql; - INSERT INTO user (Host,User) values ('<ip_of_haproxy>','<username>'); - FLUSH PRIVILEGES; + aborted connect on the server. However, it requires an unlocked authorised + user without a password. To create a basic limited user in MySQL with + optional resource limits: + + CREATE USER '<username>'@'<ip_of_haproxy|network_of_haproxy/netmask>' + /*!50701 WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 0 */ + /*M!100201 MAX_STATEMENT_TIME 0.0001 */; If you don't specify a username (it is deprecated and not recommended), the check only consists in parsing the Mysql Handshake Initialization packet or @@ -11311,6 +11312,11 @@ incremented. Most of the time it will be used to measure the frequency of occurrence of certain events (e.g. requests to a specific URL). + - gpt0 : first General Purpose Tag. It is a positive 32-bit integer + integer which may be used for anything. Most of the time it will be used + to put a special tag on some entries, for instance to note that a + specific behavior was detected and must be known for future matches + - conn_cnt : Connection Count. It is a positive 32-bit integer which counts the absolute number of connections received from clients which matched this entry. It does not mean the connections were accepted, just that @@ -12621,6 +12627,10 @@ - sc-inc-gpc0(<sc-id>) - sc-inc-gpc1(<sc-id>) - sc-set-gpt0(<sc-id>) { <int> | <expr> } + - set-dst <expr> + - set-dst-port <expr> + - set-src <expr> + - set-src-port <expr> - set-var(<var-name>) <expr> - unset-var(<var-name>) - silent-drop diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/http.h new/haproxy-2.4.2+git0.553dee326/include/haproxy/http.h --- old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/http.h 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/include/haproxy/http.h 2021-07-07 16:46:09.000000000 +0200 @@ -36,6 +36,7 @@ enum http_meth_t find_http_meth(const char *str, const int len); int http_get_status_idx(unsigned int status); const char *http_get_reason(unsigned int status); +struct ist http_get_scheme(const struct ist uri); struct ist http_get_authority(const struct ist uri, int no_userinfo); struct ist http_get_path(const struct ist uri); int http_header_match2(const char *hdr, const char *end, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/http_htx.h new/haproxy-2.4.2+git0.553dee326/include/haproxy/http_htx.h --- old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/http_htx.h 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/include/haproxy/http_htx.h 2021-07-07 16:46:09.000000000 +0200 @@ -66,6 +66,8 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struct proxy *px, int default_status, char **errmsg); +int http_scheme_based_normalize(struct htx *htx); + struct buffer *http_load_errorfile(const char *file, char **errmsg); struct buffer *http_load_errormsg(const char *key, const struct ist msg, char **errmsg); struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/queue.h new/haproxy-2.4.2+git0.553dee326/include/haproxy/queue.h --- old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/queue.h 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/include/haproxy/queue.h 2021-07-07 16:46:09.000000000 +0200 @@ -34,7 +34,7 @@ struct pendconn *pendconn_add(struct stream *strm); int pendconn_dequeue(struct stream *strm); -void process_srv_queue(struct server *s); +void process_srv_queue(struct server *s, int server_locked); unsigned int srv_dynamic_maxconn(const struct server *s); int pendconn_redistribute(struct server *s); int pendconn_grab_from_px(struct server *s); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/server-t.h new/haproxy-2.4.2+git0.553dee326/include/haproxy/server-t.h --- old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/server-t.h 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/include/haproxy/server-t.h 2021-07-07 16:46:09.000000000 +0200 @@ -368,6 +368,7 @@ struct list srv_rec_item; /* to attach server to a srv record item */ struct list ip_rec_item; /* to attach server to a A or AAAA record item */ struct ebpt_node host_dn; /* hostdn store for srvrq and state file matching*/ + struct task *srvrq_check; /* Task testing SRV record expiration date for this server */ struct { const char *file; /* file where the section appears */ struct eb32_node id; /* place in the tree of used IDs */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/stream.h new/haproxy-2.4.2+git0.553dee326/include/haproxy/stream.h --- old/haproxy-2.4.1+git0.1ce7d4925/include/haproxy/stream.h 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/include/haproxy/stream.h 2021-07-07 16:46:09.000000000 +0200 @@ -339,7 +339,7 @@ ((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_RR)))) { sess_change_server(s, NULL); if (may_dequeue_tasks(objt_server(s->target), s->be)) - process_srv_queue(objt_server(s->target)); + process_srv_queue(objt_server(s->target), 0); s->flags &= ~(SF_DIRECT | SF_ASSIGNED | SF_ADDR_SET); si->state = SI_ST_REQ; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/cache/vary.vtc new/haproxy-2.4.2+git0.553dee326/reg-tests/cache/vary.vtc --- old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/cache/vary.vtc 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/reg-tests/cache/vary.vtc 2021-07-07 16:46:09.000000000 +0200 @@ -108,7 +108,18 @@ -hdr "Content-Encoding: gzip" \ -bodylen 188 + rxreq + expect req.url == "/empty-vs-missing" + txresp -hdr "Content-Encoding: gzip" \ + -hdr "Vary: accept-encoding" \ + -hdr "Cache-Control: max-age=5" \ + -bodylen 234 + rxreq + expect req.url == "/empty-vs-missing" + txresp -hdr "Vary: accept-encoding" \ + -hdr "Cache-Control: max-age=5" \ + -bodylen 256 } -start server s2 { @@ -345,6 +356,42 @@ expect resp.bodylen == 188 expect resp.http.X-Cache-Hit == 0 + # A missing 'Accept-Encoding' implies that anything is acceptable, + # while an empty 'Accept-Encoding' implies nothing is acceptable. + + # Start by caching a gzip response. + txreq -url "/empty-vs-missing" -hdr "Accept-Encoding: gzip" + rxresp + expect resp.status == 200 + expect resp.bodylen == 234 + expect resp.http.content-encoding == "gzip" + expect resp.http.X-Cache-Hit == 0 + + # Check that it is cached. + txreq -url "/empty-vs-missing" -hdr "Accept-Encoding: gzip" + rxresp + expect resp.status == 200 + expect resp.bodylen == 234 + expect resp.http.content-encoding == "gzip" + expect resp.http.X-Cache-Hit == 1 + + # Check that the cached response is returned when no accept-encoding is + # specified. + txreq -url "/empty-vs-missing" + rxresp + expect resp.status == 200 + expect resp.bodylen == 234 + expect resp.http.content-encoding == "gzip" + expect resp.http.X-Cache-Hit == 1 + + # Check that the cached response is not returned when an empty + # accept-encoding is specified. + txreq -url "/empty-vs-missing" -hdr "Accept-Encoding:" + rxresp + expect resp.status == 200 + expect resp.bodylen == 256 + expect resp.http.content-encoding == "<undef>" + expect resp.http.X-Cache-Hit == 0 # The following requests are treated by a backend that does not cache # responses containing a Vary header diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/checks/agent-check.vtc new/haproxy-2.4.2+git0.553dee326/reg-tests/checks/agent-check.vtc --- old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/checks/agent-check.vtc 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/reg-tests/checks/agent-check.vtc 2021-07-07 16:46:09.000000000 +0200 @@ -9,7 +9,7 @@ server s1 { barrier b1 sync recv 5 - send "75%,max-conn:30,maint,down\n" + send "75%,maxconn:30,maint,down\n" expect_close barrier b2 sync } -start @@ -31,8 +31,13 @@ haproxy h1 -cli { send "show servers state" expect ~ "be1 1 srv 127.0.0.1 2 0 100 100 [[:digit:]]+ 1 0 [[:digit:]] 0 [[:digit:]]+ 0 0 - ${s1_port} -" + send "show stat" + expect ~ "be1,srv,0,0,0,0,," + barrier b1 sync barrier b2 sync send "show servers state" expect ~ "be1 1 srv 127.0.0.1 0 1 75 100 [[:digit:]]+ 1 0 [[:digit:]] 0 [[:digit:]]+ 0 0 - ${s1_port} -" + send "show stat" + expect ~ "be1,srv,0,0,0,0,30" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/converter/mqtt.vtc new/haproxy-2.4.2+git0.553dee326/reg-tests/converter/mqtt.vtc --- old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/converter/mqtt.vtc 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/reg-tests/converter/mqtt.vtc 2021-07-07 16:46:09.000000000 +0200 @@ -4,14 +4,14 @@ feature ignore_unknown_macro server s1 { - # MQTT 3.1.1 CONNECT packet (id: test_sub) - recv 22 + # MQTT 3.1.1 CONNECT packet (id: test_subaaaaaa... [len = 200]) + recv 215 sendhex "20020000" close - # MQTT 3.1.1 CONNECT packet (id: test_sub - username: test - passwd: passwd) + # MQTT 3.1.1 CONNECT packet (id: <empty> - username: test - passwd: passwd) accept - recv 36 + recv 28 sendhex "20020000" close @@ -114,14 +114,14 @@ client c1_311_1 -connect ${h1_fe1_sock} { # Valid MQTT 3.1.1 CONNECT packet (id: test_sub) - sendhex "101400044d5154540402003c0008746573745f737562" + sendhex "10d40100044d5154540402003c00c8746573745f737562616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161" recv 4 expect_close } -run client c1_311_2 -connect ${h1_fe1_sock} { - # Valid MQTT 3.1.1 CONNECT packet (id: test_sub - username: test - passwd: passwd) - sendhex "102200044d51545404c2003c0008746573745f7375620004746573740006706173737764" + # Valid MQTT 3.1.1 CONNECT packet (id: <empty> - username: test - passwd: passwd) + sendhex "101a00044d51545404c2003c00000004746573740006706173737764" recv 4 expect_close } -run diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/http-messaging/scheme_based_normalize.vtc new/haproxy-2.4.2+git0.553dee326/reg-tests/http-messaging/scheme_based_normalize.vtc --- old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/http-messaging/scheme_based_normalize.vtc 1970-01-01 01:00:00.000000000 +0100 +++ new/haproxy-2.4.2+git0.553dee326/reg-tests/http-messaging/scheme_based_normalize.vtc 2021-07-07 16:46:09.000000000 +0200 @@ -0,0 +1,125 @@ +varnishtest "scheme based normalization (rfc3982 6.3.2)" +#REQUIRE_VERSION=2.5 + +feature ignore_unknown_macro + +syslog S1 -level info { + recv + expect ~ "^.* uri: GET http://hostname/ HTTP/2.0; host: {hostname}$" + + recv + expect ~ "^.* uri: GET http://hostname:8080/ HTTP/2.0; host: {hostname:8080}$" + + recv + expect ~ "^.* uri: GET https://hostname/ HTTP/2.0; host: {hostname}$" + + recv + expect ~ "^.* uri: GET https://hostname:80/ HTTP/2.0; host: {hostname:80}$" +} -start + +haproxy h1 -conf { + defaults + mode http + timeout connect 5s + timeout client 5s + timeout server 5s + + frontend fe + bind "fd@${fe}" proto h2 + + http-request capture req.hdr(host) len 512 + log-format "uri: %r; host: %hr" + log ${S1_addr}:${S1_port} len 2048 local0 debug err + + http-request return status 200 +} -start + +# default port 80 with http scheme => should be normalized +client c1 -connect ${h1_fe_sock} { + txpri + stream 0 { + txsettings + rxsettings + txsettings -ack + rxsettings + expect settings.ack == true + } -run + + stream 1 { + txreq \ + -req "GET" \ + -scheme "http" \ + -url "/" \ + -hdr ":authority" "hostname:80" + rxhdrs + expect resp.status == 200 + } -run +} -run + +# port 8080 with http scheme => no normalization +client c2 -connect ${h1_fe_sock} { + txpri + stream 0 { + txsettings + rxsettings + txsettings -ack + rxsettings + expect settings.ack == true + } -run + + stream 1 { + txreq \ + -req "GET" \ + -scheme "http" \ + -url "/" \ + -hdr ":authority" "hostname:8080" + rxhdrs + expect resp.status == 200 + } -run +} -run + +# default port 443 with https scheme => should be normalized +client c3 -connect ${h1_fe_sock} { + txpri + stream 0 { + txsettings + rxsettings + txsettings -ack + rxsettings + expect settings.ack == true + } -run + + stream 1 { + txreq \ + -req "GET" \ + -scheme "https" \ + -url "/" \ + -hdr ":authority" "hostname:443" + rxhdrs + expect resp.status == 200 + } -run +} -run + +# port 80 with https scheme => no normalization +client c4 -connect ${h1_fe_sock} { + txpri + stream 0 { + txsettings + rxsettings + txsettings -ack + rxsettings + expect settings.ack == true + } -run + + stream 1 { + txreq \ + -req "GET" \ + -scheme "https" \ + -url "/" \ + -hdr ":authority" "hostname:80" + rxhdrs + expect resp.status == 200 + } -run +} -run + +syslog S1 -wait diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/server/cli_set_fdqn.vtc new/haproxy-2.4.2+git0.553dee326/reg-tests/server/cli_set_fdqn.vtc --- old/haproxy-2.4.1+git0.1ce7d4925/reg-tests/server/cli_set_fdqn.vtc 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/reg-tests/server/cli_set_fdqn.vtc 2021-07-07 16:46:09.000000000 +0200 @@ -28,7 +28,7 @@ haproxy h1 -cli { send "set server test/www1 fqdn foo.fqdn" - expect ~ "could not update test/www1 FQDN by 'stats socket command'" + expect ~ "set server <b>/<s> fqdn failed because no resolution is configured." send "show servers state test" expect ~ "test 1 www1 ${s1_addr} .* - ${s1_port}" } -wait diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/backend.c new/haproxy-2.4.2+git0.553dee326/src/backend.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/backend.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/backend.c 2021-07-07 16:46:09.000000000 +0200 @@ -819,7 +819,7 @@ sess_change_server(s, srv); } else { if (may_dequeue_tasks(conn_slot, s->be)) - process_srv_queue(conn_slot); + process_srv_queue(conn_slot, 0); } } @@ -1835,7 +1835,7 @@ /* release other streams waiting for this server */ if (may_dequeue_tasks(srv, s->be)) - process_srv_queue(srv); + process_srv_queue(srv, 0); return 1; } /* if we get here, it's because we got SRV_STATUS_OK, which also @@ -1911,7 +1911,7 @@ /* release other streams waiting for this server */ sess_change_server(s, NULL); if (may_dequeue_tasks(srv, s->be)) - process_srv_queue(srv); + process_srv_queue(srv, 0); /* Failed and not retryable. */ si_shutr(si); @@ -2239,7 +2239,7 @@ _HA_ATOMIC_INC(&s->be->be_counters.failed_conns); sess_change_server(s, NULL); if (may_dequeue_tasks(objt_server(s->target), s->be)) - process_srv_queue(objt_server(s->target)); + process_srv_queue(objt_server(s->target), 0); /* shutw is enough so stop a connecting socket */ si_shutw(si); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/cache.c new/haproxy-2.4.2+git0.553dee326/src/cache.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/cache.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/cache.c 2021-07-07 16:46:09.000000000 +0200 @@ -2280,6 +2280,19 @@ /* Iterate over all the ACCEPT_ENCODING_MAX_ENTRIES first accept-encoding * values that might span acrosse multiple accept-encoding headers. */ while (http_find_header(htx, hdr_name, &ctx, 0) && count < ACCEPT_ENCODING_MAX_ENTRIES) { + count++; + + /* As per RFC7231#5.3.4, "An Accept-Encoding header field with a + * combined field-value that is empty implies that the user agent + * does not want any content-coding in response." + * + * We must (and did) count the existence of this empty header to not + * hit the `count == 0` case below, but must ignore the value to not + * include VARY_ENCODING_OTHER into the final bitmap. + */ + if (istlen(ctx.value) == 0) + continue; + /* Turn accept-encoding value to lower case */ ist2bin_lc(istptr(ctx.value), ctx.value); @@ -2294,8 +2307,6 @@ /* Unknown encoding */ encoding_bitmap |= VARY_ENCODING_OTHER; } - - count++; } /* If a "*" was found in the accepted encodings (without a null weight), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/check.c new/haproxy-2.4.2+git0.553dee326/src/check.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/check.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/check.c 2021-07-07 16:46:09.000000000 +0200 @@ -1897,7 +1897,7 @@ srv->do_agent = 1; out: - return 0; + return err_code; error: deinit_srv_agent_check(srv); @@ -2155,7 +2155,6 @@ deinit_srv_agent_check(srv); err_code |= ERR_ALERT | ERR_FATAL; goto out; - return 0; } /* Parse the "fall" server keyword */ @@ -2182,7 +2181,6 @@ deinit_srv_agent_check(srv); err_code |= ERR_ALERT | ERR_FATAL; goto out; - return 0; } /* Parse the "inter" server keyword */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/cli.c new/haproxy-2.4.2+git0.553dee326/src/cli.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/cli.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/cli.c 2021-07-07 16:46:09.000000000 +0200 @@ -1281,7 +1281,7 @@ if (px) chunk_appendf(&trash, " px=%s", px->id); else if (sv) - chunk_appendf(&trash, " sv=%s/%s", sv->id, sv->proxy->id); + chunk_appendf(&trash, " sv=%s/%s", sv->proxy->id, sv->id); else if (li) chunk_appendf(&trash, " fe=%s", li->bind_conf->frontend->id); @@ -2580,7 +2580,7 @@ HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess); } if (may_dequeue_tasks(__objt_server(s->target), be)) - process_srv_queue(__objt_server(s->target)); + process_srv_queue(__objt_server(s->target), 0); } s->target = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/dns.c new/haproxy-2.4.2+git0.553dee326/src/dns.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/dns.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/dns.c 2021-07-07 16:46:09.000000000 +0200 @@ -170,7 +170,6 @@ if (!LIST_ISEMPTY(&dss->wait_sess)) { ds = LIST_NEXT(&dss->wait_sess, struct dns_session *, waiter); - fprintf(stderr, "ds: %p\n", ds); ret = ds->rx_msg.len < size ? ds->rx_msg.len : size; memcpy(data, ds->rx_msg.area, ret); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/h1_htx.c new/haproxy-2.4.2+git0.553dee326/src/h1_htx.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/h1_htx.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/h1_htx.c 2021-07-07 16:46:09.000000000 +0200 @@ -16,6 +16,7 @@ #include <haproxy/h1.h> #include <haproxy/h1_htx.h> #include <haproxy/http.h> +#include <haproxy/http_htx.h> #include <haproxy/htx.h> #include <haproxy/tools.h> @@ -191,6 +192,10 @@ sl->flags |= (HTX_SL_F_HAS_AUTHORITY|HTX_SL_F_HAS_SCHM); if (uri.len > 4 && (uri.ptr[0] | 0x20) == 'h') sl->flags |= ((uri.ptr[4] == ':') ? HTX_SL_F_SCHM_HTTP : HTX_SL_F_SCHM_HTTPS); + + /* absolute-form target URI present, proceed to scheme-based + * normalization */ + http_scheme_based_normalize(htx); } /* If body length cannot be determined, set htx->extra to diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/h2.c new/haproxy-2.4.2+git0.553dee326/src/h2.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/h2.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/h2.c 2021-07-07 16:46:09.000000000 +0200 @@ -31,6 +31,7 @@ #include <haproxy/h2.h> #include <haproxy/http-hdr-t.h> #include <haproxy/http.h> +#include <haproxy/http_htx.h> #include <haproxy/htx.h> #include <import/ist.h> @@ -553,6 +554,10 @@ if (!htx_add_endof(htx, HTX_BLK_EOH)) goto fail; + /* proceed to scheme-based normalization on target-URI */ + if (fields & H2_PHDR_FND_SCHM) + http_scheme_based_normalize(htx); + ret = 1; return ret; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/http.c new/haproxy-2.4.2+git0.553dee326/src/http.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/http.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/http.c 2021-07-07 16:46:09.000000000 +0200 @@ -468,6 +468,56 @@ } } +/* Parse the uri and looks for the scheme. If not found, an empty ist is + * returned. Otherwise, the ist pointing to the scheme is returned. + */ +struct ist http_get_scheme(const struct ist uri) +{ + const char *ptr, *start, *end; + + if (!uri.len) + goto not_found; + + ptr = uri.ptr; + start = ptr; + end = ptr + uri.len; + + /* RFC7230, par. 2.7 : + * Request-URI = "*" | absuri | abspath | authority + */ + + if (*ptr == '*' || *ptr == '/') + goto not_found; + + if (isalpha((unsigned char)*ptr)) { + /* this is a scheme as described by RFC3986, par. 3.1, or only + * an authority (in case of a CONNECT method). + */ + ptr++; + /* retrieve the scheme up to the suffix '://'. If the suffix is + * not found, this means there is no scheme and it is an + * authority-only uri. + */ + while (ptr < end && + (isalnum((unsigned char)*ptr) || *ptr == '+' || *ptr == '-' || *ptr == '.')) + ptr++; + if (ptr == end || *ptr++ != ':') + goto not_found; + if (ptr == end || *ptr++ != '/') + goto not_found; + if (ptr == end || *ptr++ != '/') + goto not_found; + } + else { + goto not_found; + } + + return ist2(start, ptr - start); + + not_found: + return IST_NULL; +} + /* Parse the uri and looks for the authority, between the scheme and the * path. if no_userinfo is not zero, the part before the '@' (including it) is * skipped. If not found, an empty ist is returned. Otherwise, the ist pointing diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/http_htx.c new/haproxy-2.4.2+git0.553dee326/src/http_htx.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/http_htx.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/http_htx.c 2021-07-07 16:46:09.000000000 +0200 @@ -11,6 +11,7 @@ */ #include <sys/types.h> #include <sys/stat.h> +#include <ctype.h> #include <fcntl.h> #include <unistd.h> @@ -1718,6 +1719,95 @@ return NULL; } +static int uri_is_default_port(const struct ist scheme, const struct ist port) +{ + return (isteq(port, ist("443")) && isteqi(scheme, ist("https://"))) || + (isteq(port, ist("80")) && isteqi(scheme, ist("http://"))); +} + +/* Apply schemed-based normalization as described on rfc3986 on section 6.3.2. + * Returns 0 if no error has been found else non-zero. + * + * The normalization is processed on the target-uri at the condition that it is + * in absolute-form. In the case where the target-uri was normalized, every + * host headers values found are also replaced by the normalized hostname. This + * assumes that the target-uri and host headers were properly identify as + * similar before calling this function. + */ +int http_scheme_based_normalize(struct htx *htx) +{ + struct http_hdr_ctx ctx; + struct htx_sl *sl; + struct ist uri, scheme, authority, host, port; + char *start, *end, *ptr; + + sl = http_get_stline(htx); + + if (!sl || !(sl->flags & (HTX_SL_F_HAS_SCHM|HTX_SL_F_HAS_AUTHORITY))) + return 0; + + uri = htx_sl_req_uri(sl); + + scheme = http_get_scheme(uri); + /* if no scheme found, no normalization to proceed */ + if (!isttest(scheme)) + return 0; + + /* Extract the port if present in authority. To properly support ipv6 + * hostnames, do a reverse search on the last ':' separator as long as + * digits are found. + */ + authority = http_get_authority(uri, 0); + start = istptr(authority); + end = istend(authority); + for (ptr = end; ptr > start && isdigit(*--ptr); ) + ; + + /* if no port found, no normalization to proceed */ + if (likely(*ptr != ':')) + return 0; + + /* split host/port on the ':' separator found */ + host = ist2(start, ptr - start); + port = istnext(ist2(ptr, end - ptr)); + + if (istlen(port) && uri_is_default_port(scheme, port)) { + /* reconstruct the uri with removal of the port */ + struct buffer *temp = get_trash_chunk(); + struct ist meth, vsn, path; + + /* meth */ + chunk_memcat(temp, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl)); + meth = ist2(temp->area, HTX_SL_REQ_MLEN(sl)); + + /* vsn */ + chunk_memcat(temp, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl)); + vsn = ist2(temp->area + meth.len, HTX_SL_REQ_VLEN(sl)); + + /* reconstruct uri without port */ + path = http_get_path(uri); + chunk_istcat(temp, scheme); + chunk_istcat(temp, host); + chunk_istcat(temp, path); + uri = ist2(temp->area + meth.len + vsn.len, + scheme.len + host.len + path.len); + + http_replace_stline(htx, meth, uri, vsn); + + /* replace every host headers values by the normalized host */ + ctx.blk = NULL; + while (http_find_header(htx, ist("host"), &ctx, 0)) { + if (!http_replace_header_value(htx, &ctx, host)) + goto fail; + } + } + + return 0; + + fail: + return 1; +} + /* Parses the "errorloc[302|303]" proxy keyword */ static int proxy_parse_errorloc(char **args, int section, struct proxy *curpx, const struct proxy *defpx, const char *file, int line, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/mqtt.c new/haproxy-2.4.2+git0.553dee326/src/mqtt.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/mqtt.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/mqtt.c 2021-07-07 16:46:09.000000000 +0200 @@ -288,15 +288,14 @@ */ static inline struct ist mqtt_read_string(struct ist parser, struct ist *str) { - uint16_t len; + uint16_t len = 0; /* read and compute the string length */ - if (istlen(parser) <= 2) + if (istlen(parser) < 2) goto error; - len = ((uint16_t)*istptr(parser) << 8) + (uint16_t)*(istptr(parser) + 1); - parser = istadv(parser, 2); - if (istlen(parser) < len) + parser = mqtt_read_2byte_int(parser, &len); + if (!isttest(parser) || istlen(parser) < len) goto error; if (str) { @@ -863,7 +862,7 @@ */ /* read client identifier */ parser = mqtt_read_string(parser, &mpkt->data.connect.payload.client_identifier); - if (!isttest(parser) || !istlen(mpkt->data.connect.payload.client_identifier)) + if (!isttest(parser)) goto end; /* read Will Properties, for MQTT v5 only diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/peers.c new/haproxy-2.4.2+git0.553dee326/src/peers.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/peers.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/peers.c 2021-07-07 16:46:09.000000000 +0200 @@ -845,10 +845,10 @@ case STD_T_UINT: case STD_T_ULL: case STD_T_DICT: - data |= 1 << data_type; + data |= 1ULL << data_type; break; case STD_T_FRQP: - data |= 1 << data_type; + data |= 1ULL << data_type; intencode(data_type, &chunkq); intencode(st->table->data_arg[data_type].u, &chunkq); break; @@ -1657,7 +1657,7 @@ for (data_type = 0 ; data_type < STKTABLE_DATA_TYPES ; data_type++) { uint64_t decoded_int; - if (!((1 << data_type) & st->remote_data)) + if (!((1ULL << data_type) & st->remote_data)) continue; decoded_int = intdecode(msg_cur, msg_end); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/queue.c new/haproxy-2.4.2+git0.553dee326/src/queue.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/queue.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/queue.c 2021-07-07 16:46:09.000000000 +0200 @@ -337,14 +337,16 @@ } /* Manages a server's connection queue. This function will try to dequeue as - * many pending streams as possible, and wake them up. + * many pending streams as possible, and wake them up. <server_locked> must + * only be set if the caller already hold the server lock. */ -void process_srv_queue(struct server *s) +void process_srv_queue(struct server *s, int server_locked) { struct proxy *p = s->proxy; int maxconn; - HA_SPIN_LOCK(SERVER_LOCK, &s->lock); + if (!server_locked) + HA_SPIN_LOCK(SERVER_LOCK, &s->lock); HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->lock); maxconn = srv_dynamic_maxconn(s); while (s->served < maxconn) { @@ -353,7 +355,8 @@ break; } HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock); - HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock); + if (!server_locked) + HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock); } /* Adds the stream <strm> to the pending connection queue of server <strm>->srv diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/resolvers.c new/haproxy-2.4.2+git0.553dee326/src/resolvers.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/resolvers.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/resolvers.c 2021-07-07 16:46:09.000000000 +0200 @@ -571,6 +571,52 @@ return 0; } +/* Cleanup fqdn/port and address of a server attached to a SRV resolution. This + * happens when an SRV item is purged or when the server status is considered as + * obsolete. + * + * Must be called with the DNS lock held. + */ +static void resolv_srvrq_cleanup_srv(struct server *srv) +{ + resolv_unlink_resolution(srv->resolv_requester, 0); + HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); + srvrq_update_srv_status(srv, 1); + ha_free(&srv->hostname); + ha_free(&srv->hostname_dn); + srv->hostname_dn_len = 0; + memset(&srv->addr, 0, sizeof(srv->addr)); + srv->svc_port = 0; + srv->flags |= SRV_F_NO_RESOLUTION; + + ebpt_delete(&srv->host_dn); + ha_free(&srv->host_dn.key); + + HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock); + LIST_DELETE(&srv->srv_rec_item); + LIST_APPEND(&srv->srvrq->attached_servers, &srv->srv_rec_item); + + srv->srvrq_check->expire = TICK_ETERNITY; +} + +/* Takes care to cleanup a server resolution when it is outdated. This only + * happens for a server relying on a SRV record. + */ +static struct task *resolv_srvrq_expire_task(struct task *t, void *context, unsigned int state) +{ + struct server *srv = context; + + if (!tick_is_expired(t->expire, now_ms)) + goto end; + + HA_SPIN_LOCK(DNS_LOCK, &srv->srvrq->resolvers->lock); + resolv_srvrq_cleanup_srv(srv); + HA_SPIN_UNLOCK(DNS_LOCK, &srv->srvrq->resolvers->lock); + + end: + return t; +} + /* Checks for any obsolete record, also identify any SRV request, and try to * find a corresponding server. */ @@ -604,20 +650,8 @@ } else if (item->type == DNS_RTYPE_SRV) { /* Remove any associated server */ - list_for_each_entry_safe(srv, srvback, &item->attached_servers, srv_rec_item) { - resolv_unlink_resolution(srv->resolv_requester, 0); - HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); - srvrq_update_srv_status(srv, 1); - ha_free(&srv->hostname); - ha_free(&srv->hostname_dn); - srv->hostname_dn_len = 0; - memset(&srv->addr, 0, sizeof(srv->addr)); - srv->svc_port = 0; - srv->flags |= SRV_F_NO_RESOLUTION; - HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock); - LIST_DELETE(&srv->srv_rec_item); - LIST_APPEND(&srv->srvrq->attached_servers, &srv->srv_rec_item); - } + list_for_each_entry_safe(srv, srvback, &item->attached_servers, srv_rec_item) + resolv_srvrq_cleanup_srv(srv); } LIST_DELETE(&item->list); @@ -675,7 +709,7 @@ if (srv->svc_port == item->port) { /* server found, we remove it from tree */ ebpt_delete(node); - free(srv->host_dn.key); + ha_free(&srv->host_dn.key); goto srv_found; } @@ -713,6 +747,7 @@ if (srv) { /* re-enable DNS resolution for this server by default */ srv->flags &= ~SRV_F_NO_RESOLUTION; + srv->srvrq_check->expire = TICK_ETERNITY; /* Check if an Additional Record is associated to this SRV record. * Perform some sanity checks too to ensure the record can be used. @@ -1543,8 +1578,6 @@ *newip = newip6; *newip_sin_family = AF_INET6; } - if (!currentip_found) - goto not_found; } /* Case when the caller looks first for an IPv6 address */ else if (family_priority == AF_INET6) { @@ -1556,8 +1589,6 @@ *newip = newip4; *newip_sin_family = AF_INET; } - if (!currentip_found) - goto not_found; } /* Case when the caller have no preference (we prefer IPv6) */ else if (family_priority == AF_UNSPEC) { @@ -1569,17 +1600,11 @@ *newip = newip4; *newip_sin_family = AF_INET; } - if (!currentip_found) - goto not_found; } - /* No reason why we should change the server's IP address */ - return RSLV_UPD_NO; - - not_found: - /* the ip of this record was chosen for the server */ if (owner && found_record) { + LIST_DEL_INIT(&owner->ip_rec_item); LIST_APPEND(&found_record->attached_servers, &owner->ip_rec_item); } @@ -1590,7 +1615,8 @@ LIST_APPEND(&r_res->answer_list, &record->list); break; } - return RSLV_UPD_SRVIP_NOT_FOUND; + + return (currentip_found ? RSLV_UPD_NO : RSLV_UPD_SRVIP_NOT_FOUND); } /* Turns a domain name label into a string. @@ -1930,20 +1956,8 @@ list_for_each_entry_safe(item, itemback, &res->response.answer_list, list) { if (item->type == DNS_RTYPE_SRV) { list_for_each_entry_safe(srv, srvback, &item->attached_servers, srv_rec_item) { - if (srv->srvrq == srvrq) { - HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); - resolv_unlink_resolution(srv->resolv_requester, safe); - srvrq_update_srv_status(srv, 1); - ha_free(&srv->hostname); - ha_free(&srv->hostname_dn); - srv->hostname_dn_len = 0; - memset(&srv->addr, 0, sizeof(srv->addr)); - srv->svc_port = 0; - srv->flags |= SRV_F_NO_RESOLUTION; - HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock); - LIST_DELETE(&srv->srv_rec_item); - LIST_APPEND(&srvrq->attached_servers, &srv->srv_rec_item); - } + if (srv->srvrq == srvrq) + resolv_srvrq_cleanup_srv(srv); } } } @@ -2426,17 +2440,30 @@ continue; } srv->resolvers = resolvers; + srv->srvrq_check = NULL; + if (srv->srvrq) { + if (!srv->srvrq->resolvers) { + srv->srvrq->resolvers = srv->resolvers; + if (resolv_link_resolution(srv->srvrq, OBJ_TYPE_SRVRQ, 0) == -1) { + ha_alert("config : %s '%s' : unable to set DNS resolution for server '%s'.\n", + proxy_type_str(px), px->id, srv->id); + err_code |= (ERR_ALERT|ERR_ABORT); + continue; + } + } - if (srv->srvrq && !srv->srvrq->resolvers) { - srv->srvrq->resolvers = srv->resolvers; - if (resolv_link_resolution(srv->srvrq, OBJ_TYPE_SRVRQ, 0) == -1) { - ha_alert("config : %s '%s' : unable to set DNS resolution for server '%s'.\n", + srv->srvrq_check = task_new(MAX_THREADS_MASK); + if (!srv->srvrq_check) { + ha_alert("config: %s '%s' : unable to create SRVRQ task for server '%s'.\n", proxy_type_str(px), px->id, srv->id); err_code |= (ERR_ALERT|ERR_ABORT); - continue; + goto err; } + srv->srvrq_check->process = resolv_srvrq_expire_task; + srv->srvrq_check->context = srv; + srv->srvrq_check->expire = TICK_ETERNITY; } - if (!srv->srvrq && resolv_link_resolution(srv, OBJ_TYPE_SERVER, 0) == -1) { + else if (resolv_link_resolution(srv, OBJ_TYPE_SERVER, 0) == -1) { ha_alert("config : %s '%s', unable to set DNS resolution for server '%s'.\n", proxy_type_str(px), px->id, srv->id); err_code |= (ERR_ALERT|ERR_ABORT); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/server.c new/haproxy-2.4.2+git0.553dee326/src/server.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/server.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/server.c 2021-07-07 16:46:09.000000000 +0200 @@ -1812,16 +1812,17 @@ else if (end[0] != '\0') return "Trailing garbage in maxconn string"; - HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); if (sv->maxconn == sv->minconn) { // static maxconn sv->maxconn = sv->minconn = v; } else { // dynamic maxconn sv->maxconn = v; } - HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); + /* server_parse_maxconn_change_request requires the server lock held. + * Specify it to process_srv_queue to prevent a deadlock. + */ if (may_dequeue_tasks(sv, sv->proxy)) - process_srv_queue(sv); + process_srv_queue(sv, 1); return NULL; } @@ -2205,6 +2206,7 @@ void free_server(struct server *srv) { task_destroy(srv->warmup); + task_destroy(srv->srvrq_check); free(srv->id); free(srv->cookie); @@ -2472,6 +2474,7 @@ err_code |= ERR_ALERT | ERR_FATAL; goto out; } + LIST_APPEND(&newsrv->srvrq->attached_servers, &newsrv->srv_rec_item); } else if (srv_prepare_for_resolution(newsrv, fqdn) == -1) { memprintf(errmsg, "Can't create DNS resolution for server '%s'", @@ -3414,9 +3417,6 @@ case RSLV_UPD_SRVIP_NOT_FOUND: goto save_ip; - case RSLV_UPD_CNAME: - goto invalid; - case RSLV_UPD_NO_IP_FOUND: has_no_ip = 1; goto update_status; @@ -3424,9 +3424,11 @@ case RSLV_UPD_NAME_ERROR: /* update resolution status to OTHER error type */ resolution->status = RSLV_STATUS_OTHER; + has_no_ip = 1; goto update_status; default: + has_no_ip = 1; goto invalid; } @@ -3442,8 +3444,8 @@ srv_update_addr(s, firstip, firstip_sin_family, (char *) chk->area); update_status: - - snr_update_srv_status(s, has_no_ip); + if (!snr_update_srv_status(s, has_no_ip) && has_no_ip) + memset(&s->addr, 0, sizeof(s->addr)); return 1; invalid: @@ -3451,7 +3453,8 @@ counters->invalid++; goto update_status; } - snr_update_srv_status(s, has_no_ip); + if (!snr_update_srv_status(s, has_no_ip) && has_no_ip) + memset(&s->addr, 0, sizeof(s->addr)); return 0; } @@ -3912,14 +3915,15 @@ if (!sv) return 1; - HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); - if (strcmp(args[3], "weight") == 0) { + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); warning = server_parse_weight_change_request(sv, args[4]); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); if (warning) cli_err(appctx, warning); } else if (strcmp(args[3], "state") == 0) { + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); if (strcmp(args[4], "ready") == 0) srv_adm_set_ready(sv); else if (strcmp(args[4], "drain") == 0) @@ -3928,8 +3932,10 @@ srv_adm_set_maint(sv); else cli_err(appctx, "'set server <srv> state' expects 'ready', 'drain' and 'maint'.\n"); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); } else if (strcmp(args[3], "health") == 0) { + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); if (sv->track) cli_err(appctx, "cannot change health on a tracking server.\n"); else if (strcmp(args[4], "up") == 0) { @@ -3946,8 +3952,10 @@ } else cli_err(appctx, "'set server <srv> health' expects 'up', 'stopping', or 'down'.\n"); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); } else if (strcmp(args[3], "agent") == 0) { + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); if (!(sv->agent.state & CHK_ST_ENABLED)) cli_err(appctx, "agent checks are not enabled on this server.\n"); else if (strcmp(args[4], "up") == 0) { @@ -3960,6 +3968,7 @@ } else cli_err(appctx, "'set server <srv> agent' expects 'up' or 'down'.\n"); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); } else if (strcmp(args[3], "agent-addr") == 0) { char *addr = NULL; @@ -3967,12 +3976,14 @@ if (strlen(args[4]) == 0) { cli_err(appctx, "set server <b>/<s> agent-addr requires" " an address and optionally a port.\n"); - goto out_unlock; + goto out; } addr = args[4]; if (strcmp(args[5], "port") == 0) port = args[6]; + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); warning = srv_update_agent_addr_port(sv, addr, port); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); if (warning) cli_msg(appctx, LOG_WARNING, warning); } @@ -3981,20 +3992,24 @@ if (strlen(args[4]) == 0) { cli_err(appctx, "set server <b>/<s> agent-port requires" " a port.\n"); - goto out_unlock; + goto out; } port = args[4]; + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); warning = srv_update_agent_addr_port(sv, NULL, port); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); if (warning) cli_msg(appctx, LOG_WARNING, warning); } else if (strcmp(args[3], "agent-send") == 0) { + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); if (!(sv->agent.state & CHK_ST_ENABLED)) cli_err(appctx, "agent checks are not enabled on this server.\n"); else { if (!set_srv_agent_send(sv, args[4])) cli_err(appctx, "cannot allocate memory for new string.\n"); } + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); } else if (strcmp(args[3], "check-addr") == 0) { char *addr = NULL; @@ -4002,12 +4017,14 @@ if (strlen(args[4]) == 0) { cli_err(appctx, "set server <b>/<s> check-addr requires" " an address and optionally a port.\n"); - goto out_unlock; + goto out; } addr = args[4]; if (strcmp(args[5], "port") == 0) port = args[6]; + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); warning = srv_update_check_addr_port(sv, addr, port); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); if (warning) cli_msg(appctx, LOG_WARNING, warning); } @@ -4016,10 +4033,12 @@ if (strlen(args[4]) == 0) { cli_err(appctx, "set server <b>/<s> check-port requires" " a port.\n"); - goto out_unlock; + goto out; } port = args[4]; + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); warning = srv_update_check_addr_port(sv, NULL, port); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); if (warning) cli_msg(appctx, LOG_WARNING, warning); } @@ -4028,7 +4047,7 @@ char *port = NULL; if (strlen(args[4]) == 0) { cli_err(appctx, "set server <b>/<s> addr requires an address and optionally a port.\n"); - goto out_unlock; + goto out; } else { addr = args[4]; @@ -4036,21 +4055,35 @@ if (strcmp(args[5], "port") == 0) { port = args[6]; } + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); warning = srv_update_addr_port(sv, addr, port, "stats socket command"); if (warning) cli_msg(appctx, LOG_WARNING, warning); srv_clr_admin_flag(sv, SRV_ADMF_RMAINT); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); } else if (strcmp(args[3], "fqdn") == 0) { if (!*args[4]) { cli_err(appctx, "set server <b>/<s> fqdn requires a FQDN.\n"); - goto out_unlock; + goto out; + } + if (!sv->resolvers) { + cli_err(appctx, "set server <b>/<s> fqdn failed because no resolution is configured.\n"); + goto out; } + if (sv->srvrq) { + cli_err(appctx, "set server <b>/<s> fqdn failed because SRV resolution is configured.\n"); + goto out; + } + HA_SPIN_LOCK(DNS_LOCK, &sv->resolvers->lock); + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); /* ensure runtime resolver will process this new fqdn */ if (sv->flags & SRV_F_NO_RESOLUTION) { sv->flags &= ~SRV_F_NO_RESOLUTION; } - warning = srv_update_fqdn(sv, args[4], "stats socket command", 0); + warning = srv_update_fqdn(sv, args[4], "stats socket command", 1); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); + HA_SPIN_UNLOCK(DNS_LOCK, &sv->resolvers->lock); if (warning) cli_msg(appctx, LOG_WARNING, warning); } @@ -4059,16 +4092,21 @@ if (sv->ssl_ctx.ctx == NULL) { cli_err(appctx, "'set server <srv> ssl' cannot be set. " " default-server should define ssl settings\n"); - goto out_unlock; - } else if (strcmp(args[4], "on") == 0) { + goto out; + } + + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); + if (strcmp(args[4], "on") == 0) { ssl_sock_set_srv(sv, 1); } else if (strcmp(args[4], "off") == 0) { ssl_sock_set_srv(sv, 0); } else { + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); cli_err(appctx, "'set server <srv> ssl' expects 'on' or 'off'.\n"); - goto out_unlock; + goto out; } srv_cleanup_connections(sv); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); cli_msg(appctx, LOG_NOTICE, "server ssl setting updated.\n"); #else cli_msg(appctx, LOG_NOTICE, "server ssl setting not supported.\n"); @@ -4080,8 +4118,7 @@ "check-addr | check-port | fqdn | health | ssl | " "state | weight\n"); } - out_unlock: - HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); + out: return 1; } @@ -4159,10 +4196,14 @@ if (!sv) return 1; + HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); + warning = server_parse_maxconn_change_request(sv, args[4]); if (warning) cli_err(appctx, warning); + HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock); + return 1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/server_state.c new/haproxy-2.4.2+git0.553dee326/src/server_state.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/server_state.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/server_state.c 2021-07-07 16:46:09.000000000 +0200 @@ -397,16 +397,12 @@ char *tmp; /* we can't apply previous state if SRV record has changed */ - if (srv->srvrq && strcmp(srv->srvrq->name, srvrecord) != 0) { - chunk_appendf(msg, ", SRV record mismatch between configuration ('%s') and state file ('%s) for server '%s'. Previous state not applied", srv->srvrq->name, srvrecord, srv->id); + if (!srv->srvrq) { + chunk_appendf(msg, ", no SRV resolution for server '%s'. Previous state not applied", srv->id); goto out; } - - /* create or find a SRV resolution for this srv record */ - if (srv->srvrq == NULL && (srv->srvrq = find_srvrq_by_name(srvrecord, srv->proxy)) == NULL) - srv->srvrq = new_resolv_srvrq(srv, srvrecord); - if (srv->srvrq == NULL) { - chunk_appendf(msg, ", can't create or find SRV resolution '%s' for server '%s'", srvrecord, srv->id); + if (strcmp(srv->srvrq->name, srvrecord) != 0) { + chunk_appendf(msg, ", SRV record mismatch between configuration ('%s') and state file ('%s) for server '%s'. Previous state not applied", srv->srvrq->name, srvrecord, srv->id); goto out; } @@ -429,8 +425,9 @@ for (i = 0; tmp[i]; i++) tmp[i] = tolower(tmp[i]); - /* insert in tree */ + /* insert in tree and set the srvrq expiration date */ ebis_insert(&srv->srvrq->named_servers, &srv->host_dn); + task_schedule(srv->srvrq_check, tick_add(now_ms, srv->srvrq->resolvers->hold.timeout)); /* Unset SRV_F_MAPPORTS for SRV records. * SRV_F_MAPPORTS is unfortunately set by parse_server() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/sock.c new/haproxy-2.4.2+git0.553dee326/src/sock.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/sock.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/sock.c 2021-07-07 16:46:09.000000000 +0200 @@ -667,7 +667,7 @@ if (!(conn->flags & CO_FL_WAIT_L4_CONN)) return 1; /* strange we were called while ready */ - if (!fd_send_ready(fd)) + if (!fd_send_ready(fd) && !(fdtab[fd].state & (FD_POLL_ERR|FD_POLL_HUP))) return 0; /* Here we have 2 cases : diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/stick_table.c new/haproxy-2.4.2+git0.553dee326/src/stick_table.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/stick_table.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/stick_table.c 2021-07-07 16:46:09.000000000 +0200 @@ -3615,7 +3615,7 @@ if (t->data_ofs[dt] == 0) continue; if (stktable_data_types[dt].arg_type == ARG_T_DELAY) - chunk_appendf(msg, " %s(%d)=", stktable_data_types[dt].name, t->data_arg[dt].u); + chunk_appendf(msg, " %s(%u)=", stktable_data_types[dt].name, t->data_arg[dt].u); else chunk_appendf(msg, " %s=", stktable_data_types[dt].name); @@ -3628,10 +3628,10 @@ chunk_appendf(msg, "%u", stktable_data_cast(ptr, std_t_uint)); break; case STD_T_ULL: - chunk_appendf(msg, "%lld", stktable_data_cast(ptr, std_t_ull)); + chunk_appendf(msg, "%llu", stktable_data_cast(ptr, std_t_ull)); break; case STD_T_FRQP: - chunk_appendf(msg, "%d", + chunk_appendf(msg, "%u", read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp), t->data_arg[dt].u)); break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/stream.c new/haproxy-2.4.2+git0.553dee326/src/stream.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/stream.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/stream.c 2021-07-07 16:46:09.000000000 +0200 @@ -623,7 +623,7 @@ _HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess); } if (may_dequeue_tasks(objt_server(s->target), s->be)) - process_srv_queue(objt_server(s->target)); + process_srv_queue(objt_server(s->target), 0); } if (unlikely(s->srv_conn)) { @@ -1815,7 +1815,7 @@ } sess_change_server(s, NULL); if (may_dequeue_tasks(srv, s->be)) - process_srv_queue(srv); + process_srv_queue(srv, 0); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.4.1+git0.1ce7d4925/src/tcpcheck.c new/haproxy-2.4.2+git0.553dee326/src/tcpcheck.c --- old/haproxy-2.4.1+git0.1ce7d4925/src/tcpcheck.c 2021-06-17 09:06:08.000000000 +0200 +++ new/haproxy-2.4.2+git0.553dee326/src/tcpcheck.c 2021-07-07 16:46:09.000000000 +0200 @@ -937,6 +937,9 @@ cs += strlen("maxconn:"); TRACE_DEVEL("change server maxconn", CHK_EV_TCPCHK_EXP, check); + /* This is safe to call server_parse_maxconn_change_request + * because the server lock is held during the check. + */ msg = server_parse_maxconn_change_request(check->server, cs); if (!wrn || !*wrn) wrn = msg; @@ -3634,7 +3637,7 @@ if (next && next->action == TCPCHK_ACT_CONNECT) { LIST_DELETE(&chk->list); LIST_INSERT(&next->list, &chk->list); - chk->index = next->index; + chk->index = next->index + 1; } } @@ -3655,7 +3658,7 @@ goto out; } LIST_APPEND(px->tcpcheck_rules.list, &next->list); - next->index = chk->index; + next->index = chk->index + 1; } }